Skip to content

fix(review): title the pr-review-cli completion notice and count demoted CRITICAL findings - #865

Merged
kyle-sexton merged 1 commit into
mainfrom
fix/pr-review-cli-notice-title-job-names
Oct 23, 2026
Merged

kyle-sexton merged 1 commit into
mainfrom
fix/pr-review-cli-notice-title-job-names

Conversation

@kyle-sexton

Copy link
Copy Markdown
Member

Refs: melodic-software/claude-code-plugins#9307

Summary

Two pr-review-cli publish fixes that block claude-code-plugins#9307 from moving its security lane onto pr-review-cli:

  • The claude-lane-review-complete notice had no annotation title. pr-review.yml and pr-review-security.yml emit ::notice title=claude-lane-review-complete::, and babysit's evidence reader keeps only annotations with that title. Without it, every pr-review-cli review read as no-record.
  • When one bad anchor demotes the whole inline batch to the summary, the model's critical-findings: line still left those findings out. A demoted CRITICAL finding then counted as non-blocking.

Fix

  • publish.cjs: the three completion notices (whole or incremental review, skip=no-change, skip=docs-only) pass { title: "claude-lane-review-complete" }.
  • countedSummary: on a demoted batch, it adds the moved CRITICAL findings to the model's one critical-findings: line, changing that line in place. A finding counts as CRITICAL unless it has exactly one IMPORTANT or SUGGESTION severity: line, which is how the gate reads a thread. With no line, it adds one that counts every summary finding as CRITICAL. With two or more lines it leaves the text alone, because a gate already counts every finding then.

Not changed: the skipped jobs' names. When a pr-review-cli job is skipped, its ${{ inputs.lane ... }} name renders as the raw expression. Literal per-lane job names would emit a skipped wrong-lane check (pr-review-security / claude-review-status) on every run. babysit's AI_REVIEW_CHECKS matches claude-review-status on the last segment, so that check would hold every PR. Each reader treats a skipped AI review check the same as a missing one (babysit_merge.py ai_review_holds, merge.md lane()), so the raw name changes no gate.

Verification

  • node --test .github/scripts/publish-review.test.cjs: 17 pass. Three of the new tests fail on main: the title on all completion notices, a demoted CRITICAL count raised in place, and a line added when missing.
  • node --test .github/scripts/claude-lane-*.test.cjs .github/scripts/publish-review.test.cjs: 201 pass.

Related

  • Follow-ups, not in these lines: the inline comment footer is duplicated when the model writes its own, and the review-key leg skips a human-pushed head on a Dependabot-authored PR.

🤖 Generated with Claude Code

…ted CRITICAL findings

The completion notice now carries the annotation title
claude-lane-review-complete on every path, as pr-review.yml and
pr-review-security.yml emit it, so a merge gate that filters on the title
finds the record. When one bad anchor moves the whole inline batch to the
summary, the summary's critical-findings line now counts the moved
CRITICAL findings, and one is added when the model left it out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T04:53:10.186476Z 1f41a44 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 25s —— View job


Security review

Reviewed the three changed files against origin/main...HEAD (1f41a44).

publish.cjs

  • RECORD = { title: "claude-lane-review-complete" } passed as the core.notice annotation-properties argument (static string, no injection surface).
  • SEVERITY / CRITICAL_LINE regexes are anchored, linear (no nested quantifiers), and bounded (\d{1,6}, MAX_BODY=8000, MAX_SUMMARY=60000) — no ReDoS concern, and matchAll's spec-mandated regex clone means the shared g-flag regex objects don't leak lastIndex state across calls (.replace also resets lastIndex before use).
  • countedSummary's fallback paths (no existing critical-findings: line, or an anchor-problem's extra unitemized findings) are conservative — they add to the critical count rather than suppress it, so a parsing edge case fails toward holding the merge gate, not bypassing it.
  • comment.body / review.summary are always coerced through stripHtml's String(text ?? ""), so a malformed/non-string model field can't throw before the existing secret-scan gate (scan(findSecret, …)) runs over the final summary text — that gate still covers the new code path unchanged.
  • The second core.notice argument is new but additive; it doesn't change what's already scanned or posted.

pr-review-cli.yml: diff is comment-only (documents the new notice title and the demoted-count behavior); no job, trigger, permission, or run: changes.

publish-review.test.cjs: new tests only, no production logic.

No .claude-plugin manifest changes, and no deletion/narrowing of a standing instruction (CLAUDE.md/AGENTS.md/rules file) in this diff, so the instruction-surface-deletion and manifest-flag checks don't apply.

No security vulnerabilities found (logic flaws, auth/access-control gaps, injection, or credential handling). This is an internal CI-bookkeeping fix with no new trust-boundary or data-flow surface; GitHub Actions hardening concerns (triggers, permissions, pins) are unaffected and out of scope for this lane regardless.

critical-findings: 0

claude-lane-summary: lane=claude-security-review sha=1f41a44879912310dd405eca27aea18c6c575d6a run=39902588980

@claude

claude Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 4m 9s —— View job


Code review: pr-review-cli publish fixes

  • Gather context (diff, PR context, rules)
  • Resolve standards index / paved paths (no paved-path index row found; no plugin manifest touched)
  • Review publish.cjs changes
  • Review publish-review.test.cjs changes
  • Review pr-review-cli.yml changes
  • Check closing issue criteria (no PR-context file / closing issue to check)
  • Check path-scoped rules (.claude/rules/pr-body-contract.md — PR body opens with Refs: and has ## Summary/## Fix/## Verification/## Related: compliant)
  • Post findings

Summary

No blocking or high-signal findings.

Traced both fixes against the test suite by hand (the sandbox denies node --test execution in this lane, so I could not run it, only read it):

  • Notice title (publish.cjs lines 30-31, 355, 357, 473-475): all three claude-lane-review-complete notice sites (whole/incremental review, skip=no-change, skip=docs-only) now pass RECORD = { title: "claude-lane-review-complete" }. Grepped the file for every core.notice call carrying that record prefix — none were missed, and the unrelated shadow ... notices correctly stay untitled. This matches the title README.md already documented at L1312-1313, so the doc and code are now consistent.
  • countedSummary/isCritical (publish.cjs lines 166-190): placeComments is all-or-nothing (every comment anchors, or the whole batch is demoted), so unanchored.length is always either 0 or review.comments.length — the rest = findings - comments.length computation in the "line missing" branch is sound against that invariant. Manually recomputed all four new/changed test cases (publish-review.test.cjs lines 489-572) against the implementation and they check out: the in-place raise, the added line, and the two-lines-left-alone case all match what the regexes (SEVERITY, CRITICAL_LINE) produce.
  • pr-review-cli.yml's header comment update (lines 92-100) accurately describes both behavior changes; no functional workflow change in this file, consistent with the PR's own "not changed" note about job names.

Nothing in .github/actions/publish-review/publish.cjs or the workflow diff touches security-sensitive surfaces (secrets, permissions, trigger gating), so nothing here is withheld for the security lane either — there's simply nothing of that kind in this diff.

Author-claimed and unverified (I did not independently run these): the PR's own "17 pass" / "201 pass" node --test results.

claude-lane-summary: lane=claude-review sha=1f41a44879912310dd405eca27aea18c6c575d6a run=39902588980

@github-actions

Copy link
Copy Markdown

claude-security-review has reviewed this pull request through 1f41a44; a later push is reviewed from there.

@github-actions

Copy link
Copy Markdown

claude-review has reviewed this pull request through 1f41a44; a later push is reviewed from there.

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit 83b739f Oct 23, 2026
30 checks passed
@kyle-sexton
kyle-sexton deleted the fix/pr-review-cli-notice-title-job-names branch October 23, 2026 05:00
kyle-sexton added a commit to melodic-software/standards that referenced this pull request Oct 23, 2026
…contract (#849)

Refs: melodic-software/claude-code-plugins#9307

## Summary

Registers `pr-review-cli.yml@83b739f625b501ad40c65dee7168d836883195e1`
(ci-workflows
[v0.63.1](https://github.com/melodic-software/ci-workflows/releases/tag/v0.63.1))
so claude-code-plugins#9307 can re-pin its security lane to it.

## Fix

v0.63.1 changes only the publish step
([ci-workflows#865](melodic-software/ci-workflows#865):
titled completion notice, demoted CRITICAL findings counted). The
contract copies the v0.63.0 entry forward verbatim: same routing, inputs
and secrets.

## Verification

- `node --test runner-policy.test.mjs` in `components/runner-policy`:
337 pass, including the new copy-forward test.

## Related

- Same shape as #848 (v0.63.0).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant