ci(github-action): update action https://github.com/misospace/pr-reviewer-action (v3.4.1 ➔ v3.7.0) #2407

Merged
GiorgioAresu merged 1 commit from renovate/https-github.com-misospace-pr-reviewer-action-3.x into main 2026-10-23 09:48:37 +02:00
Collaborator

This PR contains the following updates:

Package Type Update Change
https://github.com/misospace/pr-reviewer-action action minor v3.4.1 → v3.7.0

⚠️ Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


Release Notes

misospace/pr-reviewer-action (https://github.com/misospace/pr-reviewer-action)

v3.7.0

Compare Source

3.7.0 is about the verdict being real. Until now, review_verdict could reach approve and still publish a non-blocking comment, the only judge of a finished review was the model that wrote it, and what happened to a finding after publication was invisible. This release publishes the verdict it reached (plus a new blockers-only mode), adds an opt-in independent scorer that grades completed reviews, and exports a finding-outcome contract so operators can measure what actually happens to findings. Around that: a credential-redaction wave closes every remaining path where someone else's secret could ride to disk, and the self-hosted controller gains repository acquisition, GitHub App auth, and its first Tangled publish record.

If you publish verdicts or want the scorer, this is the release to pin:

- uses: misospace/pr-reviewer-action@v3
  with:
    publish-mode: review_verdict   # an 'approve' verdict now publishes a real approval
- uses: misospace/pr-reviewer-action@v3
  with:
    ai-confidence-model: ${{ vars.CONFIDENCE_MODEL }}       # empty (default) = scorer off
    ai-confidence-base-url: ${{ vars.CONFIDENCE_BASE_URL }}  # a distinct backend grades independently
    ai-confidence-api-key: ${{ secrets.CONFIDENCE_API_KEY }} # a distinct URL never inherits the primary key

The verdict publishes as the verdict

  • review_verdict is authoritative (#​1162, closes #​1161): a valid final verdict maps to its native event — approve → APPROVE, request_changes → REQUEST_CHANGES — instead of quietly downgrading to a comment. The one remaining comment path is deliberate scope policy: a fork PR without approve-forks, or unknown fork-ness, still fails closed to an advisory comment. A missing or invalid verdict publishes neither event and says so. allow-approve is deprecated and inert; setting it logs a deprecation warning.
  • review_blockers publishes blocking requests only (#​1162): a request_changes verdict becomes a native blocking request, an approve verdict becomes an advisory comment, and the mode never publishes an approval under any verdict, input, or PR scope.
  • Shortfalls are named, not silent (#​1164, closes #​1145): an approval published with incomplete coverage now carries an explicit "Approval published with incomplete coverage" note instead of being downgraded to a comment that looked clean; a run with no valid verdict fails with a machine-readable error rather than posing as a successful comment review.
  • Evidence gaps get one bounded repair round: after the verdict turn accepts a response, a deterministic probe can re-run requirement-trace validation over the accepted coverage and, on a genuine gap with budget remaining, append an untrusted-fenced instruction to the same conversation for one bounded tool-loop round before the verdict is re-requested. Every outcome — continued or skipped, and why — is recorded and sanitized on the artifacts. And a requirement truth re-derived from the checkout and found genuinely absent (structural-proof-unconfirmed) now synthesizes a concrete blocker and flips approve to request_changes, while a reviewer's own citation-scope note (#​854) no longer does — it stays a repairable coverage gap the continuation can go investigate.

A second opinion, opt-in

  • Independent post-review confidence scorer (#​1140, closes #​1073): after the review finishes and before publication, a separately configured model receives a credential-redacted, untrusted-fenced summary of the final review and returns a 0–5 score, a risk band, a bounded reason, and bounded concerns. ai-confidence-* inputs configure the lane; a distinct ai-confidence-base-url never implicitly inherits the primary credential. The result is advisory telemetry only — it never touches the verdict, findings, or any gate — and it is off by default: unset means no extra model call and empty outputs, never a spurious 0. On fork PRs the scorer is off unless explicitly enabled, because its prompt sends the review's own privileged output to another endpoint.

What happens to a finding afterwards

  • Finding-outcome and feedback data contract (#​1115, closes #​1027): every published inline finding carries a stable, action-owned identity marker, and a successful publish now exports finding-outcomes.json — a finding-outcomes/v1 event ledger (reported, repeated, resolved, dismissed, feedback, …) with deterministic reconciliation. Privacy-aware by construction: events carry digests and counts, never message text or logins, and adjudicated precision reads only explicit operator adjudications — a resolved thread or a 👎 cannot inflate it. No verdict, severity, suppression, or prompt behavior changes; this is the measurement seam the v3.6.0 feedback loop was missing.

Credentials that aren't yours still get masked

  • PR-authored content is redacted at ingestion (#​1157, closes #​1154): the diff, PR body, and every artifact derived from them now pass a credential-shape redactor once, at ingestion — so the model input and every persisted artifact (pr.diff, ai-request.<tier>.json, corpus sections) carry the same [REDACTED] bytes and cannot diverge. Over-redaction of a credential-shaped test fixture is the accepted tradeoff; the configured-key layer stays out of the diff so a short key can't destroy review input.
  • Provider-authored raw bodies get the generic pass (#​1153, closes #​1149): ai-response.<tier>.json on every lane now goes through redactTextDeep, so a credential the provider invented — a key it generated, another tenant's token quoted in an error body — can no longer persist verbatim even though this run never configured it.
  • Linked-issue bodies redact at the projection seam (#​1174, closes #​1159): fetched linked-issue titles, labels, and bodies reached the corpus with no redaction at all; the single projection feeding every sink now masks same-line and split-line credential shapes with line counts preserved, before any embed cut.

Model-authored markdown can't forge a prescription

  • Reservation follows the container, not just the line (#​1135, closes #​1112): a ```suggestion opener behind a blockquote or list marker rendered as a live one-click prescription cmark-gfm honors but publication never validated. The opener is now matched behind container prefixes, with the prefix preserved so benign prose stays byte-identical.
  • An unclosed fence can't swallow the validated prescription (#​1139, closes #​1136): a model message ending in an ordinary fence with no closer extended to end-of-document and rendered the action's appended, validated prescription as inert fence content. Unclosed ordinary fences are now dissolved like reserved ones — deterministic, and benign closed blocks stay untouched.
  • Merge and prescription keys are structurally injective (#​1150, fixes #​1119): both key builders joined model-authored fields with a bare NUL, and a NUL is not JS whitespace — a model could shift a field boundary and fold a distinct finding into a "duplicate". Keys now use array serialization, matching the outcomes-identity precedent.

Fail loud, not silent

  • Platform response bodies are bounded while streaming (#​1169, closes #​1131): a 32 MiB cap is enforced on bytes as they arrive, independent of Content-Length. The part that matters: an oversized diff previously degraded to an empty string, fingerprinted as empty-diff, and would have silently skipped every later push on the PR — the adapters now rethrow and the run fails visibly.
  • The durable queue refuses bad snapshots (#​1171, closes #​1130): persisted job records are validated field by field, duplicate generation ids are rejected at intake and adoption, and malformed snapshots fail closed instead of loading.
  • Supersession-aborted generations retire (#​1168, fixes #​1141): a superseded executor that reported failure used to requeue as runnable work and could win the next dispatch slot over its own replacement.

Toward the self-hosted controller

More groundwork libraries — exercised by tests, not yet imported by the Action runtime, so Action users should notice exactly nothing here.

  • Repository acquisition (#​1125, closes #​732): a persistent bare mirror cache with bounded incremental fetch, immutable head/base SHAs verified before any workspace exists, and isolated per-review worktrees with crash-recovery sweeps. Credentials stay per-invocation env; nothing is written to repo config or remotes.
  • GitHub App auth and the capability seam (#​1120, closes #​1133, substrate of #​729): RS256 JWT minting and installation-token lifecycle in-process — no gh, no shell-out — with credentials scoped exactly to the repository each call names, and managed-comment ownership proven per write so a PR author's own marker comment can't be spoofed into an update target.
  • First Tangled publish record (#​1118, closes #​588): unlike the libraries above, this seam is wired into the publish path — Tangled builds one managed top-level ATProto review record (dev.prreviewer.review) and never routes through the GitHub/Forgejo publish APIs. It stays experimental and fail-closed: with no trustworthy current-head source yet, publication refuses every PR today until #​1165 lands. Nothing is expected of Tangled users yet.

Upgrading

Pin to v3.7.0, or the floating v3 tag, which now follows this build. Immutable-version and SHA pins must be bumped deliberately.

This release has real behavior changes. The honest notes:

  • publish-mode: review_verdict users: an approve verdict now publishes a native APPROVE event where it previously published a comment. That is the point of the mode, but if you relied on the old always-comment behavior, switch to the new review_blockers mode — it never approves. allow-approve is deprecated and ignored; fork approvals still require the explicit approve-forks opt-in. Changing publish mode changes the review fingerprint, so the switch triggers one fresh review.
  • Partial-coverage approvals are no longer downgraded: an approved review with coverage gaps publishes APPROVE with an explicit incomplete-coverage note instead of a silent downgrade to COMMENT. If your branch protection treats approvals as merge-eligible, read that note before merging.
  • Artifacts are redacted more aggressively: ai-request.<tier>.json, ai-response.<tier>.json, diff/PR-body artifacts, and linked-issue sections now contain [REDACTED] where credential-shaped values appear — including values you never configured. Anything parsing those artifacts for raw content will see masks. Unset configuration still produces byte-identical request behavior.
  • All new inputs are opt-in with empty/false defaults: the confidence scorer makes no model call when ai-confidence-model is unset, and the confidence-* outputs are empty rather than zero.

Every input's current contract lives in docs/inputs.md.

Full changelog: v3.6.0...v3.7.0

Generated changelog (release-please)
Features
Bug Fixes
Chores

v3.6.0

Compare Source

3.6.0 is about closing the loop. Reviews used to be fire-and-forget: the action published findings and never learned whether a suggestion helped. This release makes findings actionable — line-exact suggestions you can apply in one click, and a usefulness signal (a 👎) that keeps a rejected prescription from coming back. Operators can stamp every model request with a per-run correlation id so proxy cost logs group one run's calls, and repositories can teach the reviewer bounded, repo-local skills.

Underneath, it's a hardening release for the write path: only proven-trusted identities may touch the action's comments, webhook event hints must agree with the signed payload, and requirement-trace stops manufacturing blockers the model never substantiated.

If any of the first three features matter to you, this is the release to pin:

- uses: misospace/pr-reviewer-action@v3
  with:
    ai-base-url: ${{ vars.AI_BASE_URL }}
    ai-api-key: ${{ secrets.AI_API_KEY }}
    ai-model: ${{ vars.AI_MODEL }}
    ai-extra-headers: |
      x-litellm-session-id: ${{ github.run_id }}

Interpolate github.run_id in the calling workflow — a literal GitHub expression here fails at action load time.

- uses: misospace/pr-reviewer-action@v3
  with:
    repository-skills: true

Findings you can act on

  • Findings carry apply-ready suggestions (#​1101, closes #​762): a finding may now include an exact line/range replacement, rendered as a native one-click suggestion block on GitHub (degraded cleanly on Forgejo), plus a concise fix prompt for coding agents. A 👎 from a trusted collaborator suppresses that exact prescription on later runs — range-exact, keyed to the published text, withhold-only: verdict, severity, and thread handling are untouched, and the action's own reactions never count. Untrusted reactions stay telemetry. (#​1110, closes #​1107: model-authored text can no longer forge a suggestion opener, and one shared predicate decides whether a finding carries a prescription.)

Trace a run, teach the reviewer

  • ai-extra-headers rides on every provider request (#​1092, closes #​1037): multi-line Name: value pairs merged into every lane — primary, smart, fallback, specialist — and both wire formats. Malformed lines, duplicates, and collisions with transport headers (Authorization, x-api-key, accept-encoding, …) are rejected at startup. The input is treated as a secret end-to-end: values are redacted from config dumps and masked out of provider error and response surfaces, even when an endpoint echoes a header value back in an HTTP 200 body (#​1094). Fingerprinting is name-only for ephemeral correlation headers (-session-id, traceparent, …), so a per-run id never invalidates a cached review; any other header participates by name plus a one-way digest of its value.
  • repository-skills opts into repo-local guidance (#​1081): discover bounded .agents/skills/*/SKILL.md files from the trusted PR base. In native-loop mode the model reads relevant skills on demand; with tools off, repository-skill-path includes one operator-selected skill as a bounded corpus addendum. Never reads PR-head content, disabled on fork PRs, and enabled state feeds the precheck config hash so a re-review can't silently reuse an incompatible run.

Only trusted hands touch a comment

  • Forgejo owner identity is proven, not assumed (#​1097, fixes #​1093): ownership now binds a canonical user id — Authorized Integration audience or a reaction self-write probe — and every unproven state fails closed as before. A clean re-review also no longer publishes an empty "Inline findings…" review; cleanup anchors on the sticky comment's own publication checkpoint instead.
  • GitHub sticky upsert only patches your own comments (#​1100, closes #​1098): a foreign-authored marker comment is never overwritten, even when it's the newest match; when no owned target exists, unattributable comments fail closed to creation.
  • Trusted owner resolves once per publish run (#​1109, closes #​1099): the Forgejo reaction self-write probe fires once instead of twice per run.
  • Superseded advisory reviews minimize instead of piling up (#​1129, closes #​1114): bot-owned COMMENTED reviews left behind by incomplete re-runs are collapsed — presentation-only, idempotent, and Forgejo no-ops. Destructive cleanup (inline retirement, verdict dismissal, thread resolution) stays behind the unchanged complete-replacement gate.

The signed body is the event

  • Forgejo event hints must match the signed payload (#​1103, closes #​1024): a replayed delivery with a valid signature but a swapped event-header hint could previously mint a fresh review; hints are now honored only when compatible with the signed action.
  • Check-update kinds are shape-anchored (#​1106, closes #​1102): check_run / check_suite / status classifications must match the signed body's own shape, closing header-driven reclassification into schedulable check_update — without dropping real Forgejo deliveries that carry no pull-request fields.

Requirement-trace blocks less, explains more

  • Process/risk notes stop forcing CHANGES_REQUESTED (#​1096, fixes #​1095): advisory sections (Dependencies, Notes, Risk, Caveats, Limitations, Rollout) no longer enter the requirement ledger; test-execution outcomes classify as non-blocking external state; and an unmet requirement is disclosed in the rendered trace instead of being synthesized into blocking findings the model never substantiated. Blocking findings now come only from the model's own substantiated violations. Pinned by zero-inference golden replays, including the false-CHANGES_REQUESTED shape from miso-gallery#543 now approving.
  • Repair-pass outcome is visible (#​1105, fixes #​1044): the bounded requirement-trace repair pass records its outcome (skipped_by_gate, no_claims, errored, merged, …) on the run artifact and renders it. "The reviewer reported no trace" and "the repair pass ran and returned nothing" used to be indistinguishable; on a degraded primary they no longer are.

Provenance you can check

  • Related-code snippets carry their provenance (#​1104, closes #​1030): every related-code snippet is stamped committed_source or sanitized_source with a redaction count, on a harness-constructed header line — never inside the fence, where repository content could forge the annotation. Related code reads the working tree, so snippets carry revision: null and literal-claim authorization fails closed there until revision binding exists.

Groundwork: measuring the tool loop

  • tool_stop_reason lands in the metadata marker (#​1122, refs #​847): every harness run records why its tool loop stopped — the production signal #​847 needs to compare tool-budget exhaustion across request sizes. The marker key appends last; unset serializes byte-identical. Also faster CI: semantic-eval fixture integrity is memoized and bad corpora fail fast before evaluation (#​1111, closes #​1078).

Upgrading

Pin to v3.6.0, or the floating v3 tag, which now follows this build. Immutable-version and SHA pins must be bumped deliberately.

Nothing breaks and no input changed meaning. The honest notes:

  • All new inputs are opt-in with empty/false defaults and leave request bytes — and the review fingerprint — unchanged when unset. Treat ai-extra-headers values like API keys: they never appear in logs, artifacts, or error text.
  • Requirement-trace users (requirement-trace: true): one behavior changed in the direction of blocking less — advisory/process sections and test-execution outcomes no longer produce blockers, and unmet requirements are disclosed rather than synthesized into findings (#​1095). Strict provenance checks on real code criteria are unchanged.
  • The metadata marker gains tool_stop_reason, appended last. Consumers parsing marker fields positionally should read it as an optional trailing key; when unset, the marker is byte-identical to 3.5.x.
  • Reviews may now carry suggestion blocks, and a trusted collaborator's 👎 suppresses that exact prescription on later runs. Suppression never touches the verdict, so a downvoted suggestion can't downgrade an approval.

Every input's current contract lives in docs/inputs.md.

Full changelog: v3.5.0...v3.6.0

Generated changelog (release-please)
Features
Bug Fixes
Performance Improvements
Documentation

v3.5.0

Compare Source

3.5.0 is about lanes. Until now every model lane — primary, smart, fallback, specialists — was effectively a clone of the primary's request shape, and "does this need a human?" lived nowhere outside the model's prose. This release makes each lane independently configurable, makes structured output on the Anthropic wire honest about what it actually enforces, and adds a first-class human-review triage that can route to the right reviewer deterministically.

It's also the biggest groundwork release yet for the self-hosted controller: the Forgejo ingress, the durable review queue, and the Tangled read seam all landed as libraries. None of it is wired into the Action runtime — Action users should notice exactly nothing there.

If your lanes run against different backends, this is the release to pin:

- uses: misospace/pr-reviewer-action@v3
  with:
    ai-base-url: ${{ vars.AI_BASE_URL }}
    ai-api-key: ${{ secrets.AI_API_KEY }}
    ai-model: ${{ vars.AI_MODEL }}
    ai-response-format: json_schema       # base default
    ai-smart-response-format: json_schema # smart lane keeps structured output
    ai-fallback-response-format: off      # fallback model rejects the parameter
    ai-specialist-reasoning-effort: high  # specialists think harder than primary

Model lanes stop being clones

  • Response format is lane-aware (#​1040, closes #​1009): ai-primary-response-format, ai-smart-response-format and ai-fallback-response-format override ai-response-format per lane; unset lanes inherit, so single-value workflows stay request-byte compatible. The motivating shape: a primary behind a proxy that rejects response_format no longer forces off onto every other lane, and the reviewer-requested smart re-review (#​721) can opt into richer json_schema.
  • Reasoning effort is profile-aware, on both wire families (#​1049, closes #​998): ai-reasoning-effort gains per-lane overrides (ai-primary-…, ai-smart-…, ai-specialist-…, ai-fallback-…). OpenAI-compatible requests send reasoning_effort; Anthropic requests send output_config.effort — but only under that lane's own *-anthropic-effort-support assertion, never inherited from another lane. The fallback lane inherits the base effort on purpose (#​965: availability recovery, never quality escalation) yet asserts its own endpoint, because ai-fallback-base-url may be a different backend entirely.
  • Anthropic structured output got truthful (#​1047): previously ai-response-format: json_schema on ai-api-format: anthropic was accepted and then silently omitted — operators believed the schema was enforced when it was only prompted. Now Anthropic-format requests carry no structured-output parameter unless the lane's *-anthropic-structured-output-support opt-in is set, the run logs what is actually enforced, and if a wrong assertion draws a 400 naming the parameter, the request retries once without it so the review degrades to prompted JSON instead of failing.
  • Specialists survive model misbehavior: streamed Anthropic overruns are detected instead of accepted, completion-limit replies with zero leads are retried, malformed no-lead responses classify as parser errors (retryable) rather than fatal, overrun-recovery retries are reported only when actually adopted, and the specialist completion budget is now a real input — deep-review-max-tokens, default 16384, independent of ai-max-tokens — enforced across every surface.
  • Smart-tier limits are yours to set (#​1032, closes #​1020): smart-tool-max-rounds and smart-tool-loop-wall-clock-sec bound only the post-review escalation rerun, leaving the primary loop untouched. Empty inherits the previous scaling behavior.

Ask a human, deterministically

  • Opt-in triage (#​1051, closes #​1003): review-triage: true makes the reviewer answer a tri-state "does this PR need specialized/owning human review?" — not_required, required, or unknown, fail-closed to unknown when the answer is missing or malformed. It's advisory only: it never moves the verdict, findings, or any tool/access gating, and with the input off the outputs stay empty — "did not run" is never confused with "no work".
  • Deterministic routing (#​1005): with review-triage-routing-mode: request, a triage of required additively requests reviewers. The model can only pick logical target ids declared in the trusted base-ref .github/pr-reviewer-routing.yml; the action maps those ids to concrete users/teams, requests are idempotent and never remove existing reviewers, and an unknown target or any uncertain state mutates nothing. Never on forks. advisory mode publishes the routing plan without touching the forge, for safe dogfooding. (GitHub-only; Forgejo degrades to request_failed.)

# .github/pr-reviewer-routing.yml (read from the base ref)
targets:
  platform:
    users: [alice]
    teams: [platform-team]
  security:
    teams: [security]

Provenance you can check

  • Source-claim blockers verify against the exact head (#​1033, closes #​1016): a finding whose blocker rests on repository source is now verified against the source at the reviewed revision, not a stale or sanitized stand-in.
  • Provenance rides through tool output (#​1029, closes #​1015): source evidence the model sees through native tools carries the same committed-vs-sanitized provenance discipline as the corpus, so a citation the reviewer makes is checkable against what it actually read.
  • Non-code criteria stop falsely blocking (#​1062): requirement-trace acceptance criteria that demand no code change no longer block approval.
  • Publish fails closed on bad data (#​1079, #​1050): malformed requested-reviewers responses abort the publication path rather than guessing, and superseded managed inline comments are retired safely instead of piling up on long-lived PRs.
  • No-diff runs can't claim coverage (#​1031, closes #​1026): partitioned reviews fail closed when the no-diff path would have reported coverage it never gathered, and outcomes are bound to the plan round that produced them.
  • Fingerprints stay honest: changing the effective triage routing mode (#​1005) or leaving a fallback effort unset now changes the review fingerprint, so config edits trigger a fresh review instead of riding a stale skip.

Forgejo

  • CI status discovery works on Forgejo v16 (#​1046): the review job no longer times out against the v16 API.
  • authorized_integration auth fixed (#​1045), plus a dedicated forgejo-token input so the Forgejo token can differ from the GitHub-compatible one, and a forgejo-auth-method input to pick between token and OIDC authorized-integration modes.

Toward the self-hosted controller

Shipped as libraries, exercised by tests, consumed by controller work ahead — the normal Action runtime doesn't touch any of it yet, and that's deliberate.

  • Forgejo ingress (#​1019, closes #​730): webhook signature verification before parse (fail closed), native-vocabulary projection, and missed-webhook reconciliation — the daemon's front door, with the contract details in docs/architecture/self-hosted-forgejo-ingress.md.
  • Durable review queue (#​1021, closes #​731): 8-state job records, settle/debounce windows that collapse bursts, at-most-one-active-generation per PR, head supersession, lease/heartbeat dispatch with bounded retry — the scheduler's brain. (docs/architecture/durable-review-queue.md)
  • Tangled read seam (#​1013, #​1012, closes #​585, #​586): pull metadata normalized into the platform seam, and the latest pull round fetched with patch-blob diff/files normalized into review inputs. Groundwork — Tangled review support is not complete yet.
  • One forge capability for Python tooling (#​1039, closes #​1041): every Python tool's reads and writes route through pr_reviewer.forge — one URL/token resolution, a redirect-safe transport that never copies the Authorization header onto a redirect, and an HTTPS-only base-URL guard that raises before any byte hits the wire. The gh api error-echo surface is gone with it.
  • Reproducible eval lanes (#​1022, closes #​967): heterogeneous model/profile lanes for the eval harness, so A/B results across different models reproduce.

Upgrading

Pin to v3.5.0, or the floating v3 tag, which now follows this build. Immutable-version and SHA pins must be bumped deliberately.

Nothing breaks and no input changed meaning. The honest notes:

  • All new inputs are opt-in with empty/false defaults, and leave request bytes unchanged when unset. The one to be deliberate about: on Anthropic-format lanes, ai-response-format: json_schema was never actually sent before — it only looked like it was. If you want native enforcement, set ai-anthropic-structured-output-support (and the lane variants) only after confirming the endpoint accepts output_config.format.
  • Specialist completions now default to a 16384 cap (deep-review-max-tokens), independent of ai-max-tokens; deep-review runs may spend more tokens per role.
  • Requirement-trace users: non-code acceptance criteria no longer block approval (#​1062) — one behavior changed in the direction of blocking less.

Every input's current contract lives in docs/inputs.md.

Full changelog: https://github.com/misospace/pr-reviewer-action/compare/v3.4.1...v3.5.0

Generated changelog (release-please)
Features
Bug Fixes
  • ci: repair dogfood regressions and retire obsolete Python test debt (#​1060) (afd5013)
  • classification: treat self-location readlink as trusted path bookkeeping (#​1034) (#​1042) (92424f9)
  • config: preserve unset fallback effort in hash (c6630d7)
  • deps: update dependency @​types/node (24.19.1 → 24.19.2) (#​1023) (e44a237)
  • enforcement: confirm documentation trace rows only from their named target source (86229e0)
  • enforcement: harden documentation scan per independent review (259de11)
  • forgejo: Fix CI timeout on V16 API (#​1046) (8350071)
  • forgejo: Fix Forgejo authorized_integration mode (#​1045) (6b38cbe)
  • ingress: bind reconciliation jobs to the configured repository (#​1025) (#​1052) (d1cff53)
  • model: declare review_triage_targets in strict OpenAI verdict schemas (aec5111)
  • model: make Anthropic structured-output semantics truthful and recover usable verdicts (7a7e130)
  • model: make Anthropic structured-output semantics truthful and recover usable verdicts (816927b)
  • model: mask configured secrets before diagnostic truncation; specialist response-format via tierResponseFormat (f533d65)
  • model: report the effective wire format after a 400 strip recovery; CodeQL cleanup (f183288)
  • partition: fail-closed no-diff coverage and bind outcomes to plan round (#​1026) (#​1031) (55ecf00)
  • precheck: fingerprint the effective triage routing mode (20ff2e2)
  • publish: fail closed on a malformed requested-reviewers GET (#​1079) (5738670)
  • publish: safely retire superseded managed inline comments (#​1050) (cc1fa07)
  • requirement-trace: stop non-code acceptance criteria falsely blocking approval (#​1062) (50bf601)
  • requirement-trace: stop non-code acceptance criteria falsely blocking approval (#​1062) (8f93a01)
  • reviewer: carry source-evidence provenance through model-visible tool output (#​1015) (#​1029) (afe282f)
  • specialists: apply overrun recovery to the combined-scout path (6fcb154)
  • specialists: classify malformed/no-lead responses as parser (2bfa3ca)
  • specialists: detect Anthropic overruns, raise cap (4abbfb1)
  • specialists: detect streamed Anthropic overruns and raise the default cap to 16K (d60da4a)
  • specialists: only report overrun recovery when the retry is adopted (d54ab2b)
  • specialists: retry completion-limit responses with zero leads (5d23b68)
  • tools: make smart-tier loop round and wall-clock limits settable (#​1020) (#​1032) (f5b3e11)
Performance Improvements
  • ci: stop tests paying the real transport backoff (8b8f0d1)
  • ci: stop tests paying the real transport backoff (4fd2a05)
Chores
  • test: drop unreferenced dogfood-623 and test-evidence artifacts (496e2d0)
  • test: drop unreferenced dogfood-623 and test-evidence artifacts (e1d1ff8), closes #​1063
Documentation
  • agents: align normative guidance with shipped v3 action (#​1055) (34d68f1)
  • ci: record the observed after-CI numbers (67d2f16)
  • requirement-trace: pin non-code proof shapes in contract doc (bf6a2b2)
Refactors
  • config: drop no-op Action-input carve-outs (68b7f61)
  • config: drop no-op Action-input carve-outs (027e94c)
  • run: extract the step-summary seam from runReview (afdef1c)
  • run: extract the step-summary seam from runReview (7a82877)

Configuration

📅 Schedule: (in timezone Europe/Rome)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [https://github.com/misospace/pr-reviewer-action](https://github.com/misospace/pr-reviewer-action) | action | minor | `v3.4.1` → `v3.7.0` | --- > ⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/6) for more information. --- ### Release Notes <details> <summary>misospace/pr-reviewer-action (https://github.com/misospace/pr-reviewer-action)</summary> ### [`v3.7.0`](https://github.com/misospace/pr-reviewer-action/releases/tag/v3.7.0) [Compare Source](https://github.com/misospace/pr-reviewer-action/compare/v3.6.0...v3.7.0) 3.7.0 is about **the verdict being real**. Until now, `review_verdict` could reach `approve` and still publish a non-blocking comment, the only judge of a finished review was the model that wrote it, and what happened to a finding after publication was invisible. This release publishes the verdict it reached (plus a new blockers-only mode), adds an opt-in independent scorer that grades completed reviews, and exports a finding-outcome contract so operators can measure what actually happens to findings. Around that: a credential-redaction wave closes every remaining path where someone else's secret could ride to disk, and the self-hosted controller gains repository acquisition, GitHub App auth, and its first Tangled publish record. If you publish verdicts or want the scorer, this is the release to pin: ```yaml - uses: misospace/pr-reviewer-action@v3 with: publish-mode: review_verdict # an 'approve' verdict now publishes a real approval ``` ```yaml - uses: misospace/pr-reviewer-action@v3 with: ai-confidence-model: ${{ vars.CONFIDENCE_MODEL }} # empty (default) = scorer off ai-confidence-base-url: ${{ vars.CONFIDENCE_BASE_URL }} # a distinct backend grades independently ai-confidence-api-key: ${{ secrets.CONFIDENCE_API_KEY }} # a distinct URL never inherits the primary key ``` #### The verdict publishes as the verdict - **`review_verdict` is authoritative** ([#&#8203;1162](https://github.com/misospace/pr-reviewer-action/pull/1162), closes [#&#8203;1161](https://github.com/misospace/pr-reviewer-action/issues/1161)): a valid final verdict maps to its native event — `approve` → APPROVE, `request_changes` → REQUEST_CHANGES — instead of quietly downgrading to a comment. The one remaining comment path is deliberate scope policy: a fork PR without `approve-forks`, or unknown fork-ness, still fails closed to an advisory comment. A missing or invalid verdict publishes neither event and says so. `allow-approve` is deprecated and inert; setting it logs a deprecation warning. - **`review_blockers` publishes blocking requests only** ([#&#8203;1162](https://github.com/misospace/pr-reviewer-action/pull/1162)): a `request_changes` verdict becomes a native blocking request, an `approve` verdict becomes an advisory comment, and the mode never publishes an approval under any verdict, input, or PR scope. - **Shortfalls are named, not silent** ([#&#8203;1164](https://github.com/misospace/pr-reviewer-action/pull/1164), closes [#&#8203;1145](https://github.com/misospace/pr-reviewer-action/issues/1145)): an approval published with incomplete coverage now carries an explicit "Approval published with incomplete coverage" note instead of being downgraded to a comment that looked clean; a run with no valid verdict fails with a machine-readable error rather than posing as a successful comment review. - **Evidence gaps get one bounded repair round**: after the verdict turn accepts a response, a deterministic probe can re-run requirement-trace validation over the accepted coverage and, on a genuine gap with budget remaining, append an untrusted-fenced instruction to the *same* conversation for one bounded tool-loop round before the verdict is re-requested. Every outcome — continued or skipped, and why — is recorded and sanitized on the artifacts. And a requirement truth re-derived from the checkout and found genuinely absent (`structural-proof-unconfirmed`) now synthesizes a concrete blocker and flips `approve` to `request_changes`, while a reviewer's own citation-scope note ([#&#8203;854](https://github.com/misospace/pr-reviewer-action/issues/854)) no longer does — it stays a repairable coverage gap the continuation can go investigate. #### A second opinion, opt-in - **Independent post-review confidence scorer** ([#&#8203;1140](https://github.com/misospace/pr-reviewer-action/pull/1140), closes [#&#8203;1073](https://github.com/misospace/pr-reviewer-action/issues/1073)): after the review finishes and before publication, a separately configured model receives a credential-redacted, untrusted-fenced summary of the final review and returns a 0–5 score, a risk band, a bounded reason, and bounded concerns. `ai-confidence-*` inputs configure the lane; a distinct `ai-confidence-base-url` never implicitly inherits the primary credential. The result is advisory telemetry only — it never touches the verdict, findings, or any gate — and it is off by default: unset means no extra model call and empty outputs, never a spurious 0. On fork PRs the scorer is off unless explicitly enabled, because its prompt sends the review's own privileged output to another endpoint. #### What happens to a finding afterwards - **Finding-outcome and feedback data contract** ([#&#8203;1115](https://github.com/misospace/pr-reviewer-action/pull/1115), closes [#&#8203;1027](https://github.com/misospace/pr-reviewer-action/issues/1027)): every published inline finding carries a stable, action-owned identity marker, and a successful publish now exports `finding-outcomes.json` — a `finding-outcomes/v1` event ledger (`reported`, `repeated`, `resolved`, `dismissed`, `feedback`, …) with deterministic reconciliation. Privacy-aware by construction: events carry digests and counts, never message text or logins, and adjudicated precision reads only explicit operator adjudications — a resolved thread or a 👎 cannot inflate it. No verdict, severity, suppression, or prompt behavior changes; this is the measurement seam the v3.6.0 feedback loop was missing. #### Credentials that aren't yours still get masked - **PR-authored content is redacted at ingestion** ([#&#8203;1157](https://github.com/misospace/pr-reviewer-action/pull/1157), closes [#&#8203;1154](https://github.com/misospace/pr-reviewer-action/issues/1154)): the diff, PR body, and every artifact derived from them now pass a credential-shape redactor once, at ingestion — so the model input and every persisted artifact (`pr.diff`, `ai-request.<tier>.json`, corpus sections) carry the same `[REDACTED]` bytes and cannot diverge. Over-redaction of a credential-shaped test fixture is the accepted tradeoff; the configured-key layer stays out of the diff so a short key can't destroy review input. - **Provider-authored raw bodies get the generic pass** ([#&#8203;1153](https://github.com/misospace/pr-reviewer-action/pull/1153), closes [#&#8203;1149](https://github.com/misospace/pr-reviewer-action/issues/1149)): `ai-response.<tier>.json` on every lane now goes through `redactTextDeep`, so a credential the *provider* invented — a key it generated, another tenant's token quoted in an error body — can no longer persist verbatim even though this run never configured it. - **Linked-issue bodies redact at the projection seam** ([#&#8203;1174](https://github.com/misospace/pr-reviewer-action/pull/1174), closes [#&#8203;1159](https://github.com/misospace/pr-reviewer-action/issues/1159)): fetched linked-issue titles, labels, and bodies reached the corpus with no redaction at all; the single projection feeding every sink now masks same-line and split-line credential shapes with line counts preserved, before any embed cut. #### Model-authored markdown can't forge a prescription - **Reservation follows the container, not just the line** ([#&#8203;1135](https://github.com/misospace/pr-reviewer-action/pull/1135), closes [#&#8203;1112](https://github.com/misospace/pr-reviewer-action/issues/1112)): a ` ```suggestion ` opener behind a blockquote or list marker rendered as a live one-click prescription cmark-gfm honors but publication never validated. The opener is now matched behind container prefixes, with the prefix preserved so benign prose stays byte-identical. - **An unclosed fence can't swallow the validated prescription** ([#&#8203;1139](https://github.com/misospace/pr-reviewer-action/pull/1139), closes [#&#8203;1136](https://github.com/misospace/pr-reviewer-action/issues/1136)): a model message ending in an ordinary fence with no closer extended to end-of-document and rendered the action's appended, *validated* prescription as inert fence content. Unclosed ordinary fences are now dissolved like reserved ones — deterministic, and benign closed blocks stay untouched. - **Merge and prescription keys are structurally injective** ([#&#8203;1150](https://github.com/misospace/pr-reviewer-action/pull/1150), fixes [#&#8203;1119](https://github.com/misospace/pr-reviewer-action/issues/1119)): both key builders joined model-authored fields with a bare NUL, and a NUL is not JS whitespace — a model could shift a field boundary and fold a distinct finding into a "duplicate". Keys now use array serialization, matching the outcomes-identity precedent. #### Fail loud, not silent - **Platform response bodies are bounded while streaming** ([#&#8203;1169](https://github.com/misospace/pr-reviewer-action/pull/1169), closes [#&#8203;1131](https://github.com/misospace/pr-reviewer-action/issues/1131)): a 32 MiB cap is enforced on bytes as they arrive, independent of Content-Length. The part that matters: an oversized diff previously degraded to an empty string, fingerprinted as `empty-diff`, and would have silently skipped every later push on the PR — the adapters now rethrow and the run fails visibly. - **The durable queue refuses bad snapshots** ([#&#8203;1171](https://github.com/misospace/pr-reviewer-action/pull/1171), closes [#&#8203;1130](https://github.com/misospace/pr-reviewer-action/issues/1130)): persisted job records are validated field by field, duplicate generation ids are rejected at intake and adoption, and malformed snapshots fail closed instead of loading. - **Supersession-aborted generations retire** ([#&#8203;1168](https://github.com/misospace/pr-reviewer-action/pull/1168), fixes [#&#8203;1141](https://github.com/misospace/pr-reviewer-action/issues/1141)): a superseded executor that reported failure used to requeue as runnable work and could win the next dispatch slot over its own replacement. #### Toward the self-hosted controller More groundwork libraries — exercised by tests, not yet imported by the Action runtime, so Action users should notice exactly nothing here. - **Repository acquisition** ([#&#8203;1125](https://github.com/misospace/pr-reviewer-action/pull/1125), closes [#&#8203;732](https://github.com/misospace/pr-reviewer-action/issues/732)): a persistent bare mirror cache with bounded incremental fetch, immutable head/base SHAs verified before any workspace exists, and isolated per-review worktrees with crash-recovery sweeps. Credentials stay per-invocation env; nothing is written to repo config or remotes. - **GitHub App auth and the capability seam** ([#&#8203;1120](https://github.com/misospace/pr-reviewer-action/pull/1120), closes [#&#8203;1133](https://github.com/misospace/pr-reviewer-action/issues/1133), substrate of [#&#8203;729](https://github.com/misospace/pr-reviewer-action/issues/729)): RS256 JWT minting and installation-token lifecycle in-process — no `gh`, no shell-out — with credentials scoped exactly to the repository each call names, and managed-comment ownership proven per write so a PR author's own marker comment can't be spoofed into an update target. - **First Tangled publish record** ([#&#8203;1118](https://github.com/misospace/pr-reviewer-action/pull/1118), closes [#&#8203;588](https://github.com/misospace/pr-reviewer-action/issues/588)): unlike the libraries above, this seam is wired into the publish path — Tangled builds one managed top-level ATProto review record (`dev.prreviewer.review`) and never routes through the GitHub/Forgejo publish APIs. It stays experimental and fail-closed: with no trustworthy current-head source yet, publication refuses every PR today until [#&#8203;1165](https://github.com/misospace/pr-reviewer-action/issues/1165) lands. Nothing is expected of Tangled users yet. #### Upgrading Pin to `v3.7.0`, or the floating `v3` tag, which now follows this build. Immutable-version and SHA pins must be bumped deliberately. This release has real behavior changes. The honest notes: - **`publish-mode: review_verdict` users**: an `approve` verdict now publishes a native APPROVE event where it previously published a comment. That is the point of the mode, but if you relied on the old always-comment behavior, switch to the new `review_blockers` mode — it never approves. `allow-approve` is deprecated and ignored; fork approvals still require the explicit `approve-forks` opt-in. Changing publish mode changes the review fingerprint, so the switch triggers one fresh review. - **Partial-coverage approvals are no longer downgraded**: an approved review with coverage gaps publishes APPROVE with an explicit incomplete-coverage note instead of a silent downgrade to COMMENT. If your branch protection treats approvals as merge-eligible, read that note before merging. - **Artifacts are redacted more aggressively**: `ai-request.<tier>.json`, `ai-response.<tier>.json`, diff/PR-body artifacts, and linked-issue sections now contain `[REDACTED]` where credential-shaped values appear — including values you never configured. Anything parsing those artifacts for raw content will see masks. Unset configuration still produces byte-identical request behavior. - **All new inputs are opt-in with empty/false defaults**: the confidence scorer makes no model call when `ai-confidence-model` is unset, and the confidence-\* outputs are empty rather than zero. Every input's current contract lives in [docs/inputs.md](https://github.com/misospace/pr-reviewer-action/blob/v3.7.0/docs/inputs.md). **Full changelog:** [v3.6.0...v3.7.0](https://github.com/misospace/pr-reviewer-action/compare/v3.6.0...v3.7.0) <details><summary>Generated changelog (release-please)</summary> ##### Features - **[#&#8203;1073](https://github.com/misospace/pr-reviewer-action/issues/1073):** independent post-review confidence scorer (advisory, opt-in) ([#&#8203;1140](https://github.com/misospace/pr-reviewer-action/issues/1140)) ([a6a51a2](https://github.com/misospace/pr-reviewer-action/commit/a6a51a293037b5426d041490724c3d29e168380d)) - **[#&#8203;588](https://github.com/misospace/pr-reviewer-action/issues/588):** publish and update the managed top-level Tangled review record ([#&#8203;1118](https://github.com/misospace/pr-reviewer-action/issues/1118)) ([3699401](https://github.com/misospace/pr-reviewer-action/commit/3699401721f88f20c883003a0ff31ed0c1b1fd38)) - **acquisition:** repository mirror cache and isolated per-review workspaces ([#&#8203;732](https://github.com/misospace/pr-reviewer-action/issues/732)) ([#&#8203;1125](https://github.com/misospace/pr-reviewer-action/issues/1125)) ([f14a977](https://github.com/misospace/pr-reviewer-action/commit/f14a9773780b7387c3fe1594994aab364c92a6b9)) - **ingress:** GitHub App auth + capability seam — every forge read/write through the capability, not a CLI ([#&#8203;729](https://github.com/misospace/pr-reviewer-action/issues/729)) ([#&#8203;1120](https://github.com/misospace/pr-reviewer-action/issues/1120)) ([a44ea97](https://github.com/misospace/pr-reviewer-action/commit/a44ea977256d779d6bfa6bcdb00d55ee33ba5ce8)) - **outcomes:** finding-outcome and feedback data contract ([#&#8203;1027](https://github.com/misospace/pr-reviewer-action/issues/1027)) ([#&#8203;1115](https://github.com/misospace/pr-reviewer-action/issues/1115)) ([bdeab8a](https://github.com/misospace/pr-reviewer-action/commit/bdeab8aa7b715f60f68d0af41db6a06ab411c0e8)) - **review:** enable trusted repository skills ([#&#8203;1134](https://github.com/misospace/pr-reviewer-action/issues/1134)) ([0d26862](https://github.com/misospace/pr-reviewer-action/commit/0d2686224707192b4ac7def8213c1d9cbc12c143)) ##### Bug Fixes - **[#&#8203;1112](https://github.com/misospace/pr-reviewer-action/issues/1112):** reserve container-prefixed suggestion openers behind blockquote/list prefixes ([#&#8203;1135](https://github.com/misospace/pr-reviewer-action/issues/1135)) ([2d0d39f](https://github.com/misospace/pr-reviewer-action/commit/2d0d39f73b0c6a9691545add3a2192d1d2c3ad9d)) - **[#&#8203;1119](https://github.com/misospace/pr-reviewer-action/issues/1119):** make merge and prescription keys injective against NUL forgery ([#&#8203;1150](https://github.com/misospace/pr-reviewer-action/issues/1150)) ([6fade46](https://github.com/misospace/pr-reviewer-action/commit/6fade46a579fe1ea238e882300d84663cb1ece41)) - **[#&#8203;1130](https://github.com/misospace/pr-reviewer-action/issues/1130):** validate persisted job identities and reject duplicate queue ids ([#&#8203;1171](https://github.com/misospace/pr-reviewer-action/issues/1171)) ([c8b77a9](https://github.com/misospace/pr-reviewer-action/commit/c8b77a967283d0b4e6e6e05485c53439079bb20f)) - **[#&#8203;1131](https://github.com/misospace/pr-reviewer-action/issues/1131):** bound platform text/JSON response bodies while streaming ([#&#8203;1169](https://github.com/misospace/pr-reviewer-action/issues/1169)) ([1855642](https://github.com/misospace/pr-reviewer-action/commit/18556429227e3ad144b61c4122ce580b8d599b64)) - **[#&#8203;1136](https://github.com/misospace/pr-reviewer-action/issues/1136):** dissolve an unclosed ordinary fence that would swallow the validated prescription ([#&#8203;1139](https://github.com/misospace/pr-reviewer-action/issues/1139)) ([bac85a1](https://github.com/misospace/pr-reviewer-action/commit/bac85a1e825c5da6d5aaf93b73f6fef4065c0022)) - **[#&#8203;1141](https://github.com/misospace/pr-reviewer-action/issues/1141):** retire supersession-aborted generations on failed executor settle ([#&#8203;1168](https://github.com/misospace/pr-reviewer-action/issues/1168)) ([31342a1](https://github.com/misospace/pr-reviewer-action/commit/31342a16e0e6e5dc2a1b6401e27a147395b4e885)), closes [#&#8203;1141](https://github.com/misospace/pr-reviewer-action/issues/1141) - **[#&#8203;1145](https://github.com/misospace/pr-reviewer-action/issues/1145):** review_verdict publishes the verdict; bounded tool-loop evidence-repair continuation; confirmed-unmet escalation ([#&#8203;1164](https://github.com/misospace/pr-reviewer-action/issues/1164)) ([716adb1](https://github.com/misospace/pr-reviewer-action/commit/716adb1a2f4455c6b02cf6f2611d2e38d9e41247)) - **[#&#8203;1149](https://github.com/misospace/pr-reviewer-action/issues/1149):** route persisted raw provider bodies through redactTextDeep ([#&#8203;1153](https://github.com/misospace/pr-reviewer-action/issues/1153)) ([04e5bd1](https://github.com/misospace/pr-reviewer-action/commit/04e5bd11c695344a0c6e3553ea15ddc04e69387f)) - **[#&#8203;1154](https://github.com/misospace/pr-reviewer-action/issues/1154):** credential-shape redact the PR-authored artifact family (incl. diff path headers) ([#&#8203;1157](https://github.com/misospace/pr-reviewer-action/issues/1157)) ([f5f8f74](https://github.com/misospace/pr-reviewer-action/commit/f5f8f74e0e3359230bb14193a29aed2156051f11)) - **[#&#8203;1159](https://github.com/misospace/pr-reviewer-action/issues/1159):** redact fetched linked-issue bodies at the projection seam ([#&#8203;1174](https://github.com/misospace/pr-reviewer-action/issues/1174)) ([a66b9e9](https://github.com/misospace/pr-reviewer-action/commit/a66b9e96fe005a6ad793d2da93bc9a85ba8be870)) - **[#&#8203;1161](https://github.com/misospace/pr-reviewer-action/issues/1161):** publish the review_verdict verdict; add review_blockers mode ([#&#8203;1162](https://github.com/misospace/pr-reviewer-action/issues/1162)) ([1ceebd8](https://github.com/misospace/pr-reviewer-action/commit/1ceebd8e9684d1e0a4159d53b16b1459dfbd86b1)), closes [#&#8203;1161](https://github.com/misospace/pr-reviewer-action/issues/1161) - **deps:** update dependency astro (7.4.0 → 7.4.1) ([#&#8203;1160](https://github.com/misospace/pr-reviewer-action/issues/1160)) ([cf8d3f1](https://github.com/misospace/pr-reviewer-action/commit/cf8d3f1c2cdd16ea992b5d0c860a7388d37bfe29)) ##### Chores - **deps:** lock file maintenance ([#&#8203;1148](https://github.com/misospace/pr-reviewer-action/issues/1148)) ([c3f04c5](https://github.com/misospace/pr-reviewer-action/commit/c3f04c5bca14dc899de0b74094b5fa7e00fa915e)) - **dev:** add reproducible Node development bootstrap ([#&#8203;1142](https://github.com/misospace/pr-reviewer-action/issues/1142)) ([57947fc](https://github.com/misospace/pr-reviewer-action/commit/57947fcf50bceda5235c2fad7a9fe41b4eb5778f)) </details> ### [`v3.6.0`](https://github.com/misospace/pr-reviewer-action/releases/tag/v3.6.0) [Compare Source](https://github.com/misospace/pr-reviewer-action/compare/v3.5.0...v3.6.0) 3.6.0 is about **closing the loop**. Reviews used to be fire-and-forget: the action published findings and never learned whether a suggestion helped. This release makes findings *actionable* — line-exact suggestions you can apply in one click, and a usefulness signal (a 👎) that keeps a rejected prescription from coming back. Operators can stamp every model request with a per-run correlation id so proxy cost logs group one run's calls, and repositories can teach the reviewer bounded, repo-local skills. Underneath, it's a hardening release for the write path: only proven-trusted identities may touch the action's comments, webhook event hints must agree with the signed payload, and requirement-trace stops manufacturing blockers the model never substantiated. If any of the first three features matter to you, this is the release to pin: ```yaml - uses: misospace/pr-reviewer-action@v3 with: ai-base-url: ${{ vars.AI_BASE_URL }} ai-api-key: ${{ secrets.AI_API_KEY }} ai-model: ${{ vars.AI_MODEL }} ai-extra-headers: | x-litellm-session-id: ${{ github.run_id }} ``` Interpolate `github.run_id` in the calling workflow — a literal GitHub expression here fails at action load time. ```yaml - uses: misospace/pr-reviewer-action@v3 with: repository-skills: true ``` #### Findings you can act on - **Findings carry apply-ready suggestions** ([#&#8203;1101](https://github.com/misospace/pr-reviewer-action/pull/1101), closes [#&#8203;762](https://github.com/misospace/pr-reviewer-action/issues/762)): a finding may now include an exact line/range replacement, rendered as a native one-click suggestion block on GitHub (degraded cleanly on Forgejo), plus a concise fix prompt for coding agents. A 👎 from a trusted collaborator suppresses that exact prescription on later runs — range-exact, keyed to the published text, withhold-only: verdict, severity, and thread handling are untouched, and the action's own reactions never count. Untrusted reactions stay telemetry. ([#&#8203;1110](https://github.com/misospace/pr-reviewer-action/pull/1110), closes [#&#8203;1107](https://github.com/misospace/pr-reviewer-action/issues/1107): model-authored text can no longer forge a `suggestion` opener, and one shared predicate decides whether a finding carries a prescription.) #### Trace a run, teach the reviewer - **`ai-extra-headers` rides on every provider request** ([#&#8203;1092](https://github.com/misospace/pr-reviewer-action/pull/1092), closes [#&#8203;1037](https://github.com/misospace/pr-reviewer-action/issues/1037)): multi-line `Name: value` pairs merged into every lane — primary, smart, fallback, specialist — and both wire formats. Malformed lines, duplicates, and collisions with transport headers (`Authorization`, `x-api-key`, `accept-encoding`, …) are rejected at startup. The input is treated as a secret end-to-end: values are redacted from config dumps and masked out of provider error and response surfaces, even when an endpoint echoes a header value back in an HTTP 200 body ([#&#8203;1094](https://github.com/misospace/pr-reviewer-action/pull/1094)). Fingerprinting is name-only for ephemeral correlation headers (`-session-id`, `traceparent`, …), so a per-run id never invalidates a cached review; any other header participates by name plus a one-way digest of its value. - **`repository-skills` opts into repo-local guidance** ([#&#8203;1081](https://github.com/misospace/pr-reviewer-action/pull/1081)): discover bounded `.agents/skills/*/SKILL.md` files from the trusted PR base. In native-loop mode the model reads relevant skills on demand; with tools off, `repository-skill-path` includes one operator-selected skill as a bounded corpus addendum. Never reads PR-head content, disabled on fork PRs, and enabled state feeds the precheck config hash so a re-review can't silently reuse an incompatible run. #### Only trusted hands touch a comment - **Forgejo owner identity is proven, not assumed** ([#&#8203;1097](https://github.com/misospace/pr-reviewer-action/pull/1097), fixes [#&#8203;1093](https://github.com/misospace/pr-reviewer-action/issues/1093)): ownership now binds a canonical user id — Authorized Integration audience or a reaction self-write probe — and every unproven state fails closed as before. A clean re-review also no longer publishes an empty "Inline findings…" review; cleanup anchors on the sticky comment's own publication checkpoint instead. - **GitHub sticky upsert only patches your own comments** ([#&#8203;1100](https://github.com/misospace/pr-reviewer-action/pull/1100), closes [#&#8203;1098](https://github.com/misospace/pr-reviewer-action/issues/1098)): a foreign-authored marker comment is never overwritten, even when it's the newest match; when no owned target exists, unattributable comments fail closed to creation. - **Trusted owner resolves once per publish run** ([#&#8203;1109](https://github.com/misospace/pr-reviewer-action/pull/1109), closes [#&#8203;1099](https://github.com/misospace/pr-reviewer-action/issues/1099)): the Forgejo reaction self-write probe fires once instead of twice per run. - **Superseded advisory reviews minimize instead of piling up** ([#&#8203;1129](https://github.com/misospace/pr-reviewer-action/pull/1129), closes [#&#8203;1114](https://github.com/misospace/pr-reviewer-action/issues/1114)): bot-owned `COMMENTED` reviews left behind by incomplete re-runs are collapsed — presentation-only, idempotent, and Forgejo no-ops. Destructive cleanup (inline retirement, verdict dismissal, thread resolution) stays behind the unchanged complete-replacement gate. #### The signed body is the event - **Forgejo event hints must match the signed payload** ([#&#8203;1103](https://github.com/misospace/pr-reviewer-action/pull/1103), closes [#&#8203;1024](https://github.com/misospace/pr-reviewer-action/issues/1024)): a replayed delivery with a valid signature but a swapped event-header hint could previously mint a fresh review; hints are now honored only when compatible with the signed action. - **Check-update kinds are shape-anchored** ([#&#8203;1106](https://github.com/misospace/pr-reviewer-action/pull/1106), closes [#&#8203;1102](https://github.com/misospace/pr-reviewer-action/issues/1102)): `check_run` / `check_suite` / `status` classifications must match the signed body's own shape, closing header-driven reclassification into schedulable `check_update` — without dropping real Forgejo deliveries that carry no pull-request fields. #### Requirement-trace blocks less, explains more - **Process/risk notes stop forcing CHANGES_REQUESTED** ([#&#8203;1096](https://github.com/misospace/pr-reviewer-action/pull/1096), fixes [#&#8203;1095](https://github.com/misospace/pr-reviewer-action/issues/1095)): advisory sections (`Dependencies`, `Notes`, `Risk`, `Caveats`, `Limitations`, `Rollout`) no longer enter the requirement ledger; test-execution outcomes classify as non-blocking external state; and an unmet requirement is disclosed in the rendered trace instead of being synthesized into blocking findings the model never substantiated. Blocking findings now come only from the model's own substantiated violations. Pinned by zero-inference golden replays, including the false-CHANGES_REQUESTED shape from [miso-gallery#543](https://github.com/miso-gallery/pr-reviewer-action/issues/543) now approving. - **Repair-pass outcome is visible** ([#&#8203;1105](https://github.com/misospace/pr-reviewer-action/pull/1105), fixes [#&#8203;1044](https://github.com/misospace/pr-reviewer-action/issues/1044)): the bounded requirement-trace repair pass records its outcome (`skipped_by_gate`, `no_claims`, `errored`, `merged`, …) on the run artifact and renders it. "The reviewer reported no trace" and "the repair pass ran and returned nothing" used to be indistinguishable; on a degraded primary they no longer are. #### Provenance you can check - **Related-code snippets carry their provenance** ([#&#8203;1104](https://github.com/misospace/pr-reviewer-action/pull/1104), closes [#&#8203;1030](https://github.com/misospace/pr-reviewer-action/issues/1030)): every related-code snippet is stamped `committed_source` or `sanitized_source` with a redaction count, on a harness-constructed header line — never inside the fence, where repository content could forge the annotation. Related code reads the working tree, so snippets carry `revision: null` and literal-claim authorization fails closed there until revision binding exists. #### Groundwork: measuring the tool loop - **`tool_stop_reason` lands in the metadata marker** ([#&#8203;1122](https://github.com/misospace/pr-reviewer-action/pull/1122), refs [#&#8203;847](https://github.com/misospace/pr-reviewer-action/issues/847)): every harness run records why its tool loop stopped — the production signal [#&#8203;847](https://github.com/misospace/pr-reviewer-action/issues/847) needs to compare tool-budget exhaustion across request sizes. The marker key appends last; unset serializes byte-identical. Also faster CI: semantic-eval fixture integrity is memoized and bad corpora fail fast before evaluation ([#&#8203;1111](https://github.com/misospace/pr-reviewer-action/pull/1111), closes [#&#8203;1078](https://github.com/misospace/pr-reviewer-action/issues/1078)). #### Upgrading Pin to `v3.6.0`, or the floating `v3` tag, which now follows this build. Immutable-version and SHA pins must be bumped deliberately. Nothing breaks and no input changed meaning. The honest notes: - **All new inputs are opt-in with empty/false defaults** and leave request bytes — and the review fingerprint — unchanged when unset. Treat `ai-extra-headers` values like API keys: they never appear in logs, artifacts, or error text. - **Requirement-trace users** (`requirement-trace: true`): one behavior changed in the direction of blocking less — advisory/process sections and test-execution outcomes no longer produce blockers, and unmet requirements are disclosed rather than synthesized into findings ([#&#8203;1095](https://github.com/misospace/pr-reviewer-action/issues/1095)). Strict provenance checks on real code criteria are unchanged. - **The metadata marker gains `tool_stop_reason`**, appended last. Consumers parsing marker fields positionally should read it as an optional trailing key; when unset, the marker is byte-identical to 3.5.x. - **Reviews may now carry suggestion blocks**, and a trusted collaborator's 👎 suppresses that exact prescription on later runs. Suppression never touches the verdict, so a downvoted suggestion can't downgrade an approval. Every input's current contract lives in [docs/inputs.md](https://github.com/misospace/pr-reviewer-action/blob/v3.6.0/docs/inputs.md). **Full changelog:** [v3.5.0...v3.6.0](https://github.com/misospace/pr-reviewer-action/compare/v3.5.0...v3.6.0) <details><summary>Generated changelog (release-please)</summary> ##### Features - **[#&#8203;1037](https://github.com/misospace/pr-reviewer-action/issues/1037):** send ai-extra-headers on every AI provider request ([#&#8203;1092](https://github.com/misospace/pr-reviewer-action/issues/1092)) ([a640068](https://github.com/misospace/pr-reviewer-action/commit/a640068e855d45f264737da3b05e30a6566f7816)) - **[#&#8203;847](https://github.com/misospace/pr-reviewer-action/issues/847):** record tool_stop_reason in the metadata marker on every harness run ([#&#8203;1122](https://github.com/misospace/pr-reviewer-action/issues/1122)) ([c9a0c0e](https://github.com/misospace/pr-reviewer-action/commit/c9a0c0e242027fe52e91972011560213108bfa8a)) - **deps:** update dependency astro (5.18.2 → 7.4.0) ([#&#8203;1091](https://github.com/misospace/pr-reviewer-action/issues/1091)) ([4e22d0d](https://github.com/misospace/pr-reviewer-action/commit/4e22d0d0df17f8bf609fd6301b0dee26aa39983d)) - **findings:** actionable suggestions and durable usefulness feedback ([#&#8203;1101](https://github.com/misospace/pr-reviewer-action/issues/1101)) ([6db0b06](https://github.com/misospace/pr-reviewer-action/commit/6db0b063586f885e105111920103f7d1a7b8dd03)) - **reviewer:** stamp provenance on related-code corpus snippets ([#&#8203;1104](https://github.com/misospace/pr-reviewer-action/issues/1104)) ([041c68d](https://github.com/misospace/pr-reviewer-action/commit/041c68d239a87255910962939e4cf0056e9f33da)) - **review:** opt-in trusted-base repository skills ([#&#8203;1081](https://github.com/misospace/pr-reviewer-action/issues/1081)) ([154ead3](https://github.com/misospace/pr-reviewer-action/commit/154ead31350475fc2ba85d2c6ff5790cb0e3ed68)) ##### Bug Fixes - **[#&#8203;1024](https://github.com/misospace/pr-reviewer-action/issues/1024):** bind Forgejo event hints to signed payload action ([#&#8203;1103](https://github.com/misospace/pr-reviewer-action/issues/1103)) ([b2fafa0](https://github.com/misospace/pr-reviewer-action/commit/b2fafa00c5c265b5d0aed27d050d1d22d6e71730)) - **[#&#8203;1037](https://github.com/misospace/pr-reviewer-action/issues/1037):** mask configured extra-header values on provider response surfaces ([#&#8203;1094](https://github.com/misospace/pr-reviewer-action/issues/1094)) ([20d3dc9](https://github.com/misospace/pr-reviewer-action/commit/20d3dc9a5d28012096294841d17d291274644f7f)) - **[#&#8203;1044](https://github.com/misospace/pr-reviewer-action/issues/1044):** surface the requirement-trace repair-pass outcome in the artifact and rendered trace ([#&#8203;1105](https://github.com/misospace/pr-reviewer-action/issues/1105)) ([47fa8cf](https://github.com/misospace/pr-reviewer-action/commit/47fa8cf7c3eb80b7539954f6c5aa8cb6c163db82)) - **[#&#8203;1093](https://github.com/misospace/pr-reviewer-action/issues/1093):** trusted Forgejo owner identity; no empty inline reviews on clean re-review ([#&#8203;1097](https://github.com/misospace/pr-reviewer-action/issues/1097)) ([82d4cbc](https://github.com/misospace/pr-reviewer-action/commit/82d4cbc54decdc4b721cf0aaa9e5f4f721429c75)) - **[#&#8203;1098](https://github.com/misospace/pr-reviewer-action/issues/1098):** GitHub sticky upsert only patches trusted-owner comments ([#&#8203;1100](https://github.com/misospace/pr-reviewer-action/issues/1100)) ([2e7adfb](https://github.com/misospace/pr-reviewer-action/commit/2e7adfb7fe8a3ce31949df2f710779b02257b36b)) - **[#&#8203;1099](https://github.com/misospace/pr-reviewer-action/issues/1099):** resolve trusted owner once per publish run ([#&#8203;1109](https://github.com/misospace/pr-reviewer-action/issues/1109)) ([37fccd2](https://github.com/misospace/pr-reviewer-action/commit/37fccd28d7a107145e65e2ad30b8ad787cccdaf7)) - **[#&#8203;1102](https://github.com/misospace/pr-reviewer-action/issues/1102):** bind check update event kinds to signed payload shape ([#&#8203;1106](https://github.com/misospace/pr-reviewer-action/issues/1106)) ([82c862f](https://github.com/misospace/pr-reviewer-action/commit/82c862f4822b9689c6bcdf5e9adeed6fa2c80ab0)) - **[#&#8203;1107](https://github.com/misospace/pr-reviewer-action/issues/1107):** reserve model suggestion openers and unify feedback precheck ([#&#8203;1110](https://github.com/misospace/pr-reviewer-action/issues/1110)) ([09a05ed](https://github.com/misospace/pr-reviewer-action/commit/09a05ed8e4d5970bc3ffa9adf925ae59e5474d52)) - **[#&#8203;1114](https://github.com/misospace/pr-reviewer-action/issues/1114):** minimize superseded advisory reviews on incomplete re-runs ([#&#8203;1129](https://github.com/misospace/pr-reviewer-action/issues/1129)) ([2376d50](https://github.com/misospace/pr-reviewer-action/commit/2376d5073948fe1bb6c84b7985ff5014206152ed)) - **ci:** follow the fork workflow rename ([05fe106](https://github.com/misospace/pr-reviewer-action/commit/05fe10694099333a178c455e35da2db37f72d619)) - **ci:** follow the fork workflow rename ([99836fd](https://github.com/misospace/pr-reviewer-action/commit/99836fd12e5264e55229ca4e9e03d1f4731d0059)) - **requirement-trace:** stop process/risk notes forcing CHANGES_REQUESTED ([#&#8203;1095](https://github.com/misospace/pr-reviewer-action/issues/1095)) ([#&#8203;1096](https://github.com/misospace/pr-reviewer-action/issues/1096)) ([584ca94](https://github.com/misospace/pr-reviewer-action/commit/584ca940ede94718352471a5f268211ea04fafb0)) ##### Performance Improvements - **[#&#8203;1078](https://github.com/misospace/pr-reviewer-action/issues/1078):** memoize fixture integrity and fail fast on bad corpora ([#&#8203;1111](https://github.com/misospace/pr-reviewer-action/issues/1111)) ([bda231b](https://github.com/misospace/pr-reviewer-action/commit/bda231b908a96818d1f02d24eb18ffaa7e4ddc02)) ##### Documentation - add release-notes house style guide ([#&#8203;1082](https://github.com/misospace/pr-reviewer-action/issues/1082)) ([438f090](https://github.com/misospace/pr-reviewer-action/commit/438f090c5dae2ae8b7e17bc9db376da237a1d371)) </details> ### [`v3.5.0`](https://github.com/misospace/pr-reviewer-action/releases/tag/v3.5.0) [Compare Source](https://github.com/misospace/pr-reviewer-action/compare/v3.4.1...v3.5.0) 3.5.0 is about **lanes**. Until now every model lane — primary, smart, fallback, specialists — was effectively a clone of the primary's request shape, and "does this need a human?" lived nowhere outside the model's prose. This release makes each lane independently configurable, makes structured output on the Anthropic wire *honest* about what it actually enforces, and adds a first-class human-review triage that can route to the right reviewer deterministically. It's also the biggest groundwork release yet for the self-hosted controller: the Forgejo ingress, the durable review queue, and the Tangled read seam all landed as libraries. None of it is wired into the Action runtime — Action users should notice exactly nothing there. If your lanes run against different backends, this is the release to pin: ```yaml - uses: misospace/pr-reviewer-action@v3 with: ai-base-url: ${{ vars.AI_BASE_URL }} ai-api-key: ${{ secrets.AI_API_KEY }} ai-model: ${{ vars.AI_MODEL }} ai-response-format: json_schema # base default ai-smart-response-format: json_schema # smart lane keeps structured output ai-fallback-response-format: off # fallback model rejects the parameter ai-specialist-reasoning-effort: high # specialists think harder than primary ``` #### Model lanes stop being clones - **Response format is lane-aware** ([#&#8203;1040](https://github.com/misospace/pr-reviewer-action/issues/1040), closes [#&#8203;1009](https://github.com/misospace/pr-reviewer-action/issues/1009)): `ai-primary-response-format`, `ai-smart-response-format` and `ai-fallback-response-format` override `ai-response-format` per lane; unset lanes inherit, so single-value workflows stay request-byte compatible. The motivating shape: a primary behind a proxy that rejects `response_format` no longer forces `off` onto every other lane, and the reviewer-requested smart re-review ([#&#8203;721](https://github.com/misospace/pr-reviewer-action/issues/721)) can opt into richer `json_schema`. - **Reasoning effort is profile-aware, on both wire families** ([#&#8203;1049](https://github.com/misospace/pr-reviewer-action/issues/1049), closes [#&#8203;998](https://github.com/misospace/pr-reviewer-action/issues/998)): `ai-reasoning-effort` gains per-lane overrides (`ai-primary-…`, `ai-smart-…`, `ai-specialist-…`, `ai-fallback-…`). OpenAI-compatible requests send `reasoning_effort`; Anthropic requests send `output_config.effort` — but only under that lane's own `*-anthropic-effort-support` assertion, never inherited from another lane. The fallback lane inherits the base *effort* on purpose ([#&#8203;965](https://github.com/misospace/pr-reviewer-action/issues/965): availability recovery, never quality escalation) yet asserts its own *endpoint*, because `ai-fallback-base-url` may be a different backend entirely. - **Anthropic structured output got truthful** ([#&#8203;1047](https://github.com/misospace/pr-reviewer-action/issues/1047)): previously `ai-response-format: json_schema` on `ai-api-format: anthropic` was accepted and then silently omitted — operators believed the schema was enforced when it was only prompted. Now Anthropic-format requests carry no structured-output parameter unless the lane's `*-anthropic-structured-output-support` opt-in is set, the run logs what is actually enforced, and if a wrong assertion draws a 400 naming the parameter, the request retries once without it so the review degrades to prompted JSON instead of failing. - **Specialists survive model misbehavior**: streamed Anthropic overruns are detected instead of accepted, completion-limit replies with zero leads are retried, malformed no-lead responses classify as parser errors (retryable) rather than fatal, overrun-recovery retries are reported only when actually adopted, and the specialist completion budget is now a real input — `deep-review-max-tokens`, default `16384`, independent of `ai-max-tokens` — enforced across every surface. - **Smart-tier limits are yours to set** ([#&#8203;1032](https://github.com/misospace/pr-reviewer-action/issues/1032), closes [#&#8203;1020](https://github.com/misospace/pr-reviewer-action/issues/1020)): `smart-tool-max-rounds` and `smart-tool-loop-wall-clock-sec` bound only the post-review escalation rerun, leaving the primary loop untouched. Empty inherits the previous scaling behavior. #### Ask a human, deterministically - **Opt-in triage** ([#&#8203;1051](https://github.com/misospace/pr-reviewer-action/issues/1051), closes [#&#8203;1003](https://github.com/misospace/pr-reviewer-action/issues/1003)): `review-triage: true` makes the reviewer answer a tri-state "does this PR need specialized/owning human review?" — `not_required`, `required`, or `unknown`, fail-closed to `unknown` when the answer is missing or malformed. It's advisory only: it never moves the verdict, findings, or any tool/access gating, and with the input off the outputs stay empty — "did not run" is never confused with "no work". - **Deterministic routing** ([#&#8203;1005](https://github.com/misospace/pr-reviewer-action/issues/1005)): with `review-triage-routing-mode: request`, a triage of `required` additively requests reviewers. The model can only pick logical target ids declared in the trusted base-ref `.github/pr-reviewer-routing.yml`; the action maps those ids to concrete users/teams, requests are idempotent and never remove existing reviewers, and an unknown target or any uncertain state mutates nothing. Never on forks. `advisory` mode publishes the routing plan without touching the forge, for safe dogfooding. (GitHub-only; Forgejo degrades to `request_failed`.) ```yaml # .github/pr-reviewer-routing.yml (read from the base ref) targets: platform: users: [alice] teams: [platform-team] security: teams: [security] ``` #### Provenance you can check - **Source-claim blockers verify against the exact head** ([#&#8203;1033](https://github.com/misospace/pr-reviewer-action/issues/1033), closes [#&#8203;1016](https://github.com/misospace/pr-reviewer-action/issues/1016)): a finding whose blocker rests on repository source is now verified against the source at the reviewed revision, not a stale or sanitized stand-in. - **Provenance rides through tool output** ([#&#8203;1029](https://github.com/misospace/pr-reviewer-action/issues/1029), closes [#&#8203;1015](https://github.com/misospace/pr-reviewer-action/issues/1015)): source evidence the model sees through native tools carries the same committed-vs-sanitized provenance discipline as the corpus, so a citation the reviewer makes is checkable against what it actually read. - **Non-code criteria stop falsely blocking** ([#&#8203;1062](https://github.com/misospace/pr-reviewer-action/issues/1062)): requirement-trace acceptance criteria that demand no code change no longer block approval. - **Publish fails closed on bad data** ([#&#8203;1079](https://github.com/misospace/pr-reviewer-action/issues/1079), [#&#8203;1050](https://github.com/misospace/pr-reviewer-action/issues/1050)): malformed requested-reviewers responses abort the publication path rather than guessing, and superseded managed inline comments are retired safely instead of piling up on long-lived PRs. - **No-diff runs can't claim coverage** ([#&#8203;1031](https://github.com/misospace/pr-reviewer-action/issues/1031), closes [#&#8203;1026](https://github.com/misospace/pr-reviewer-action/issues/1026)): partitioned reviews fail closed when the no-diff path would have reported coverage it never gathered, and outcomes are bound to the plan round that produced them. - **Fingerprints stay honest**: changing the effective triage routing mode ([#&#8203;1005](https://github.com/misospace/pr-reviewer-action/issues/1005)) or leaving a fallback effort unset now changes the review fingerprint, so config edits trigger a fresh review instead of riding a stale skip. #### Forgejo - **CI status discovery works on Forgejo v16** ([#&#8203;1046](https://github.com/misospace/pr-reviewer-action/issues/1046)): the review job no longer times out against the v16 API. - **`authorized_integration` auth fixed** ([#&#8203;1045](https://github.com/misospace/pr-reviewer-action/issues/1045)), plus a dedicated `forgejo-token` input so the Forgejo token can differ from the GitHub-compatible one, and a `forgejo-auth-method` input to pick between token and OIDC authorized-integration modes. #### Toward the self-hosted controller Shipped as libraries, exercised by tests, consumed by controller work ahead — the normal Action runtime doesn't touch any of it yet, and that's deliberate. - **Forgejo ingress** ([#&#8203;1019](https://github.com/misospace/pr-reviewer-action/issues/1019), closes [#&#8203;730](https://github.com/misospace/pr-reviewer-action/issues/730)): webhook signature verification before parse (fail closed), native-vocabulary projection, and missed-webhook reconciliation — the daemon's front door, with the contract details in `docs/architecture/self-hosted-forgejo-ingress.md`. - **Durable review queue** ([#&#8203;1021](https://github.com/misospace/pr-reviewer-action/issues/1021), closes [#&#8203;731](https://github.com/misospace/pr-reviewer-action/issues/731)): 8-state job records, settle/debounce windows that collapse bursts, at-most-one-active-generation per PR, head supersession, lease/heartbeat dispatch with bounded retry — the scheduler's brain. (`docs/architecture/durable-review-queue.md`) - **Tangled read seam** ([#&#8203;1013](https://github.com/misospace/pr-reviewer-action/issues/1013), [#&#8203;1012](https://github.com/misospace/pr-reviewer-action/issues/1012), closes [#&#8203;585](https://github.com/misospace/pr-reviewer-action/issues/585), [#&#8203;586](https://github.com/misospace/pr-reviewer-action/issues/586)): pull metadata normalized into the platform seam, and the latest pull round fetched with patch-blob diff/files normalized into review inputs. Groundwork — Tangled review support is not complete yet. - **One forge capability for Python tooling** ([#&#8203;1039](https://github.com/misospace/pr-reviewer-action/issues/1039), closes [#&#8203;1041](https://github.com/misospace/pr-reviewer-action/issues/1041)): every Python tool's reads and writes route through `pr_reviewer.forge` — one URL/token resolution, a redirect-safe transport that never copies the `Authorization` header onto a redirect, and an HTTPS-only base-URL guard that raises before any byte hits the wire. The `gh api` error-echo surface is gone with it. - **Reproducible eval lanes** ([#&#8203;1022](https://github.com/misospace/pr-reviewer-action/issues/1022), closes [#&#8203;967](https://github.com/misospace/pr-reviewer-action/issues/967)): heterogeneous model/profile lanes for the eval harness, so A/B results across different models reproduce. #### Upgrading Pin to `v3.5.0`, or the floating `v3` tag, which now follows this build. Immutable-version and SHA pins must be bumped deliberately. Nothing breaks and no input changed meaning. The honest notes: - **All new inputs are opt-in with empty/false defaults**, and leave request bytes unchanged when unset. The one to be deliberate about: on Anthropic-format lanes, `ai-response-format: json_schema` was *never actually sent* before — it only looked like it was. If you want native enforcement, set `ai-anthropic-structured-output-support` (and the lane variants) only after confirming the endpoint accepts `output_config.format`. - **Specialist completions** now default to a `16384` cap (`deep-review-max-tokens`), independent of `ai-max-tokens`; deep-review runs may spend more tokens per role. - **Requirement-trace users**: non-code acceptance criteria no longer block approval ([#&#8203;1062](https://github.com/misospace/pr-reviewer-action/issues/1062)) — one behavior changed in the direction of blocking less. Every input's current contract lives in [docs/inputs.md](https://github.com/misospace/pr-reviewer-action/blob/v3.5.0/docs/inputs.md). **Full changelog:** <https://github.com/misospace/pr-reviewer-action/compare/v3.4.1...v3.5.0> <details> <summary>Generated changelog (release-please)</summary> ##### Features - **eval:** reproducible heterogeneous model/profile lanes for [#&#8203;967](https://github.com/misospace/pr-reviewer-action/issues/967) ([#&#8203;1022](https://github.com/misospace/pr-reviewer-action/issues/1022)) ([492c743](https://github.com/misospace/pr-reviewer-action/commit/492c743f89afa2eddf233c08b80a5682b2388297)) - **forge:** route Python tooling through a configured forge capability ([#&#8203;1041](https://github.com/misospace/pr-reviewer-action/issues/1041)) ([#&#8203;1039](https://github.com/misospace/pr-reviewer-action/issues/1039)) ([c235b7d](https://github.com/misospace/pr-reviewer-action/commit/c235b7d5f1c2f91e5260b73fa25f2a9ffede59b5)) - **ingress:** self-hosted Forgejo webhook/auth/reconciliation adapter ([#&#8203;730](https://github.com/misospace/pr-reviewer-action/issues/730)) ([#&#8203;1019](https://github.com/misospace/pr-reviewer-action/issues/1019)) ([c16c85b](https://github.com/misospace/pr-reviewer-action/commit/c16c85b0e708ac8f71e6e72cd343b540c8f21e35)) - **model:** allow response-format overrides per model lane ([#&#8203;1009](https://github.com/misospace/pr-reviewer-action/issues/1009)) ([#&#8203;1040](https://github.com/misospace/pr-reviewer-action/issues/1040)) ([20cab2d](https://github.com/misospace/pr-reviewer-action/commit/20cab2d572ae5967cdc745d7da42cd46f8dfc16c)) - **model:** independent ai-fallback-reasoning-effort override ([#&#8203;1053](https://github.com/misospace/pr-reviewer-action/issues/1053)) ([cd20d43](https://github.com/misospace/pr-reviewer-action/commit/cd20d435205fc20efed9886a6dfdc7784e45f7f9)) - **model:** independent ai-fallback-reasoning-effort override ([#&#8203;1053](https://github.com/misospace/pr-reviewer-action/issues/1053)) ([51cad39](https://github.com/misospace/pr-reviewer-action/commit/51cad39880d2b745874499ed32ba5b394e7d7b56)) - **model:** per-profile reasoning effort for OpenAI and Anthropic ([#&#8203;998](https://github.com/misospace/pr-reviewer-action/issues/998)) ([#&#8203;1049](https://github.com/misospace/pr-reviewer-action/issues/1049)) ([01dda91](https://github.com/misospace/pr-reviewer-action/commit/01dda91efa706a0cb62a59fb30cbd852215d0ed0)) - **queue:** durable review-queue scheduling semantics ([#&#8203;731](https://github.com/misospace/pr-reviewer-action/issues/731)) ([#&#8203;1021](https://github.com/misospace/pr-reviewer-action/issues/1021)) ([e9582f5](https://github.com/misospace/pr-reviewer-action/commit/e9582f532b22ef0db56c20ae03563bf9616a19d4)) - **tangled:** fetch latest pull round and normalize patch-blob diff/files ([#&#8203;586](https://github.com/misospace/pr-reviewer-action/issues/586)) ([#&#8203;1012](https://github.com/misospace/pr-reviewer-action/issues/1012)) ([e7db913](https://github.com/misospace/pr-reviewer-action/commit/e7db913365d4e89a792dee30164cf712bcd221a4)) - **tangled:** normalize pull metadata into the platform read seam ([#&#8203;585](https://github.com/misospace/pr-reviewer-action/issues/585)) ([#&#8203;1013](https://github.com/misospace/pr-reviewer-action/issues/1013)) ([aa12fff](https://github.com/misospace/pr-reviewer-action/commit/aa12fffaf9d31abd0775fda8fbbaeba91194be29)) - **triage:** add first-class human-review triage output ([#&#8203;1003](https://github.com/misospace/pr-reviewer-action/issues/1003)) ([#&#8203;1051](https://github.com/misospace/pr-reviewer-action/issues/1051)) ([9cf25c8](https://github.com/misospace/pr-reviewer-action/commit/9cf25c8412beefc1fbc71a9d13965bfe8af5a5ee)) - **triage:** route required human review to trusted reviewer targets ([#&#8203;1005](https://github.com/misospace/pr-reviewer-action/issues/1005)) ([bcdda85](https://github.com/misospace/pr-reviewer-action/commit/bcdda85118bef65e3c8a40d5c698d4efab73fa46)) - **triage:** route required human review to trusted reviewer targets ([#&#8203;1005](https://github.com/misospace/pr-reviewer-action/issues/1005)) ([3d4ec70](https://github.com/misospace/pr-reviewer-action/commit/3d4ec70085a09d5a77f02ee0e43ee98c89dc2622)) ##### Bug Fixes - **ci:** repair dogfood regressions and retire obsolete Python test debt ([#&#8203;1060](https://github.com/misospace/pr-reviewer-action/issues/1060)) ([afd5013](https://github.com/misospace/pr-reviewer-action/commit/afd50132f1bb87b1a174b5a4515fb7c4d978891c)) - **classification:** treat self-location readlink as trusted path bookkeeping ([#&#8203;1034](https://github.com/misospace/pr-reviewer-action/issues/1034)) ([#&#8203;1042](https://github.com/misospace/pr-reviewer-action/issues/1042)) ([92424f9](https://github.com/misospace/pr-reviewer-action/commit/92424f95006e478ce5152fba9377d67551696df1)) - **config:** preserve unset fallback effort in hash ([c6630d7](https://github.com/misospace/pr-reviewer-action/commit/c6630d7051fba50815c0764396d8f2cac272b223)) - **deps:** update dependency [@&#8203;types/node](https://github.com/types/node) (24.19.1 → 24.19.2) ([#&#8203;1023](https://github.com/misospace/pr-reviewer-action/issues/1023)) ([e44a237](https://github.com/misospace/pr-reviewer-action/commit/e44a23736f38de52e175cef8e75886072ed07028)) - **enforcement:** confirm documentation trace rows only from their named target source ([86229e0](https://github.com/misospace/pr-reviewer-action/commit/86229e0ba078d900908302549552eb0a1e2be334)) - **enforcement:** harden documentation scan per independent review ([259de11](https://github.com/misospace/pr-reviewer-action/commit/259de11f78e39a5d35647d668f09394e4c3169d4)) - **forgejo:** Fix CI timeout on V16 API ([#&#8203;1046](https://github.com/misospace/pr-reviewer-action/issues/1046)) ([8350071](https://github.com/misospace/pr-reviewer-action/commit/83500713ca546772eb31a7bb1f4e7adfbdc51c1a)) - **forgejo:** Fix Forgejo authorized_integration mode ([#&#8203;1045](https://github.com/misospace/pr-reviewer-action/issues/1045)) ([6b38cbe](https://github.com/misospace/pr-reviewer-action/commit/6b38cbe0e32de71ea7bc0510816cc53412b80b1b)) - **ingress:** bind reconciliation jobs to the configured repository ([#&#8203;1025](https://github.com/misospace/pr-reviewer-action/issues/1025)) ([#&#8203;1052](https://github.com/misospace/pr-reviewer-action/issues/1052)) ([d1cff53](https://github.com/misospace/pr-reviewer-action/commit/d1cff53a6b33ec7b59a428e6ea9ec83b830bc4c2)) - **model:** declare review_triage_targets in strict OpenAI verdict schemas ([aec5111](https://github.com/misospace/pr-reviewer-action/commit/aec51114db9bf60b98f419065a98f7f3d120f0e4)) - **model:** make Anthropic structured-output semantics truthful and recover usable verdicts ([7a7e130](https://github.com/misospace/pr-reviewer-action/commit/7a7e1308f88e068ae21997e567b8e5cdbbae0c41)) - **model:** make Anthropic structured-output semantics truthful and recover usable verdicts ([816927b](https://github.com/misospace/pr-reviewer-action/commit/816927bd27feffb63820333386bbe5ac0491c10f)) - **model:** mask configured secrets before diagnostic truncation; specialist response-format via tierResponseFormat ([f533d65](https://github.com/misospace/pr-reviewer-action/commit/f533d656999e35e8a1ba097f98f703b890cbcb66)) - **model:** report the effective wire format after a 400 strip recovery; CodeQL cleanup ([f183288](https://github.com/misospace/pr-reviewer-action/commit/f183288d98fb6b6ab15ba92f80e2590eebc442dd)) - **partition:** fail-closed no-diff coverage and bind outcomes to plan round ([#&#8203;1026](https://github.com/misospace/pr-reviewer-action/issues/1026)) ([#&#8203;1031](https://github.com/misospace/pr-reviewer-action/issues/1031)) ([55ecf00](https://github.com/misospace/pr-reviewer-action/commit/55ecf0050f260ea56180a146844c444afc873354)) - **precheck:** fingerprint the effective triage routing mode ([20ff2e2](https://github.com/misospace/pr-reviewer-action/commit/20ff2e2122b3b75154ba063af5da63249447e089)) - **publish:** fail closed on a malformed requested-reviewers GET ([#&#8203;1079](https://github.com/misospace/pr-reviewer-action/issues/1079)) ([5738670](https://github.com/misospace/pr-reviewer-action/commit/5738670be1ca48a9ec403eeabf646fbf8c558180)) - **publish:** safely retire superseded managed inline comments ([#&#8203;1050](https://github.com/misospace/pr-reviewer-action/issues/1050)) ([cc1fa07](https://github.com/misospace/pr-reviewer-action/commit/cc1fa074cc486da697616e49f2c485058feebb75)) - **requirement-trace:** stop non-code acceptance criteria falsely blocking approval ([#&#8203;1062](https://github.com/misospace/pr-reviewer-action/issues/1062)) ([50bf601](https://github.com/misospace/pr-reviewer-action/commit/50bf6015ffb47db859a8e17635fbe1dc80be0a74)) - **requirement-trace:** stop non-code acceptance criteria falsely blocking approval ([#&#8203;1062](https://github.com/misospace/pr-reviewer-action/issues/1062)) ([8f93a01](https://github.com/misospace/pr-reviewer-action/commit/8f93a010c5376cb33ab8aecff943407e9bc4df95)) - **reviewer:** carry source-evidence provenance through model-visible tool output ([#&#8203;1015](https://github.com/misospace/pr-reviewer-action/issues/1015)) ([#&#8203;1029](https://github.com/misospace/pr-reviewer-action/issues/1029)) ([afe282f](https://github.com/misospace/pr-reviewer-action/commit/afe282f5fa3e5b343946f9d927c165db20286cf5)) - **specialists:** apply overrun recovery to the combined-scout path ([6fcb154](https://github.com/misospace/pr-reviewer-action/commit/6fcb154bddcfba352349e7e20f2176b0e0598c56)) - **specialists:** classify malformed/no-lead responses as parser ([2bfa3ca](https://github.com/misospace/pr-reviewer-action/commit/2bfa3ca3ef6042571737595f72e0a20d739b98d9)) - **specialists:** detect Anthropic overruns, raise cap ([4abbfb1](https://github.com/misospace/pr-reviewer-action/commit/4abbfb18e0ed510712bbd93f0bb58957a390fded)) - **specialists:** detect streamed Anthropic overruns and raise the default cap to 16K ([d60da4a](https://github.com/misospace/pr-reviewer-action/commit/d60da4abe3e0e024a084b7bd2f898c21b1738565)) - **specialists:** only report overrun recovery when the retry is adopted ([d54ab2b](https://github.com/misospace/pr-reviewer-action/commit/d54ab2bcd12590064a80d823d316a3b7c0a57b62)) - **specialists:** retry completion-limit responses with zero leads ([5d23b68](https://github.com/misospace/pr-reviewer-action/commit/5d23b689cd6abe8ffe6cbafe30a97f614de778a9)) - **tools:** make smart-tier loop round and wall-clock limits settable ([#&#8203;1020](https://github.com/misospace/pr-reviewer-action/issues/1020)) ([#&#8203;1032](https://github.com/misospace/pr-reviewer-action/issues/1032)) ([f5b3e11](https://github.com/misospace/pr-reviewer-action/commit/f5b3e115d1c3f805eda479040025552c00b1f623)) ##### Performance Improvements - **ci:** stop tests paying the real transport backoff ([8b8f0d1](https://github.com/misospace/pr-reviewer-action/commit/8b8f0d16b5348c07f5f62a210e8b9f093f683ce3)) - **ci:** stop tests paying the real transport backoff ([4fd2a05](https://github.com/misospace/pr-reviewer-action/commit/4fd2a052055736312c341ad40a819f5593f64768)) ##### Chores - **test:** drop unreferenced dogfood-623 and test-evidence artifacts ([496e2d0](https://github.com/misospace/pr-reviewer-action/commit/496e2d052ab9d8e0640e89ce7b75c402fc2a9a77)) - **test:** drop unreferenced dogfood-623 and test-evidence artifacts ([e1d1ff8](https://github.com/misospace/pr-reviewer-action/commit/e1d1ff826457d45f4def6fea5563f00503022048)), closes [#&#8203;1063](https://github.com/misospace/pr-reviewer-action/issues/1063) ##### Documentation - **agents:** align normative guidance with shipped v3 action ([#&#8203;1055](https://github.com/misospace/pr-reviewer-action/issues/1055)) ([34d68f1](https://github.com/misospace/pr-reviewer-action/commit/34d68f17e57751e7279fc2391a3277e67c461ef0)) - **ci:** record the observed after-CI numbers ([67d2f16](https://github.com/misospace/pr-reviewer-action/commit/67d2f16bd4bb61224ade6d81787ebf194a7c2fda)) - **requirement-trace:** pin non-code proof shapes in contract doc ([bf6a2b2](https://github.com/misospace/pr-reviewer-action/commit/bf6a2b2de45451e3792c1bd77ba297b9e8fb50b2)) ##### Refactors - **config:** drop no-op Action-input carve-outs ([68b7f61](https://github.com/misospace/pr-reviewer-action/commit/68b7f61a46a02d45ee3fba56e950ec05d07b044a)) - **config:** drop no-op Action-input carve-outs ([027e94c](https://github.com/misospace/pr-reviewer-action/commit/027e94c4171889ec5e41bbb09876d2bc46847a6d)) - **run:** extract the step-summary seam from runReview ([afdef1c](https://github.com/misospace/pr-reviewer-action/commit/afdef1cb63f8f99e831b16f78abd3e2cc6fc9805)) - **run:** extract the step-summary seam from runReview ([7a82877](https://github.com/misospace/pr-reviewer-action/commit/7a828779f1f35b8b85f56cf967544a23c6b80c39)) </details> </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Rome) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTEuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE2Ny41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9naXRodWItYWN0aW9uIiwicmVub3ZhdGUvZ2l0aHViLXJlbGVhc2UiLCJ0eXBlL21pbm9yIl19-->
ci(github-action): update action https://github.com/misospace/pr-reviewer-action (v3.4.1 ➔ v3.5.0)
Some checks failed
Konflate 0 resources changed
Labeler / Labeler (pull_request) Successful in 3s
Lint / actionlint (pull_request) Failing after 12s
Lint / yamllint (pull_request) Failing after 16s
AI PR Review / AI PR Review (pull_request) Successful in 1m26s
aa0208f33f
Collaborator

No rendered changes.

konflate 0.6.6 · rendered f7fb1bd · full diff →

<!-- konflate:pr-2407 --> No rendered changes. <sub>konflate 0.6.6 · rendered `f7fb1bd` · [full diff →](https://konflate.aresu.eu/#/pr/2407)</sub>

AI Automated Review

Analysis engine: minimax/MiniMax-M2-7-anthropic (anthropic) — primary route · pr-reviewer-action v3.6.0

Approve — Renovate dependency update for misospace/pr-reviewer-action from v3.4.1 → v3.6.0.

The diff is a single SHA-pin change in .forgejo/workflows/pr-reviewer.yaml with no other parameter modifications. Konflate confirms zero rendered cluster changes. All upstream release notes (14 bug fixes, 6 features, 1 performance improvement) affect the action's internal logic only and are additive; none introduce breaking changes to action inputs or output contracts. No repository standards conflict. No cluster resources affected.

<!-- ai-pr-reviewer --> <!-- ai-pr-reviewer:{"version":1,"head_sha":"e2cc592db7575177e50c1d7585cfa727f98fb24f","base_sha":"908a649f3d7832e331e2b5c217fa367faef85460","review_result":"clean","review_route":"primary","cache_hit_ratio":0.206,"tool_budget":24,"tool_budget_source":"tier-default","tool_calls":8,"tool_rounds":7,"max_rounds":24,"context_budget":65536,"context_peak":19718,"action_version":"v3.6.0","tool_stop_reason":"model-stopped"} --> <!-- ai-pr-review-sha:e2cc592db7575177e50c1d7585cfa727f98fb24f --> <!-- ai-pr-review-fingerprint:2726db82432ad79a98756ac997759d8c123b070c3091201563e7cf99a9770230|cfg:77e7b09f23dfa8e93696918a40220a51664214408456cf36804c4c7c0bc8cb88 --> # AI Automated Review _Analysis engine: minimax/MiniMax-M2-7-anthropic (anthropic) — primary route · pr-reviewer-action v3.6.0_ **Approve** — Renovate dependency update for `misospace/pr-reviewer-action` from v3.4.1 → v3.6.0. The diff is a single SHA-pin change in `.forgejo/workflows/pr-reviewer.yaml` with no other parameter modifications. Konflate confirms zero rendered cluster changes. All upstream release notes (14 bug fixes, 6 features, 1 performance improvement) affect the action's internal logic only and are additive; none introduce breaking changes to action inputs or output contracts. No repository standards conflict. No cluster resources affected.
renovate-bot force-pushed renovate/https-github.com-misospace-pr-reviewer-action-3.x from aa0208f33f
Some checks failed
Konflate 0 resources changed
Labeler / Labeler (pull_request) Successful in 3s
Lint / actionlint (pull_request) Failing after 12s
Lint / yamllint (pull_request) Failing after 16s
AI PR Review / AI PR Review (pull_request) Successful in 1m26s
to a63367ff63
Some checks failed
Labeler / Labeler (pull_request) Successful in 11s
Lint / actionlint (pull_request) Failing after 22s
Lint / yamllint (pull_request) Failing after 19s
AI PR Review / AI PR Review (pull_request) Successful in 1m34s
Konflate 0 resources changed
2026-10-16 22:19:41 +02:00
Compare
renovate-bot changed title from ci(github-action): update action https://github.com/misospace/pr-reviewer-action (v3.4.1 ➔ v3.5.0) to ci(github-action): update action https://github.com/misospace/pr-reviewer-action (v3.4.1 ➔ v3.6.0) 2026-10-18 22:02:08 +02:00
renovate-bot force-pushed renovate/https-github.com-misospace-pr-reviewer-action-3.x from a63367ff63
Some checks failed
Labeler / Labeler (pull_request) Successful in 11s
Lint / actionlint (pull_request) Failing after 22s
Lint / yamllint (pull_request) Failing after 19s
AI PR Review / AI PR Review (pull_request) Successful in 1m34s
Konflate 0 resources changed
to e2cc592db7
Some checks failed
Labeler / Labeler (pull_request) Successful in 4s
Lint / actionlint (pull_request) Failing after 15s
Lint / yamllint (pull_request) Failing after 20s
AI PR Review / AI PR Review (pull_request) Successful in 1m14s
Konflate 0 resources changed
2026-10-18 22:02:09 +02:00
Compare
renovate-bot force-pushed renovate/https-github.com-misospace-pr-reviewer-action-3.x from e2cc592db7
Some checks failed
Labeler / Labeler (pull_request) Successful in 4s
Lint / actionlint (pull_request) Failing after 15s
Lint / yamllint (pull_request) Failing after 20s
AI PR Review / AI PR Review (pull_request) Successful in 1m14s
Konflate 0 resources changed
to f7fb1bdcdc
Some checks failed
AI PR Review / AI PR Review (pull_request) Failing after 3s
Labeler / Labeler (pull_request) Successful in 4s
Lint / actionlint (pull_request) Failing after 13s
Lint / yamllint (pull_request) Failing after 19s
Konflate 0 resources changed
2026-10-20 20:02:24 +02:00
Compare
renovate-bot changed title from ci(github-action): update action https://github.com/misospace/pr-reviewer-action (v3.4.1 ➔ v3.6.0) to ci(github-action): update action https://github.com/misospace/pr-reviewer-action (v3.4.1 ➔ v3.7.0) 2026-10-20 20:02:25 +02:00
GiorgioAresu deleted branch renovate/https-github.com-misospace-pr-reviewer-action-3.x 2026-10-23 09:48:37 +02:00
Sign in to join this conversation.
No description provided.