diff --git a/.github/labels.yml b/.github/labels.yml index 237c1233..b316634c 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -117,6 +117,14 @@ description: Trigger Claude Code automation color: "b41d8f" +- name: claude:review:passed + description: Automated Claude PR review found no blocking issues on the current head commit + color: "0e8a16" + +- name: claude:review:failed + description: Automated Claude PR review found blocking issues on the current head commit + color: "b60205" + - name: copilot description: GitHub Copilot related color: "e6dac6" diff --git a/.github/workflows/claude-code-automation-pr-review.yml b/.github/workflows/claude-code-automation-pr-review.yml index 55d5f592..dfbeb2bb 100644 --- a/.github/workflows/claude-code-automation-pr-review.yml +++ b/.github/workflows/claude-code-automation-pr-review.yml @@ -214,6 +214,49 @@ jobs: Use `gh pr comment` with your Bash tool to leave your comprehensive review as a comment on the PR. + ## Machine-Readable Verdict (MANDATORY) + + After posting your review comment, you MUST emit a single-label verdict on the PR. This label is consumed by branch-protection rules to gate auto-merge — it is the only deterministic signal of your review outcome. + + **Verdict criteria** (all must hold for PASS): + + - No blocking findings under "CRITICAL CHECKS" — i.e. no missing test markers, no coverage drop below 85%, no `make lint` failures, no conventional-commit violations. + - No blocking architecture or security violations under "Repository-Specific Review Areas". + - Suggestions / nice-to-haves do NOT block the verdict. + + If any blocking finding remains: verdict is **FAIL**. + Otherwise: verdict is **PASS**. + + **Apply the label** (the two labels are mutually exclusive — always remove the opposite one): + + ```bash + # PASS: + gh pr edit ${{ github.event.pull_request.number }} \ + --add-label "claude:review:passed" \ + --remove-label "claude:review:failed" + + # FAIL: + gh pr edit ${{ github.event.pull_request.number }} \ + --add-label "claude:review:failed" \ + --remove-label "claude:review:passed" + ``` + + Note: `--remove-label` is a no-op if the label is not present, so it is safe to always include it. + + Also include the verdict as the final line of your sticky review comment, formatted exactly as: + + ``` + **Verdict**: ✅ claude:review:passed + ``` + + or + + ``` + **Verdict**: ❌ claude:review:failed + ``` + + This makes the verdict visible to humans without scrolling through all findings. + --- **Remember**: This is medical device software. Insist on highest standards. Be thorough, actionable, and kind. diff --git a/pyproject.toml b/pyproject.toml index 28d48a28..c1ed2d37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -138,6 +138,7 @@ dependencies = [ "lxml>=6.1.0", # CVE-2026-41066 (Renovate #556); also required for python 3.14 pre-built wheels "filelock>=3.20.3", # CVE-2025-68146 (>=3.20.1); CVE-2026-22701 (>=3.20.3, Renovate #387) "marshmallow>=3.26.2", # CVE-2025-68480 + "pygments>=2.20.0", # CVE-2026-4539 (>=2.20.0); transitive via rich "cryptography>=46.0.7", # CVE-2026-39892 (>=46.0.7); transitive via pyjwt[crypto] "pydicom>=3.0.2", # CVE-2026-32711 (>=3.0.2); transitive via dicomweb-client/wsidicom/highdicom "pyasn1>=0.6.3", # CVE-2026-30922 (>=0.6.3); transitive via cryptography diff --git a/uv.lock b/uv.lock index 5ee497cd..a0f806f6 100644 --- a/uv.lock +++ b/uv.lock @@ -69,6 +69,7 @@ dependencies = [ { name = "pyasn1" }, { name = "pydantic-settings" }, { name = "pydicom" }, + { name = "pygments" }, { name = "pyjwt", extra = ["crypto"] }, { name = "python-dateutil" }, { name = "python-multipart" }, @@ -215,6 +216,7 @@ requires-dist = [ { name = "pyasn1", specifier = ">=0.6.3" }, { name = "pydantic-settings", specifier = ">=2.12.0,<3" }, { name = "pydicom", specifier = ">=3.0.2" }, + { name = "pygments", specifier = ">=2.20.0" }, { name = "pyinstaller", marker = "extra == 'pyinstaller'", specifier = ">=6.14.0,<7" }, { name = "pyjwt", extras = ["crypto"], specifier = ">=2.12.0,<3" }, { name = "python-dateutil", specifier = ">=2.9.0.post0,<3" },