---
title: Frontend PR Process
description: Human-facing guide for creating, reviewing, and merging pull
  requests against arda-frontend-app, including the Fast Gate and merge queue
  conventions.
editUrl: true
head: []
template: doc
sidebar:
  hidden: false
  attrs: {}
pagefind: true
draft: false
author: Arda Systems
copyright: (c) Arda Systems, All rights reserved
license: Please contact Arda Systems for licensing information
maturity: published
tags:
  - process
  - craft
  - deployment-and-release
  - frontend
  - pull-request
  - merge-queue
  - changelog
domain: process
source: documentation
comments: false
---

This guide explains how to create, review, and merge a pull request against `arda-frontend-app`. It is the **human companion** to the `pr-steward` agent skill — the mechanics described here are what the skill automates when it shepherds a PR.

For the design behind these conventions, see the [Phase 2 — Queued PRs and Tiered Gates](../../../roadmap/completed/frontend-pipeline/phase-2-queued-prs/index.md) roadmap entry.

## When this guide applies

Follow this process for every PR against `main` in `Arda-cards/arda-frontend-app`. The same conventions are implemented (with minor variations) in other Arda repositories that use the merge queue; this guide documents the frontend specifically.

## TL;DR

1. Branch from latest `main` as `<github-username>/<topic>`.
2. Make your change. Run `make ci` (or lint + tsc + jest + build) before pushing.
3. Open a PR. Fill out the `## CHANGELOG` section in the description (the template scaffolds it).
4. The Fast Gate runs (~5 min). Address any review comments and re-push.
5. Get at least one approving review.
6. Click "Merge when ready" → PR enters the merge queue.
7. Queue Gate runs (~10–15 min). On success the PR merges automatically.
8. Post-merge automation handles the rest (CHANGELOG assembly, version bump, GitHub Release, deploy).

## Step-by-step

### 1. Branch from latest `main`

Paths below assume the standard Arda workspace layout (the `arda/` workspace root with `arda-frontend-app/` as a sibling clone). Adjust to your local layout if different.

```bash
git -C <workspace>/arda-frontend-app fetch origin main
git -C <workspace>/arda-frontend-app checkout -b <username>/<topic> origin/main
```

For project work, prefer a worktree under `projects/<project-name>-worktrees/` rather than touching the main clone.

### 2. Make the change

Follow the repo conventions in [`arda-frontend-app/CLAUDE.md`](https://github.com/Arda-cards/arda-frontend-app/blob/main/CLAUDE.md). Notable rules:

- **Path alias** — `@/` maps to `src/`.
- **Authentication** — `useAuth()` from `src/store/hooks/useAuth.ts` is the authoritative auth hook. Legacy `AuthContext` is being phased out.
- **API client** — never call the ARDA backend directly from the browser. Use `src/lib/ardaClient.ts`, which routes through `src/app/api/arda/...`.
- **Mock mode** — `npm run dev:mock` (or `make dev-mock`) runs the app with MSW handlers. E2E tests always run in mock mode.

### 3. Pre-push gate

Run the full local check suite before every push, even for "trivial" changes. The frontend repo has a Makefile target that mirrors the Fast Gate:

```bash
cd <workspace>/arda-frontend-app
make check
```

Equivalent manual sequence:

```bash
npm run lint
npx tsc --noEmit
npx jest --no-coverage --watchAll=false --forceExit
npm run build
```

If you changed E2E specs, also run a relevant subset locally:

```bash
NEXT_PUBLIC_MOCK_MODE=true npm run test:e2e -- --grep "@sanity"
```

The pre-push rule applies to every push, not just the first one. Fix-up commits also need to clear the local gate before being pushed.

### 4. Open the PR

The repository's PR template scaffolds the structure. Fill in:

- **Summary** — what the PR does and why.
- **CHANGELOG** — the section the merge automation reads. See [CHANGELOG conventions](#changelog-conventions) below.
- **Closes** — `Closes #<issue>` lines for any issues this PR resolves.
- **Test Plan** — checklist of what you verified (or what should be verified post-merge).

PR title follows conventional commits: `<type>: <short description>` where type is one of `feat`, `fix`, `refactor`, `test`, `docs`, `chore`.

If you are an agent or contributing on someone's behalf, append the attribution block to the PR body and to every comment you post:

```markdown
> [!note]
> Authored by <Tool Name> for <github-username>
```

### 5. Watch the Fast Gate

| Required check | Typical time | What it does |
|---|---|---|
| `lint` | ~30s | ESLint |
| `build` | ~3 min | Next.js production build (includes typecheck) |
| `unit-tests-coverage` | ~3 min | Jest + coverage threshold enforcement |
| `changelog-check` | ~10s | Validates the `## CHANGELOG` section in the PR body |
| `e2e` | ~5s | Pass-through summary on PR — shards skip on `pull_request` |
| `quarantine-check` | ~5s | Validates `@quarantine` tags + budget |

If a check fails, fix the issue locally, re-run `make ci`, and push the fix. The Fast Gate reruns automatically. **Do not push to a branch that is already in the merge queue** — the push is rejected.

### 6. Review comments

Address every reviewer comment before approval. The conventions:

- **Code change** — make it locally, run `make ci`, push. Reply to the comment with the commit SHA: `Fixed in <sha> — <one-line summary>.`
- **Reply only** — explain the rationale.
- **Defer** — open a follow-up issue using `/gh-ticket` (or `gh issue create`) and reply with `Tracked in <ticket-url>.`
- **Ignore** — reply with the rationale.

Resolve every review thread once it has been addressed. The `pr-steward` skill automates this.

### 7. Approval and merge queue entry

The repository requires at least one approving review and no pending "request changes" review. Once approved:

```text
mergeStateStatus: BLOCKED  →  CLEAN
```

Click **"Merge when ready"** in the GitHub UI (or run `gh pr merge <num> --auto --squash`). The PR enters the merge queue.

### 8. Watch the Queue Gate

The Queue Gate runs against the rebased merge commit (`gh-readonly-queue/main/pr-<num>-<sha>`):

| Required check | Typical time | What it does |
|---|---|---|
| `lint`, `build`, `unit-tests-coverage` | ~5 min | Re-run on the rebased code (zero added wall time — finishes before E2E) |
| `changelog-check` | pass-through | Already validated on PR; passes through in queue |
| `e2e-sanity-{alpha,bravo}` | ~5–8 min | Sanity E2E shards |
| `e2e-acceptance-{alpha,bravo,charlie}` | ~10–15 min | Acceptance E2E shards |
| `quarantine-check` | ~5s | Quarantine tag + budget validation on the rebased commit |

#### Possible outcomes

- **Success** — PR merges automatically. Skip to [post-merge](#post-merge).
- **Bisection re-queue** — your PR was batched with others; the batch failed and GitHub bisected. The offending PR is removed and your PR re-enters the queue automatically. No action needed.
- **Ejection (your PR caused the failure)** — your PR is removed from the queue and reopened. Investigate the failure, fix it on a new push, re-approve if needed, and re-enter the queue.

### 9. Post-merge

Three workflows run automatically on `main` after the merge commit lands:

1. **Changelog Assembly** (`changelog-assembly.yaml`)
   - Extracts the `## CHANGELOG` entries from your PR description (or the last `## CHANGELOG` comment).
   - Computes the SemVer bump from `.github/clq/changemap.json`.
   - Updates `CHANGELOG.md`, `package.json`, `package-lock.json`.
   - Pushes a `[changelog-assembly]` commit using `CHANGELOG_ASSEMBLY_TOKEN` (a PAT, so the push triggers downstream workflows).
   - Runs CLQ validation.
   - Creates the GitHub Release.
2. **Deploy Frontend** (`deploy.yaml`) — triggered by the assembly's success via `workflow_run`.
   - Runs `source-info` → `deploy-dev` → `deploy-stage` in series.
   - In parallel, runs `quality-gate-build` → `quality-gate-{alpha,bravo}` (Extended E2E) → `quality-gate-evaluate`.
   - Also runs the non-blocking `quality-gate-quarantine` job.
   - `deploy-demo` and `deploy-prod` run after stage and a successful evaluate. **Prod requires environment-protection approval** in the GitHub UI before it actually deploys.
3. **Post-Merge: Changelog Assembly (skipped)** — the assembly's own commit re-enters the assembly workflow, which checks for the `[changelog-assembly]` marker and skips. This is the loop-prevention guard.

You do not need to do anything for steps 1 and 2 unless one of them fails (you will be tagged on the auto-created bug issue).

## CHANGELOG conventions

The PR description must include a `## CHANGELOG` section with at least one valid category:

```markdown
## CHANGELOG

### Added
- New search-by-tag feature for the items page.

### Fixed
- TC-NAV-004 sidebar toggle no longer hangs on slow connections.
```

### Valid categories

| Category | SemVer bump | Use for |
|---|---|---|
| `Added` | minor | New features |
| `Changed` | major | Intentional breaking changes to existing functionality |
| `Deprecated` | minor | Features marked for future removal |
| `Fixed` | patch | Bugfixes (most common) |
| `Removed` | major | Removed functionality |
| `Security` | patch | Vulnerability fixes |

Be deliberate about category choice — it directly determines the version bump. Internal-only changes belong under `Fixed`. Reserve `Changed` and `Removed` for real breaking changes.

### Amending

To amend the CHANGELOG after PR creation, post a comment with a new `## CHANGELOG` section. The last `## CHANGELOG` found in either the description or in author comments wins.

### Do not edit `CHANGELOG.md` directly

CI rejects PRs that modify `CHANGELOG.md` directly (the file is the assembly's output, not its input). The `changelog-check` job enforces this.

## Quarantining a flaky test

If a test fails intermittently and you need to ship the change anyway:

1. Open an issue describing the flake. Note the test path and a sample failure.
2. Tag the test title with `@quarantine(YYYY-MM-DD, #<issue>)`:
   ```ts
   test('TC-NAV-004 sidebar toggle @acceptance @quarantine(2026-05-04, #795)', ...);
   ```
3. The expiry date must be ≤ the budget's `maxExpiryDays` from today (default: 7).
4. The total quarantined count must be ≤ the budget's `maxQuarantined` (default: 5). If you would exceed it, fix or unquarantine an existing test first.
5. The `quarantine-check` action validates the tag on every PR.

The quarantined test is excluded from the merge gate but **still runs post-merge** in the non-blocking `quality-gate-quarantine` job — its outcome flows into the weekly flaky-test aggregation.

See [`knowledge-base/flaky-test-quarantine.md`](https://github.com/Arda-cards/arda-frontend-app/blob/main/knowledge-base/flaky-test-quarantine.md) for the full lifecycle.

## When things go wrong

| Symptom | What to do |
|---|---|
| `npm error 401 Unauthorized` for `@arda-cards/*` | The repo's `.npmrc` reads `_authToken=${GITHUB_TOKEN}`; locally export `GITHUB_TOKEN=$(gh auth token)` before `npm install`. In CI the workflow-level env is already set. |
| `mergeStateStatus: BLOCKED` | Likely missing approval, missing required check, or unresolved review thread. `gh pr view <num> --json reviewDecision,statusCheckRollup` to inspect. |
| Required check shows skipped on PR | The skipped variant is the queue-only path; the pass-through summary still reports green. |
| Push rejected with `branch is in merge queue` | Wait for the queue to finish. If the PR is ejected, push the fix to the now-reopened branch. |
| Changelog Assembly failed | Check that the PR's `## CHANGELOG` has at least one valid category; verify CLQ accepts the resulting version chain. |
| Deploy Frontend failed at `quality-gate-build` | Likely an `npm ci` failure (cold cache, missing token) or a workflow-level issue — see [Phase 2 design — `npm ci` auth](../../../roadmap/completed/frontend-pipeline/phase-2-queued-prs/design.md). |

## Appendix — agent companions

| Agent skill | Source | What it automates |
|---|---|---|
| `pr-steward` | `workspace/instructions/claude/skills/pr-steward/SKILL.md` | Steps 4–9 above. Watches checks, triages reviewer comments, replies and resolves threads, offers queue entry on explicit confirmation, monitors `merge_group` runs through to merge or ejection. |
| `pr-body-changelog` (knowledge base) | `arda-frontend-app/knowledge-base/pr-body-changelog.md` | Conventions for `## CHANGELOG` sections in the frontend repo. |

The skill never enters the merge queue or merges autonomously — both require an explicit affirmative response in the same session as the request.