--- name: pr description: Create a pull request with CVE details and strategy justification. --- # PR Phase ## Your Role Create a pull request that clearly documents the CVE fix, including what strategies were attempted and why, so reviewers have full context. ## Prerequisites - `validation-results.md` must show a passing verdict (run `/validate` first) - `pr-description.md` must exist with draft PR body (written by `/patch`) - `patch-log.md` must exist with strategy justification - `context.md` must exist with CVE details - Changes must be in the working tree or in the validated candidate revision recorded under **Candidate Build** in `context.md` If validation hasn't passed, tell the user to run `/validate` first. A draft PR created solely for the candidate build handoff in `downstream-verification.md` is a submission within `/validate`; it does not satisfy or bypass this phase's passing-validation prerequisite. ## Process ### Step 1: Pre-flight Checks 1. Confirm `validation-results.md` records passing validation for the current checkout, source revision/snapshot, selected CVE/package scope and versions, build references, and required platforms. Missing, incomplete, or outdated candidate validation returns to `/validate`; changed selected build inputs or platform requirements return to `/patch` first. Use the recorded validation result without repeating registry, advisory, or certification lookups. A passing scan alone cannot substitute for the complete validation verdict. Verify changes are limited to dependency manifests/lock files and the toolchain, builder, package-build, release-pipeline, or CI references recorded in the patch log. Report unrelated edits rather than staging them. 2. Verify the current branch is not `main` or `master` - If on a protected branch, create a feature branch first 3. Confirm the intended PR base branch with the user (e.g., `main`, `release-x.y`) - Do not rely on the repository default branch implicitly 4. Confirm the checkout and branch are the user-selected execution target. Do not require or compare a report-derived repository identity. Jira components and image suffixes are informational hints and do not determine the PR scope. ### Step 2: Check for Existing PRs Before creating a new PR, check whether an existing open PR already addresses any CVE or package in the explicitly selected patch scope. If the user selected multiple CVE/package entries for this checkout, the duplicate check must cover the complete scope rather than only a representative ticket. Derive the unique `(CVE, package)` pairs from the current context and patch log, run the duplicate search for each pair (or use an equivalent query that covers all pairs), then combine matches by normalized PR URL before deciding whether to stop. Never expand the scope from a repository name, Jira component, image hint, or report grouping alone. Run `../scripts/check_existing_prs.py` if available: ```bash # Repeat for every unique (CVE_ID, package) pair in the selected bundle. python3 ../scripts/check_existing_prs.py {repo_full} {target_base_branch} {CVE_ID} {package} ``` If the script is not available, search manually: ```bash # Repeat each search for every unique CVE and package in the selected bundle. gh pr list --state open --base {target_base_branch} --search "{CVE_ID}" gh pr list --state open --base {target_base_branch} --search "{package}" ``` When multiple searches identify the same PR, report it only once and retain all matching CVE/package pairs as evidence. Apply the strongest matching action below across the complete bundle: stop for an `exact_cve` or `bot_update`, warn for `same_package`, and continue only when no search produces a match, with one bounded exception: a candidate-build PR recorded in this context may be reused after its repository, head branch/SHA, confirmed base, and complete selected CVE/package scope match the validated candidate. Verify those values through the host; do not trust the recorded URL alone. Reuse that PR instead of treating it as a new duplicate. During `/validate` resubmission, the remote head must match the previously recorded candidate SHA before pushing a reviewed successor to the same confirmed branch/base/scope; invalidate old results and record the new SHA after submission. All other matches retain the normal actions below; do not suppress a separate conflicting PR. **Interpret the result:** | Match Type | Action | |------------|--------| | `exact_cve` | Stop. Report the existing PR URL. Recommend the user check if it already covers this fix. | | `bot_update` | Stop. Report the Dependabot/Renovate PR. Recommend reviewing it instead of creating a duplicate. | | `same_package` | Warn: another PR already bumps this package (possibly for a different CVE). Ask the user whether to proceed or defer to the existing PR. | | `none` | No duplicates found — continue to Step 3. | If an existing PR is found, record it in `context.md` under a "Related PRs" section so the `/close` phase can reference it. When the work came from `/cve-fix:report`, use only the CVE/package entries explicitly selected for the current checkout. Keep compatible selected patches together in one PR when the user requests a collective scope. Work in another checkout requires a separate branch and PR; do not infer that scope from a repository name, Jira component, or image hint. ### Step 3: Create Feature Branch If not already on a feature branch: ```bash git checkout -b cve-fix/{context} ``` Branch naming: - Single CVE from Jira: `cve-fix/{ISSUE_KEY}` (e.g., `cve-fix/EDM-1234`) - CVE ID only: `cve-fix/{CVE-ID}` (e.g., `cve-fix/CVE-2024-1234`) - Multiple CVEs: `cve-fix/{context}` (e.g., `cve-fix/security-updates-2024-03`) ### Step 4: Self-Review Gate Before committing, run a self-review of the dependency changes to catch issues before they reach external reviewers. Read and follow `../../_shared/recipes/self-review-gate.md` with these parameters: | Parameter | Value | |-----------|-------| | DIFF_COMMAND | `git diff HEAD` | | MAX_ROUNDS | `2` | | CONTEXT_FILES | `.artifacts/cve-fix/{context}/context.md`, `.artifacts/cve-fix/{context}/patch-log.md` (if they exist) | For an already committed candidate, set DIFF_COMMAND to `git diff {target-base-branch}...HEAD` so the review covers its committed patch, and include `git diff HEAD` if further working-tree changes exist. Any self-review fixes to a validated candidate require new candidate validation before proceeding. If the gate reports FLAG (unfixed CRITICAL or HIGH findings), stop and present the findings to the user. Do not proceed until the user decides how to handle them. If the gate reports PASS, proceed. If the gate made code fixes, stage them explicitly before continuing: ```bash git add {fixed files} ``` ### Step 5: Stage and Commit If the candidate is already committed and validated at the current HEAD, verify there are no additional source/build-input changes and reuse that commit; do not require an empty follow-up commit. If the source or inputs changed, return to `/validate` for the updated candidate before completing `/pr`. For a patch not yet committed, stage dependency-related files (plus any gate fixes already staged above): | Ecosystem | Files to Stage | |---|---| | Go | `go.mod`, `go.sum` | | Node.js | `package.json`, `package-lock.json` / `yarn.lock` / `pnpm-lock.yaml` | | Python | `requirements.txt` / `pyproject.toml` / `poetry.lock` / `uv.lock` | | Rust | `Cargo.toml`, `Cargo.lock` | | Ruby | `Gemfile`, `Gemfile.lock` | | Java (Maven) | `pom.xml` | | Java (Gradle) | `build.gradle` / `build.gradle.kts`, `gradle.lockfile` | Explicitly stage the toolchain and build/release reference changes listed in the patch log as well, using the product's actual build configuration. Examples include Containerfiles/Dockerfiles, package build requirements, and CI pipelines; none of these file types is mandatory for every product. If post-patch commands generated additional dependency changes (e.g., vendor files), review and include those too. Inspect the staged diff against the validated scope before committing. The optional `create_pr.py` helper's preflight only permits its ecosystem file list and does not enforce downstream verification. When build-reference changes are needed, use the manual staging/commit/publish steps here after completing this gate; do not omit required files to make the helper pass. Commit message format: ```text {ISSUE_KEY}: patch {CVE-ID} by updating {package} to {version} Resolves {CVE-ID} ({severity}) in {package}. Updated {package} from {old_version} to {new_version} via {strategy}. ``` For multiple CVEs: ```text {ISSUE_KEY}: patch {n} CVEs in dependency updates Resolves: - {CVE-ID-1} ({severity}) in {package-1} - {CVE-ID-2} ({severity}) in {package-2} See PR body for strategy details. ``` ### Step 6: Review PR Description The `/patch` phase already wrote `.artifacts/cve-fix/{context}/pr-description.md`. Refresh its **Downstream Verification** table and Validation section from the matching final `validation-results.md` before creating or updating the PR. Replace provisional/pending statements with the actual results; do not append contradictory summaries. Carry forward `/patch`'s input approval evidence without repeating availability research. Include the validated candidate identity, build run, actual compiler/input identities, binary/CVE checks, and required platform coverage. Preserve failures or missing results as blockers rather than filling in the success example below. Read the complete refreshed description and confirm it matches the candidate being published. ```markdown ### Validation - Candidate: {source SHA/snapshot digest} - Build: {run ID/link, or local build record} - Dependencies: Updated to fixed versions - Downstream inputs: {approved identities and actual compiler/provenance checks} - Artifacts and platforms: {binary checks and required coverage results} - CVE resolution: {fixed scan verdicts or documented equivalent evidence} - Tests: All passing ({n} tests, 0 failures) ``` ### Step 7: Push and Create PR ```bash git push -u origin cve-fix/{context} ``` If **Candidate Build** records a matching draft PR, update that PR's body from `pr-description.md` refreshed in Step 6 instead of creating another PR. Record its URL under **Main PR** as shown below and keep it draft. Otherwise create the PR: ```bash gh pr create \ --title "{ISSUE_KEY}: patch {CVE-ID(s)} in {repository}" \ --base {target-base-branch} \ --body-file .artifacts/cve-fix/{context}/pr-description.md \ --draft ``` Capture the PR URL from the `gh pr create` output and append it to `.artifacts/cve-fix/{context}/context.md`: ```markdown ## Main PR - URL: {pr_url} - Branch: cve-fix/{context} - Base: {target-base-branch} ``` If `gh` is not available, provide the branch name and PR body to the user for manual creation. Ask them to provide the PR URL so it can be recorded. ### Step 8: Report Report to the user: - PR URL - Summary of what was fixed - Any manual steps needed (e.g., review generated code changes) ## When This Phase Is Done Report the PR URL and a brief summary. Then re-read `controller.md` for next-step guidance.