---
name: prepare-commit-pr
description: Prepare a clean commit and PR for the yeshuman monorepo — working tree review, changelog, branch hygiene, smoke checks, then push and open the PR with gh (and surface Railway check URLs when possible). Use when the user asks to prep a PR, ship a branch, or avoid committing local-only trees.
---

# Prepare commit / PR / push (yeshuman)

## Default outcome

**Goal:** get from a messy or ready branch to an **open GitHub PR**, with checks run first.

**Bias:** after prep steps succeed, **push the branch** (if needed) and **`gh pr create`** on behalf of the user. Only **stop and ask** when something needs human judgment (see [When to pause for the user](#when-to-pause-for-the-user)).

## When to use

Before staging and pushing: large cleanups, doc moves, multi-area feature branches, or any change where `git status` is noisy or risky.

## Steps

### 1. Working tree — no accidental bulk commits

- Run `git status` and scan **untracked** and **deleted** paths.
- For large directories you **do not** want in the PR (local experiments, vendored upstream trees), either **move them outside the repo** or add a **`.gitignore`** entry (team preference). Confirm they no longer appear in `git status` before `git add`.
- Prefer **explicit** `git add <paths>` over `git add -A` when the tree is mixed.

### 2. Docs match the code

- After file removals, search for dead references: e.g. `rg 'mcp_client\\.py'` on `README.md`, `AGENTS.md`, and `docs/` (ignore backend identifiers like `client_name='mcp_client'`).
- Root [README.md](../../../README.md) should describe **HTTP/SSE MCP** only unless a stdio bridge is reintroduced.
- [AGENTS.md](../../../AGENTS.md) stays the canonical dev/runbook pointer for agents.

### 3. Changelog

- If the change is user-visible or structural, update [CHANGELOG.md](../../../CHANGELOG.md) under **`[Unreleased]`** so **Removed** / **Changed** / **Added** match what the PR actually does.

### 4. Branch hygiene

- Avoid stacking unrelated commits on **`master`** when it is already ahead of `origin`. Create a branch, e.g. `chore/short-description`, commit there, open the PR against the default branch.
- If **`master`** moved after you branched (e.g. another PR merged), **rebase**: `git fetch origin && git rebase origin/master` then `git push --force-with-lease`. Sync local default with `git checkout master && git reset --hard origin/master` when appropriate.
- With a **dirty** working tree, **`git stash`** (or commit) before `checkout` / `reset` so Git does not abort.
- **Default branch:** this repo uses **`master`** (`gh repo view --json defaultBranchRef`). For forks, confirm with `gh repo view`.

### 5. Smoke checks

**API** (from [AGENTS.md](../../../AGENTS.md)) when `api/` is in scope:

```bash
cd api && uv run python manage.py check
cd api && uv run pytest --import-mode=importlib -q --maxfail=1
```

Use a broader pytest run before merge if you touched core app code. A full `pytest` run may fail on unrelated tests (e.g. import drift in another app); fix or exclude those before relying on CI parity.

**Labs** (`labs/`) when the frontend is in scope — run **both**:

```bash
cd labs && pnpm type-check
cd labs && pnpm build
```

- **`pnpm type-check`** (`tsc --noEmit`) — fast type-only check.
- **`pnpm build`** (`tsc -b && vite build`) — **production-shaped** gate; catches Vite bundling and build-time issues that type-check alone can miss (closer to Railway / static deploys).

### 6. PR title and body

- **Title** — short, imperative, scope-clear (e.g. `feat: thread file assets and Labs threads UX`).
- **Body** — summary, risk/deploy notes (migrations, env vars), verification commands, follow-ups.
- Optional: write or reuse a root **`PR_NOTES.md`** for a paste-ready description; then pass it to `gh` with **`--body-file PR_NOTES.md`** (do not commit that file unless the team wants it on the default branch).

### 7. Infer primary client (for Railway / review focus)

Use a **best-effort primary client** so you know which **`gh pr checks`** rows and Railway services matter most. Signals (first match wins or combine):

| Signal | Example |
|--------|---------|
| Branch name | `feat/talentco-…`, `lumie/…` |
| **Touched paths** | `labs/client-config.json` + grep for tenant keys; `api/client-config.json` under a client key; docs named for a tenant |
| **Commit / PR scope** | Majority of files under client-specific dirs or config blocks |

Known client handles (see [AGENTS.md](../../../AGENTS.md) and [railway-pr-deploy-triage](../railway-pr-deploy-triage/SKILL.md)): e.g. `yeshuman`, `bookedai`, `talentco`, `lumie`, `recruitrtech`, `lortsmith`. If **several** clients change equally, list them in the PR body and in check output — do not guess a single “main” client without stating that it is ambiguous.

### 8. Push and create the PR (`gh`)

**Preconditions:** meaningful commits exist, working tree is clean **or** any remaining changes are intentionally out of scope (e.g. local `.cursor/settings.json` untracked).

1. **Push** (set upstream if missing):

   ```bash
   git push -u origin HEAD
   ```

   If push is rejected after a rebase: `git push --force-with-lease` only when appropriate; if unsure, **pause for the user**.

2. **Create the PR** (default: open against **`master`**):

   ```bash
   gh pr create --base master --title "…" --body-file PR_NOTES.md
   ```

   If there is no `PR_NOTES.md`, use **`--body`** with a concise markdown string, or **`gh pr create --fill`** only when commit messages alone are enough (usually prefer an explicit body for multi-area PRs).

3. **Capture the PR number / URL:**

   ```bash
   gh pr view --json number,url
   ```

### 9. Railway deploys and preview URLs (`gh` first)

**Do not invent** preview hostnames. After the PR exists and checks start:

1. List checks (from repo root; add `--repo owner/repo` if not the default remote):

   ```bash
   gh pr checks <PR_NUMBER>
   ```

   Or JSON for tooling:

   ```bash
   gh pr checks <PR_NUMBER> --json name,state,link,bucket
   ```

   Field **`link`** is usually the **details URL** for that check (often a Railway deployment deep link for this monorepo’s Railway status checks).

2. **Interpretation:** each row’s **`link`** (per [railway-pr-deploy-triage](../railway-pr-deploy-triage/SKILL.md)) points at the **Railway deployment** (or check run) for that service (e.g. `talentco - talentco-ui`). Open it to see logs and, once deploy completes, the **public / preview domain** (e.g. from `RAILWAY_PUBLIC_DOMAIN` in the service). Do not guess the hostname in chat. For failing checks, follow the triage skill (`railway logs`, auth via [railway-cli-local-auth](../railway-cli-local-auth/SKILL.md)).

3. **Optional CLI:** after auth, `railway` may show deployment URLs for a linked project/service — still prefer **`gh pr checks`** for PR-scoped, check-aligned links.

4. **Summarize for the user:** PR URL, inferred **primary client** (if any), and **pending or passing** check names for `<client>-api` / `<client>-ui`, with links from `gh pr checks`. If checks are still **queued**, say so explicitly.

### 10. New files under `.cursor/skills/`

This repo **gitignores** `.cursor/skills/` but **tracks** individual skills via **`git add -f .cursor/skills/<name>/SKILL.md`**. Without `-f`, `git add` will skip them.

## When to pause for the user

- **Uncommitted** work they may want in the PR, or **unclear** scope (multiple unrelated features in one branch without confirmation).
- **`gh auth`** not configured or wrong account; **`git push`** rejected and force-push is risky.
- **Fork** workflow: base repo or `upstream` differs; confirm `--repo` and base branch.
- **Sensitive** files in `git status` (secrets, local env) — never stage.
- User asked for **draft only** or **no PR** — use `gh pr create --draft` or stop after push.

## Verify

```bash
git status
rg 'mcp_client\.py' README.md AGENTS.md docs/ 2>/dev/null || true
# When Labs changed:
cd labs && pnpm type-check && pnpm build
# When API changed:
cd api && uv run python manage.py check
# After push + PR:
gh pr view --json number,url
gh pr checks <PR_NUMBER>
```
