- Mirror upstream #1786's nested-shell / executable-normalization hardening
into the fork-only pr_verdict_guard.py (verdict-gating is a real fork
control), keeping it in parity with pr_creation_guard.py.
- Close the glued short-flag bypass (bash -c'...') in BOTH guards: a shell's
-c argument can be concatenated into the same argv token, which the
space-separated -c detection missed. Diverges pr_creation_guard.py from
upstream #1786 by design; to be upstreamed.
- Gate the new #1799 sidebar active-thread refresh on ownership so a non-owner
viewing a shared thread reads last-known state without persisting a metadata
write (mirrors the is_owner gate on the single-thread read path).
- Fix an F821 in the #1799 cherry-pick (Mapping import / concrete dict type).
Guards remain intentionally fail-open per the honest-agent threat model;
docstrings narrowed to name the residual exotic-shell / stdin-fed vectors.
* feat(reviewer): explicit-request verdicts + shell verdict guard
Mention-triggered reviews that explicitly ask for a verdict now submit a
real APPROVE/REQUEST_CHANGES through publish_review; auto-reviews stay
advisory (COMMENT). Authorization is enforced in code: publish_review
honors a verdict only when the dispatching webhook set verdict_requested,
which only the explicit-mention path does.
- request_pr_review gains instructions (forwarded verbatim into an escaped
requester_instructions data block) and request_verdict
- self-review guard downgrades verdicts on Open SWE-authored PRs; stale
APPROVEs are best-effort dismissed when later findings land
- new PullRequestVerdictGuardMiddleware blocks gh pr review
--approve/-a/--request-changes/-r, gh api, and curl verdict fallbacks on
both the coding-agent and reviewer graphs
- shared escape helper moved to agent/utils/prompt_data.py
* fix(reviewer): harden verdict path against security-review findings
Adversarial security review (detector fan-out + proof-or-kill verifier)
of the verdict feature surfaced several verdict-integrity gaps; resolve
the confirmed ones:
- head-drift (high): a mid-run push moves the resolved head, so an APPROVE
could anchor to an unreviewed commit. Downgrade any verdict to a comment
when the resolved head differs from the reviewed head (verdict_ignored
reason head_moved); the push's own re-review submits a fresh verdict.
- self-review fail-open: downgrade to comment when the PR author cannot be
confirmed (author_unknown), and compare bot logins case-insensitively.
- verdict_submitted now reflects GitHub's returned review state, not just
the event we asked for, so a coerced APPROVE isn't reported as submitted.
- an authorized verdict whose findings all anchor outside the diff now
posts as a bodied review with zero inline comments instead of failing.
- add finding_reply to the shared data-block escape tag superset.