pr · diff
git:20260702.d9d795b to git:20260717.e2c9d88
58 added, 204 removed. Audit B to B.
---
- description: Creates or updates a pull request (GitHub) or merge request (GitLab) for the current branch using the Conventional PR format — intent, summary, changes, rationale, and test plan. Captures the implementation conversation's intent into the PR description when run in the same conversation. Use when a branch is ready for review, or to update an existing PR/MR description.
+ description: Creates or updates a pull request (GitHub) or merge request (GitLab) for the current branch in the Conventional PR format — intent, summary, changes, rationale, and test plan. Pushes the branch if needed (asks before any force-push) and captures the implementation conversation's intent into the PR description. Use when a feature branch is ready for review or to refresh an existing PR/MR description.
disable-model-invocation: true
---
# Pull Request / Merge Request
- Create or update a PR (GitHub) or MR (GitLab) for the current branch using the Conventional PR format. Detects the hosting platform, checks for an existing PR/MR, and either creates a new one or offers to update the existing one. New PRs target the repository's default branch; updates to existing PRs use the PR's current target branch. PRs/MRs are created as ready to merge (not draft).
+ This skill never commits working-tree changes — it only pushes existing commits and manages the PR/MR.
## Step 1: Pre-flight
- Read `$CLAUDE_PLUGIN_ROOT/skills/init/references/multi-repo-detection.md` for workspace detection. If a multi-repo workspace is detected, run the multi-repo selection procedure below. Otherwise, skip to **Verify git state**.
-
- ### Multi-repo selection
+ If the current directory has no `.git/` directory, read `$CLAUDE_PLUGIN_ROOT/skills/init/references/multi-repo-detection.md` and apply it. In a detected workspace:
- 1. For each child repo, check:
- - Current branch: `git -C <repo-path> rev-parse --abbrev-ref HEAD`
- - Default branch: use the algorithm from `$CLAUDE_PLUGIN_ROOT/skills/pr/references/default-branch-detection.md` (run inside the repo)
- - Whether it has commits ahead of default: `git -C <repo-path> log --oneline origin/<default-branch>..HEAD 2>/dev/null | head -1`
- 2. If default branch detection fails for a repo, warn the user (e.g., "Could not detect default branch for `<repo>` — skipping") and exclude it from the candidates list
- 3. Filter to repos that are on a non-default branch AND have commits ahead of the default branch
- 4. If **no repos** have changes → inform the user: "No repositories in this workspace have branches with changes ready for a PR." Stop.
- 5. If **one repo** has changes → inform the user which repo was detected and proceed to run Steps 2–8 inside that repo's directory
- 6. If **multiple repos** have changes → present the list and use `AskUserQuestion` — header "Multi-Repo PRs", question "Multiple repositories have changes ready for PRs:". Options:
- - **All** — "Create PRs for all repos with changes (one at a time)"
- - Each individual repo name — "Create PR for `<repo>` only"
- 7. If the user selects a specific repo, proceed to run Steps 2–8 inside that repo's directory
- 8. If the user selects **All**, process each repo with changes through Steps 2–8 sequentially. For each repo: run all commands inside that repo's directory, complete Steps 2–7 fully (including the per-repo report in Step 7), then **continue to the next repo**. After the last repo, show the combined summary from Step 8. In an **All** run, any per-repo stop condition in Steps 2–7 (unknown platform, CLI cancel, Update-Flow Cancel, etc.) stops only that repo — record the outcome for the Step 8 summary and continue with the next repo; only the Step 1 gates halt the whole run
+ - Filter to child repos on a non-default branch with commits ahead of the default branch (detect the default branch per `$CLAUDE_PLUGIN_ROOT/skills/pr/references/default-branch-detection.md`, run inside each repo). Warn and skip any repo whose default branch cannot be detected.
+ - 0 candidates → "No repositories in this workspace have branches with changes ready for a PR." Stop. 1 → announce which repo was detected and run Steps 2–7 inside it. Multiple → ask (AskUserQuestion): **All** or one specific repo.
+ - **All** → run Steps 2–7 per repo sequentially (show a `## <repo-name>` heading before Step 2; run all commands inside that repo). Any per-repo stop condition (unknown platform, CLI cancel, update-flow Cancel, …) stops only that repo — record the outcome for the Step 8 summary and continue with the next. Only the gates below halt the whole run.
- ### Verify git state
+ **Verify git state** (stop gates):
- 1. Confirm the current directory is inside a git repository: `git rev-parse --is-inside-work-tree`. If not → inform the user and stop.
- 2. Get the current branch: `git rev-parse --abbrev-ref HEAD`.
- 3. Check that the current branch is not the default branch. Detect the default branch using the algorithm in `$CLAUDE_PLUGIN_ROOT/skills/pr/references/default-branch-detection.md`. If no default branch can be determined → inform the user: "Could not detect the default branch. Ensure `origin` is configured and has been fetched." Stop. If on the default branch → inform the user: "You're on the default branch (`<branch>`). Switch to a feature branch first." Stop.
+ 1. Not inside a git repository → inform the user and stop.
+ 2. Default-branch detection (reference above) fails → "Could not detect the default branch. Ensure `origin` is configured and has been fetched." Stop.
+ 3. On the default branch → "You're on the default branch (`<branch>`). Switch to a feature branch first." Stop.
## Step 2: Platform Detection
- When processing multiple repos, show a heading (e.g., `## repo-name`) before starting this step for each repo.
-
- Read `$CLAUDE_PLUGIN_ROOT/skills/pr/references/platform-detection.md` and use the **Platform Detection Algorithm** section. If platform is unknown → inform the user that the hosting platform could not be determined and stop.
+ Read `$CLAUDE_PLUGIN_ROOT/skills/pr/references/platform-detection.md` and apply the **Platform Detection Algorithm**. Unknown platform → inform the user and stop.
## Step 3: CLI Availability
- Read `$CLAUDE_PLUGIN_ROOT/skills/pr/references/platform-detection.md` and use the **CLI Verification** section to check availability and authentication. If the CLI is not installed, use the **CLI Installation** section — offer to install via `AskUserQuestion` (header "Install CLI", question "The [GitHub CLI (`gh`) / GitLab CLI (`glab`)] is required but not installed. Install it now?"):
- - **Install** — "Install automatically (requires [package manager])"
- - **Cancel** — "I'll install it manually"
-
- If the user chooses **Cancel** → provide manual installation instructions and stop.
- If installation fails → provide manual installation instructions and stop.
- If installed but auth fails → inform the user: "CLI installed. Run `[gh/glab] auth login` to authenticate, then re-run `/optimus:pr`." Stop.
-
- ## Step 4: Branch and Existing PR/MR Check
-
- ### Push branch if needed
-
- Check if the branch has been pushed: `git ls-remote --heads origin <branch> 2>/dev/null`
+ Apply the reference's **CLI Verification** section. If the CLI is missing, offer to install it per its **CLI Installation** section (ask: **Install** / **Cancel**). On Cancel or install failure → provide manual installation instructions and stop. Installed but unauthenticated → "Run `gh/glab auth login` to authenticate, then re-run `/optimus:pr`." Stop.
- If the branch is not on the remote:
- 1. Check for commits: `git log --oneline HEAD --not --remotes 2>/dev/null | head -1`. If no commits → inform the user: "No commits on this branch yet. Commit your changes first." Stop.
- 2. Push: `git push -u origin <branch>`
+ ## Step 4: Push and Existing PR/MR Check
- If the branch is on the remote but has unpushed commits (`git log origin/<branch>..HEAD --oneline`), check for divergence first: `git rev-list --count HEAD..origin/<branch>`
+ If the branch is not on the remote (`git ls-remote --heads origin <branch>`): with no commits on the branch → "No commits on this branch yet. Commit your changes first." Stop. Otherwise `git push -u origin <branch>`.
- - Count is `0` → fast-forward push: `git push origin <branch>`
- - Count is greater than `0` → the remote has commits not in local history (typical after a local rebase); a plain push would be rejected as non-fast-forward. Do NOT plain-push. Use `AskUserQuestion` — header "Diverged branch", question "The remote branch has commits not in your local history (e.g., pre-rebase commits). Overwrite it?":
- - **Force push** — "Run `git push --force-with-lease origin <branch>`"
- - **Cancel** — "I'll reconcile the branch manually"
+ If the branch is on the remote with unpushed commits, check divergence first: `git rev-list --count HEAD..origin/<branch>`
- If the user chooses **Force push** → run `git push --force-with-lease origin <branch>`. If the lease is rejected → inform the user: "Force push rejected — the remote gained new commits since your last fetch. Review them before overwriting." Stop.
- If the user chooses **Cancel** → inform the user to reconcile the branch and push manually, then re-run `/optimus:pr`. Stop.
+ - Count `0` → fast-forward push: `git push origin <branch>`
+ - Count `> 0` → the remote has commits not in local history (typical after a rebase). NEVER plain-push. Ask (AskUserQuestion "Diverged branch"): **Force push** → run `git push --force-with-lease origin <branch>`; if the lease is rejected → "Force push rejected — the remote gained new commits since your last fetch. Review them before overwriting." Stop. **Cancel** → tell the user to reconcile and push manually, then re-run `/optimus:pr`. Stop.
- ### Check for existing PR/MR
+ Check for an existing PR/MR:
- **GitHub:** `gh pr view --json number,state,title,body,url,baseRefName 2>/dev/null`
- - If a PR exists and is **open** → save the `baseRefName` as the PR's **target branch**, then go to Step 6 (Update Flow)
- - If a PR exists but is **closed/merged** → treat as no PR (create a new one)
- - If no PR exists → go to Step 5 (Create Flow)
-
- **GitLab:** `glab mr view --output json 2>/dev/null`
- - If an MR exists and is **opened** → save the `target_branch` from the JSON as the MR's **target branch**, then go to Step 6 (Update Flow)
- - If an MR exists but is **closed/merged** → treat as no MR
- - If no MR exists → go to Step 5 (Create Flow)
- ## Step 5: Create Flow
-
- ### Detect default branch
-
- - **GitHub:** `gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'`. If this differs from Step 1's local detection, the API value is authoritative for this step's diffs (the local `origin/HEAD` ref may be stale).
- - **GitLab:** use the default branch detected in Step 1, or `git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'`
-
- ### Gather change data
-
- Collect information about the changes on the branch:
-
- ```bash
- # Commit list
- git log --oneline origin/<default-branch>..HEAD
+ Open PR/MR → save its `baseRefName` / `target_branch` as the **target branch** and go to Step 6 (Update Flow). Closed/merged or none → Step 5 (Create Flow).
- # Changed files summary
- git diff --stat origin/<default-branch>..HEAD
+ ## Step 5: Create Flow
- # Full diff for analysis
- git diff origin/<default-branch>..HEAD
- ```
+ Default branch: on GitHub, `gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'` is authoritative over Step 1's local detection (local `origin/HEAD` may be stale); on GitLab, use Step 1's detection.
- If there are no commits ahead of the default branch → inform the user: "This branch has no changes compared to `<default-branch>`." Stop.
+ Gather the branch's commits and diff vs `origin/<default-branch>`. No commits ahead → "This branch has no changes compared to `<default-branch>`." Stop.
### Detect intent context
- Before generating PR content, determine whether author intent is recoverable. This classification drives whether the `## Intent` section is populated, preserved, prompted for, or omitted. Classify into one of three states:
-
- 1. **Intent available from conversation** — the current conversation contains implementation context for this branch. Signals:
- - Prior Edit / Write / NotebookEdit tool calls in the conversation touched files that appear in `git diff --stat origin/<default-branch>..HEAD`.
- - The conversation discussed design decisions, non-goals, trade-offs, or "decided against" language relative to the changes.
- - The conversation explicitly stated the problem being solved or the scope of the change.
- - **TDD handoff (special case of state 1).** When the conversation contains a `## TDD Summary` block from `/optimus:tdd` Step 9 — detected by the literal headings `## TDD Summary` and `### Behaviors Implemented` (case-sensitive) above the diff, optionally with a `### Coverage` section containing `Before:`, `After:`, and `Delta:` lines — treat this as a strong state-1 signal and apply the summary population rule below when filling the PR body.
- - **Workflow handoff (special case of state 1).** When the conversation contains a `## Implementation Summary` block from `/optimus:workflow` Step 6 — detected by the literal headings `## Implementation Summary` and `### Components Built` (case-sensitive) above the diff, optionally with a `### Coverage` section containing `Before:`, `After:`, and `Delta:` lines — treat this as a strong state-1 signal and apply the summary population rule below when filling the PR body.
- 2. **Intent available from existing PR body** (Update Flow only — Step 6) — the existing PR body contains an `## Intent` section. Detection: see `$CLAUDE_PLUGIN_ROOT/skills/pr/references/pr-template.md` "Detecting `## Intent` in an existing PR body" for the canonical heuristic (shared with `/optimus:code-review`).
- 3. **No intent context found** — neither of the above. Default classification when in doubt: if the heuristic is uncertain, prefer state 3 over fabricating an Intent section.
-
- State 3 handling — use `AskUserQuestion` — header "Intent capture", question "No implementation context detected for this branch. How would you like to handle the `## Intent` section?":
- - **Add intent now** — Claude will ask the user to reply with Problem / Scope / Non-goals / Key decisions on separate lines (blank lines skip the sub-field) in a plain message exchange, then populate the section from the reply.
- - **Skip** — omit the section entirely. Do not stub it. For the strongest downstream review on a future run, re-run `/optimus:pr` from the conversation where the implementation happened.
-
- Suppress this prompt entirely in state 1 or state 2 (no friction on the happy paths).
-
- ### Generate PR content
-
- Read the Conventional PR template: `$CLAUDE_PLUGIN_ROOT/skills/pr/references/pr-template.md`
-
- Generate a title and body following the template. When filling in the sections:
- - Populate the **`## Intent`** section based on the classification above (state 2 only applies in the Update Flow — Step 6 handles it):
- - State 1 (conversation context) → populate Problem / Scope / Non-goals / Key decisions from the conversation. Use only what the conversation actually answered; omit a sub-field if it has no clear answer.
- - State 3 with "Add intent now" → populate from the user's reply to the plain-message follow-up.
- - State 3 with "Skip" → omit the section entirely (no stub, no placeholder).
- - **Never infer Intent from commit messages or the diff alone.** A fabricated Intent section creates false `Intent Mismatch` findings in `/optimus:code-review`.
- - **Summary population rule** — when a TDD or Workflow handoff signal fired during intent detection, populate the body from the summary block visible in the conversation. Both handoffs share one rule; only these per-source tokens differ:
-
- | Handoff | Summary block | Table | Non-goals rows | Key decisions source |
- |---------|---------------|-------|----------------|----------------------|
- | TDD | `## TDD Summary` | `### Behaviors Implemented` | Status `Not started` | refactor-step reasoning captured in the conversation (e.g. "renamed X to match existing pattern", "extracted Y to share with Z") |
- | Workflow | `## Implementation Summary` | `### Components Built` | Status begins with `Deferred` (include the stated reason) | the `### Stats` `Orchestration` line plus any design choices the summary surfaced (e.g. "fanned out by component, then one integration pass") |
-
- Using the row for whichever handoff fired, fill the PR body:
- - **`## Intent` → Scope**: one bullet per **Table** row where Status is `✓ Complete`, using the description column verbatim.
- - **`## Intent` → Non-goals**: one bullet per **Table** row whose Status matches the **Non-goals rows** column above. Omit the sub-field if no such rows exist.
- - **`## Intent` → Key decisions**: pull from the **Key decisions source** above. If none are present (e.g. every TDD refactor step reported "No changes needed — code is clean"), omit this sub-field rather than inventing decisions.
- - **`## Intent` → Problem**: quote/summarize the spec or JIRA task file if it was loaded in the conversation, otherwise summarize the initiating brief from the start of the conversation.
- - **`## Test plan`**: one verification item per **Table** row that is `✓ Complete`, plus the project's test command. If the conversation contains a `### Coverage` section with `Before:`, `After:`, `Delta:` lines, append a single line `Coverage: <Before> → <After> (<Delta>)` to the Test plan.
- - Synthesize the **Summary** from commit messages, changed files, and the diff
- - Use `git diff --stat` output as a starting point for **Changes**, then describe what each file change accomplishes
- - For the **Test plan**, look for: test files in the diff → "Run `<test command>` to verify"; CI configuration → "CI pipeline will run automatically"; manual verification → describe what to check
-
- ### Preview and confirm
+ Classify into one of three states before generating content:
- Present the generated title and body to the user (in a multi-repo workspace, include the repo name in the header):
+ 1. **Conversation context** — this conversation implemented the branch: Edit/Write/NotebookEdit calls touched files in the diff, or the conversation discussed the problem, design decisions, or non-goals. A `## TDD Summary` block with `### Behaviors Implemented` (literal, case-sensitive — emitted by `/optimus:tdd`) is a strong state-1 signal; apply the population rule below.
+ 2. **Existing PR body has `## Intent`** (Update Flow only — see the detection rule in the template).
+ 3. **None** — when uncertain, prefer this state over fabricating. Ask (AskUserQuestion "Intent capture"): **Add intent now** → have the user reply with Problem / Scope / Non-goals / Key decisions on separate lines in a plain message (blank lines skip a sub-field); **Skip** → omit the section entirely, no stub.
- ```
- ## PR Preview [— repo-name]
+ Suppress the state-3 prompt in states 1 and 2. **Never infer Intent from commit messages or the diff alone** — a fabricated Intent creates false `Intent Mismatch` findings in `/optimus:code-review`.
- **Title:** <title>
+ ### Generate content
- ---
+ Read `$CLAUDE_PLUGIN_ROOT/skills/pr/references/pr-template.md` and generate a title and body. Populate `## Intent` from the conversation (state 1) or the user's reply (state 3), including only sub-fields the source actually answers.
- <body>
- ```
+ **TDD Summary population rule** — when the handoff signal fired, fill the body from the summary block:
- Use `AskUserQuestion` — header "PR preview", question "Review the PR/MR title and description above. Proceed or adjust?":
- - **Create PR** — "Looks good — create the PR/MR"
- - **Adjust** — "I want to modify the title or description"
+ - **Intent → Scope**: one bullet per `### Behaviors Implemented` row with Status `✓ Complete`, description verbatim.
+ - **Intent → Non-goals**: one bullet per `Not started` row; omit if none.
+ - **Intent → Key decisions**: refactor-step reasoning captured in the conversation; omit rather than invent.
+ - **Intent → Problem**: quote/summarize the spec or JIRA task file loaded in the conversation, else the initiating brief.
+ - **Test plan**: one verification item per `✓ Complete` row plus the project's test command; if a `### Coverage` section with `Before:` / `After:` / `Delta:` lines is present, append one line `Coverage: <Before> → <After> (<Delta>)`.
- If the user chooses **Adjust**, ask what to change, apply modifications, and preview again.
+ ### Preview, confirm, create
- ### Create PR/MR
+ Show the generated title and body under `## PR Preview` (append `— <repo-name>` in a multi-repo run). Ask (AskUserQuestion): **Create PR** → proceed; **Adjust** → ask what to change, apply, and preview again.
- Write the body to a temp file in the current working directory: `TMPFILE=$(mktemp ./pr-body-XXXXXX.md)`. Clean up after the creation attempt: `rm -f "$TMPFILE"`. (Use a relative path, not `/tmp` — on Windows, Git Bash's `/tmp` mount is unresolvable by the native `gh.exe`/`glab.exe`, which would silently submit an empty body.)
+ Write the body to a temp file at a relative path: `TMPFILE=$(mktemp ./pr-body-XXXXXX.md)` — never `/tmp` (on Windows, Git Bash's `/tmp` is unresolvable by native `gh.exe`/`glab.exe`, which would silently submit an empty body). Remove it with `rm -f "$TMPFILE"` after the attempt.
- **GitHub:** `gh pr create --title "<title>" --body-file "$TMPFILE" --base <default-branch>`
- **GitLab:** `glab mr create --title "<title>" --description "$(cat "$TMPFILE")" --target-branch <default-branch>`
- Proceed to Step 7.
+ PRs/MRs are created ready to merge (not draft). Proceed to Step 7.
## Step 6: Update Flow
- ### Show current PR/MR
-
- Display the current title and body to the user:
-
- ```
- ## Existing PR/MR
-
- **#<number>:** <title>
- **URL:** <url>
-
- ---
-
- <current body>
- ```
-
- ### Ask what to update
-
- Use `AskUserQuestion` — header "Update PR", question "A PR/MR already exists for this branch. What would you like to do?":
- - **Regenerate title and description** — "Regenerate both using the Conventional PR format based on current branch changes. Existing `## Intent` is preserved verbatim."
- - **Regenerate description only** — "Keep the current title, regenerate the description. Existing `## Intent` is preserved verbatim."
- - **Regenerate Intent only** — "Replace just the `## Intent` section (or add one if missing). Use when the implementation scope has changed and the existing Intent is stale. Keeps title, Summary, Changes, and Test plan untouched unless they explicitly contradict the new Intent."
- - **Cancel** — "Keep the current PR/MR as-is"
-
- If the user chooses **Cancel** → report the existing PR/MR URL and stop.
-
- If the user chooses **Regenerate Intent only** → re-detect intent context but treat state 2 (existing PR Intent) as *replaceable* — the user explicitly asked to regenerate it. Populate the new `## Intent` from the highest available signal: state 1 (conversation context) when present, otherwise prompt the user directly for Problem / Scope / Non-goals / Key decisions via a plain-message reply (do NOT re-emit the state-3 "How would you like to handle Intent?" meta-prompt — the user has already opted in). If the user provides no reply or all sub-fields are blank, leave the existing Intent unchanged, report "No replacement Intent provided — existing `## Intent` kept as-is. No changes will be made.", and stop (do not enter Phase 3). Otherwise replace the `## Intent` section in the existing body with the freshly populated one (or insert it before `## Summary` if missing). Skip Phase 1 (do not regenerate other sections) and Phase 2 (no preservation pass needed). Jump to Phase 3 (preview).
-
- ### Regenerate content
-
- #### Phase 1 — Generate fresh content
-
- Gather change data using the existing PR/MR's **target branch** (saved in Step 4) as the base for diffs — use it in place of `<default-branch>` in the `git log`, `git diff --stat`, and `git diff` commands from Step 5. Generate new content following the Conventional PR template. This is the authoritative content. Do not present yet.
-
- #### Phase 2 — Scan existing content for non-diff information
-
- Review the existing PR/MR title and body (saved from Step 4) for information that **cannot be derived from code changes**. Examples: issue/ticket references (`#45`, `JIRA-123`), deployment instructions, external links, reviewer-directed notes, follow-up tasks, and the `## Intent` section.
-
- **Never preserve facts that are derivable from the current diff** — version numbers, file counts, function/class/symbol names, path names, line counts, or changed-file lists. These must come from Phase 1's fresh content. If the existing body contains such a fact (for example, "plugin version incremented from 1.56.1 to 1.59.0"), discard the old value and use the one re-derived from the current diff, even if the old value was correct when the PR was first opened. Rebases and force-pushes can change any of these, so the description must always match what reviewers see in "Files changed".
-
- Discard anything that is outdated, factually wrong based on current diffs, or already covered by the freshly generated content. If useful non-diff information is found:
+ Show the existing PR/MR (number, title, URL, current body), then ask (AskUserQuestion "Update PR"):
- 1. **`## Intent` section (load-bearing handoff to `/optimus:code-review`)** — if the existing body has an `## Intent` section, **always preserve it verbatim** and re-insert it at the top of the new body (before `## Summary`), matching the template's section order. This is the most critical preservation in the Update Flow: a fresh-conversation update run (no implementation context — e.g., refreshing the PR after a rebase) has no way to recover the original intent, so a silent overwrite would destroy the only record. **Never silently overwrite an existing `## Intent` section** with a fresh inference from commits/diff. If both an existing `## Intent` AND a populated conversation context exist, the existing section wins by default; surface a one-line note in the Phase 3 preview — *"Existing `## Intent` section preserved. The current conversation suggests possible updates — choose 'Regenerate Intent only' if you want to revise."* — and continue.
- 2. **Standard sections**: Integrate at a natural position within the matching section of the new content (e.g., issue references in Summary, manual verification steps in Test plan).
- 3. **Non-standard sections**: If the existing body has sections outside the four standard ones (e.g., `## Deployment notes`, `## Related issues`) that contain non-diff information still relevant, preserve them after `## Test plan`.
- 4. **Title**: Only when regenerating the title — if the existing title contains an issue reference or similar non-diff context, incorporate it into the new title while keeping Conventional Commit format.
+ - **Regenerate title and description** — existing `## Intent` preserved verbatim.
+ - **Regenerate description only** — keep the title; existing `## Intent` preserved verbatim.
+ - **Regenerate Intent only** — replace just the `## Intent` section (or add one if missing); everything else untouched.
+ - **Cancel** — report the existing URL and stop.
- **Friction floor for the standalone-update flow:** if the existing body has an `## Intent` section AND the conversation has no implementation context (no Edit/Write/NotebookEdit touching the current diff), the regeneration must succeed **without any intent-related prompting** — the Phase 3 preview/confirm still runs. The user came here to fix the description after a rebase, not to re-litigate intent.
+ **Regenerate Intent only:** re-detect intent context, treating the existing PR Intent as replaceable (the user opted in). Use conversation context when present; otherwise prompt directly for Problem / Scope / Non-goals / Key decisions in a plain reply (not the state-3 meta-prompt). Empty reply or all sub-fields blank → keep the existing Intent, report "No replacement Intent provided — existing `## Intent` kept as-is. No changes will be made." and stop (do not enter Phase 3). Otherwise replace `## Intent` in place (or insert it before `## Summary`), skip Phases 1–2, and jump to Phase 3.
- #### Phase 3 — Preview
+ **Phase 1 — fresh content.** Gather commits and diff against the PR's saved **target branch** (not the repo default) and generate new content from the template. This is the authoritative content; do not present yet.
- Present the final content for preview. If any non-diff information was carried over from the existing PR/MR, add a brief note above the preview: "Note: some manually-added content from the existing PR/MR was carried over (issue references, deployment notes, etc.)."
+ **Phase 2 — preservation scan.** Review the existing title and body for information that cannot be derived from the code changes:
- Use `AskUserQuestion` — header "Update preview", question "Review the updated PR/MR. Proceed or adjust?":
- - **Update** — "Apply changes to the PR/MR"
- - **Adjust** — "I want to modify before updating"
+ - **`## Intent`** — always preserve verbatim and re-insert before `## Summary`. Never silently overwrite it with fresh inference. If conversation context also exists, the existing section still wins; add a note to the Phase 3 preview: "Existing `## Intent` section preserved. The current conversation suggests possible updates — choose 'Regenerate Intent only' if you want to revise."
+ - Keep other non-diff information — issue/ticket references, deployment instructions, external links, reviewer notes, follow-ups — integrated into the matching section. Still-relevant non-standard sections go after `## Test plan`. When regenerating the title, carry issue references into the new title.
+ - **Never preserve diff-derivable facts** (version numbers, counts, symbol/path/file names) — always re-derive them from the current diff; rebases and force-pushes can change them. Discard anything outdated, wrong, or already covered by the fresh content.
+ - **Friction floor:** when the existing body has `## Intent` and the conversation has no implementation context, the update must complete without any intent-related prompting — only the Phase 3 preview runs.
- ### Apply update
+ **Phase 3 — preview.** If non-diff content was carried over, note it briefly above the preview. Ask (AskUserQuestion): **Update** → proceed; **Adjust** → apply changes and preview again.
- Write the body to a temp file (same pattern as Step 5). Clean up after the update attempt.
+ Apply using the Step 5 temp-file pattern:
- - **GitHub:** `gh pr edit <number> --title "<title>" --body-file "$TMPFILE"` (or `--body-file` only if keeping the title)
+ - **GitHub:** `gh pr edit <number> --title "<title>" --body-file "$TMPFILE"` (omit `--title` when keeping the title)
- **GitLab:** `glab mr update <number> --title "<title>" --description "$(cat "$TMPFILE")"`
- Proceed to Step 7.
-
## Step 7: Per-Repo Report
```
## PR/MR [Created / Updated] [— repo-name]
- - URL: [PR/MR URL]
+ - URL: [url]
- Title: [title]
- Target: [target-branch]
- Status: Ready to merge
```
- If processing multiple repos, **continue to the next repo** — go back to Step 2 for the next repo in the list. Do NOT show next-step recommendations or the fresh-conversation tip until all repos are done. After the last repo (or if processing a single repo), proceed to Step 8.
+ In a multi-repo run, continue with the next repo (back to Step 2); hold all recommendations until every repo is done.
## Step 8: Final Summary
- In a multi-repo workspace where multiple repos were processed, show a combined summary across all repos:
-
- ```
- ## All PRs/MRs Processed
-
- | Repo | PR/MR | Status | URL |
- |------|-------|--------|-----|
- | `repo-name` | title | Created / Updated / Skipped (reason) | URL |
- ```
-
- Recommend running `/optimus:code-review` for quality review before merging.
+ After a multi-repo run, show a combined table: Repo | PR/MR | Status (Created / Updated / Skipped (reason)) | URL.
- Tell the user the closing tip per `$CLAUDE_PLUGIN_ROOT/references/skill-handoff.md` "Closing tip wording" — use **Variant C** (default — `/optimus:code-review` is non-continuation).
+ Recommend `/optimus:code-review` in a fresh conversation for a quality review before merging — it gathers its own context from the PR description.