---
name: pr
description: Use when opening or updating PRs for the active feature — handles multi-repo dependency order, quality gates, and PR descriptions
---

# /pr - Create or Update PRs (Humand Tech Plugin)

Run quality checks, push branches, and create (or update) pull requests across all repos in the feature.

## Plugin-first adaptation

```bash
eval "$(bash "${CLAUDE_SKILL_DIR}/../../scripts/workflow-setup.sh" <workspace_root>)"
```

- Use `$REPOS_FILE`, `$LOCAL_CONFIG_FILE`, `$TEAMS_FILE` from `workflow-setup.sh`.
- Feature resolution: see `docs/feature-resolution.md`.

After running `workflow-setup.sh`, if `LOCAL_CONFIG_FILE` is empty, use **AskUserQuestion** before proceeding:

```
⚠️ No local-config.json found — I can't resolve repo paths without it.

[1] Run /initial-setup now (takes ~2 min, only needed once)
[2] Skip and continue anyway (some steps may fail)
```

If the user chooses **[1]**: invoke `/initial-setup` and stop this skill.  
If the user chooses **[2]**: continue, substituting `$LOCAL_CONFIG_FILE` references with best-effort guesses or skipping repo-dependent steps gracefully.

## Superpowers-first hooks

- Use `verification-before-completion` before reporting PR creation success.
- Use `systematic-debugging` if CI/gate fails.

## Feature Resolution

See `docs/feature-resolution.md` for the full algorithm. Summary: use session context if clear; otherwise resolve from `git branch --show-current` in CWD + `git worktree list --porcelain` per repo in `$LOCAL_CONFIG_FILE`.

This skill accepts an optional branch argument (example: `/pr feat/SQSH-1234-foo`) to override CWD detection.

Read `$REPOS_FILE` for lint commands, labels, PR base branch, and other repo settings.

## Workflow

### 1. Load Context

Run the Feature Resolution algorithm above. The result gives you the active repos and their paths, and the branch name.

If no repo is found on a non-base branch: stop and tell the user to run `/start` first or check out the feature branch manually.

Extract ticket key from the branch name (e.g. `feat/SQSH-1672-desc` → `SQSH-1672`). If ticket metadata (title, description) is needed for the PR body, fetch from Jira MCP at invocation time using the extracted key.

### 2. Multi-repo: choose scope (if feature has 2+ repos)

If the feature resolution yields **more than one repo**, ask before opening/updating PRs:  
"This feature has N repos (e.g. humand-web, material-hu, …). Open/update PRs in all of them or only in one?"  
If the user chooses **only one**, list repos and ask which one (or accept repo name in reply).  
If they choose **all**, proceed with every repo.  
If the feature has **exactly one repo**, skip this question.

### 3. Commit & Push (Single Gate Path)

Check for uncommitted changes:

```bash
cd <repo_path>
git status --porcelain
```

If **any repo has uncommitted changes**, run the `/commit` skill to stage, commit, run the mandatory pre-push gate, and push. Once `/commit` completes, continue with step 4.

If all repos are clean but some have unpushed commits, run the pre-push gate here (once) and then push:

1. **Ensure runtime is valid for Node/npm repos.** For repos using `npm`/`pnpm`, use `check-runtime.sh`; it attempts `nvm use` only when mismatch is detected.
2. **Ensure checks can run.** If `path` is a worktree and dependencies are missing, install via:
   - `bash "$PLUGIN_ROOT/scripts/check-runtime.sh" <repo_path> -- npm install` (npm repos)
   - `bash "$PLUGIN_ROOT/scripts/check-runtime.sh" <repo_path> -- pnpm install` (pnpm repos)
3. Run configured `lint_cmd` and `type_check_cmd` from `$REPOS_FILE` (for npm/pnpm repos, run through `check-runtime.sh -- bash -lc "<cmd>"`).
4. If checks fail due to branch-introduced issues, do not push until fixed.
5. If failures are pre-existing on base, call it out and proceed.

Then push:

```bash
cd <repo_path>
git push -u origin <branch_name>
```

Then continue with step 4.

### 4. Gather PR Info (Single Prompt)

Show changed files and ask all questions in ONE message:

```
Files changed in this PR:
  humand-web: src/components/Profile.tsx, src/pages/profile/index.tsx, ...
  material-hu: src/components/Avatar/Avatar.tsx

Please answer:

1. PR Title:
   Format: [TICKET] Module1 | Module2 | Short description
   [1] {auto-suggest}
   [2] Enter custom title

2. Summary (1-3 bullet points describing the high-level change):
   [1] {auto-suggest based on commits and diffs}
   [2] Enter custom summary

3. Test Plan (checklist of how to verify the change):
   [1] {auto-suggest test scenarios}
   [2] Enter custom test plan

4. Labels (comma-separated numbers, or "none"):
   {list labels from each repo's pr_labels in $REPOS_FILE}

Example: "1, 1, 1, none" or "2, 2, 2, 1,2"
```

#### Summary Section Structure

The `## Summary` section in every PR body has three parts:

1. **Bullet points** — 1-3 high-level sentences describing the change (from question 2)
2. **`### What Changed`** — a markdown table listing every changed file and a short description of what changed in it. Auto-generate this from the diff; do not ask the user.
3. **`### Test Plan`** — a checklist of steps to verify the change (from question 3). Use `- [ ]` checkboxes.

Example:

```markdown
## Summary
- Replaced custom swipe animation with design system skeleton component
- Affects Feed and Groups multimedia carousels

### What Changed

| File | Change |
|------|--------|
| `src/components/attachment/MediaCarousel.tsx` | Swapped `LoadingPlaceHolder` for `HuSkeleton` with `aspectRatio: 16/9` |

### Test Plan
- [ ] Open Feed with posts containing images — verify skeleton shows before media renders
- [ ] Confirm no left-to-right swipe animation appears anymore
```

#### PR Title Format

Titles follow the pattern: `[TICKET] Module1 | Module2 | Short description`

- The ticket prefix goes in brackets: `[SQSH-1234]`
- Affected modules/areas are pipe-separated: `Web | Groups | Leave group`
- If no ticket, omit the bracket prefix: `Web | Fix postMessage origin validation`

Examples:

- `[SQPD-2759] Service Management | Enable service report download`
- `[SQSH-3151] Web | Groups | Leave group`
- `[SQRN-1234] Profile | Avatar | Fix rounded edge`

When auto-suggesting, infer modules from the changed file paths (e.g., `src/pages/dashboard/marketplace/` → `Marketplace`).

### Parsing User Response

- Accept answers separated by commas or on multiple lines
- For numbered options: use suggestion if user picks "1"
- For labels: accept comma-separated numbers or "none"
- Do NOT ask for confirmation - proceed directly

### 5. Create PRs in Dependency Order

Create PRs in dependency order (upstream first) as defined by `dependency_order` in `$REPOS_FILE`.

For each repo:

1. Read `pr_base` from `$REPOS_FILE`. **Always use `pr_base` as the PR target — never target a release or staging branch directly.** If a repo's `pr_labels` includes `hot fix` or `stg fix`, that means a GitHub automation handles backporting to release branches via labels; PRs must still target `pr_base` (usually `develop`).
2. Read the repo's `.github/pull_request_template.md` to know the **exact sections** expected
3. Fill in the template sections with the gathered PR info

**IMPORTANT:** Each repo has its own PR template. Always read it and follow its structure exactly for all existing sections.

Allowed normalized additions for consistency across repos:

- `### What Changed` (file/change table)
- `### Test Plan` (checkbox list)
- `## Related PRs` (only when multi-repo feature)

Injection rules:

1. If the template already contains one of these sections, fill that section in place.
2. If `## Summary` exists but `### What Changed` and/or `### Test Plan` are missing, inject missing ones **inside Summary** after summary bullets.
3. If `## Summary` does not exist, append missing normalized sections at the end of the body.
4. For multi-repo features, append `## Related PRs` at the end only if it does not already exist.

#### Creating the PR

```bash
cd <repo_path>
gh pr create \
  --title "[TICKET] Module1 | Module2 | Short description" \
  --body "$(cat <<'EOF'
{filled template matching the repo's .github/pull_request_template.md}
EOF
)" \
  --base <pr_base> \
  --assignee @me
```

When filling in template sections:

- **Summary bullet points**: Use the user-provided or auto-suggested summary (1-3 bullets)
- **What Changed table**: Auto-generate from the diff. List each changed file with a concise description of what changed. Use the `| File | Change |` markdown table format. Group trivially related files into one row if appropriate (e.g. a component + its styles). Inject if missing per rules above.
- **Test Plan**: Use the user-provided or auto-suggested test plan as `- [ ]` checkboxes. Inject if missing per rules above.
- **Screenshots/GIFs/Videos**: Write `N/A` (user can add them in GitHub)
- **Jira Card**: `[TICKET](https://humand.atlassian.net/browse/TICKET)` — omit section content if no ticket
- **Checklist** (mobile): Leave checkboxes unchecked for the author to fill
- **Related PRs**: For multi-repo features, append at end if missing; if already present in template, fill in place

If labels were requested, add them:

```bash
gh pr edit <PR_NUMBER> --add-label "<label_name>"
```

### 6. hu-translations PR

Note: branches are already pushed by `/commit`. The `git push` below is only needed if hu-translations was not part of the original `/commit` run.

If hu-translations resolves to a non-base branch via feature resolution and has branch changes to publish (committed or already pushed), push and create PR using the hu-translations repo template (same rule as every repo: read `.github/pull_request_template.md` and fill its exact sections):

```bash
cd <hu_translations_path>
git push -u origin <branch_name>
gh pr create \
  --base <pr_base> \
  --title "[TICKET] Add translations" \
  --body "$(cat <<'EOF'
{filled hu-translations template}
EOF
)" \
  --assignee @me
```

### 7. Upgrade hu-translations in Dependent Repos

Run `npm upgrade hu-translations` in every repo in the feature that has `has_translations: true` in `$REPOS_FILE` **only when the hu-translations change is already mergeable as a dependency update**:

- Run the upgrade when the hu-translations branch is merged (or the updated package/version is already available to consume).
- Do **not** run the upgrade while the hu-translations PR is still open/draft and not yet consumable.

When upgrade is deferred:

- Leave dependent repos without the lockfile bump for now.
- Add a PR comment noting that `hu-translations` upgrade will be pushed in a follow-up commit after merge/publish.
- After merge/publish, run `npm upgrade hu-translations`, commit, push, and update the existing PR(s).

### 8. Cross-Link PRs

After all PRs are created, add comments linking related PRs:

```bash
gh pr comment <pr_number> --repo <owner/repo> --body "$(cat <<'EOF'
Related PRs for this feature:
- humand-main-api: <url>
- material-hu: <url>
- humand-web: <url>

EOF
)"
```

### 9. Summary & Chaining

Show the PR summary:

```
PRs created:

humand-main-api:
  https://github.com/HumandDev/humand-main-api/pull/123
  Base: develop <- feat/SQRN-1234-add-user-profile

material-hu:
  https://github.com/HumandDev/material-hu/pull/456
  Base: main <- feat/SQRN-1234-add-user-profile

humand-web:
  https://github.com/HumandDev/humand-web/pull/789
  Base: develop <- feat/SQRN-1234-add-user-profile

All PRs:
  Assigned to you
  Cross-linked with related PRs
  Include ticket reference
```

Then offer `/merge-watch`:

- **Single PR:** `Would you like me to run /merge-watch to auto-merge PR #789 when CI passes?`
- **Multiple PRs:** List the PRs and ask: `Would you like me to run /merge-watch on these PRs? I'll start with the first one.`

If the user accepts, immediately invoke `/merge-watch` for the first (or only) PR. If they decline, stop.

## Updating Existing PRs

If PRs already exist (from a previous /pr):

1. Push new commits (no need to create new PR)
2. Optionally update PR description
3. Add comment about new changes

## Error Handling

- If push fails (rejected): Suggest rebase or force push (with confirmation)
- If PR creation fails: Show error, try to continue with other repos
- If gh CLI not authenticated: Prompt to run `gh auth login`
- If `$LOCAL_CONFIG_FILE` is missing: Tell user to copy from `local-config.example.json` into `$CONFIG_HOME`

## Notes

- `/pr` invokes `/commit` automatically if uncommitted changes exist — no need to run `/commit` first
- Pushing is handled by `/commit`; `/pr` only ensures branches are pushed if somehow missed
- PRs are created in dependency order to allow proper linking
- All PRs are assigned to @me (current GitHub user)
- Cross-linking helps reviewers understand the full scope
- For multiline PR comments, use HEREDOC bodies to avoid literal `\n` rendering in GitHub
- Lint/type checks are mandatory but can be bypassed with confirmation
- If no ticket, leave the Jira Card link empty or omit the section content
- PR title format: `[TICKET] Module1 | Module2 | Short description` — omit bracket prefix if no ticket
- PR body must follow the repo's `.github/pull_request_template.md` structure — do not use a generic template
