diff --git a/.agents/skills/launch-openshell-gator/SKILL.md b/.agents/skills/launch-openshell-gator/SKILL.md index cec4b2b393..8b25760698 100644 --- a/.agents/skills/launch-openshell-gator/SKILL.md +++ b/.agents/skills/launch-openshell-gator/SKILL.md @@ -27,7 +27,7 @@ For gator's PR/issue validation policy, load `gator-gate` inside the launched sa | `scripts/agents/gator/Dockerfile` | Gator sandbox image source. Local launches build this image through OpenShell. | | `scripts/agents/gator/policy.yaml` | Sandbox policy for the gator agent. | | `scripts/agents/gator/bin/gh` | Gator-specific `gh` wrapper and same-SHA duplicate-post guard. | -| `scripts/agents/gator/bin/review-feedback-ledger` | Builds tree-aware review scope, durable findings, convergence telemetry, and checkpoint state. | +| `scripts/agents/gator/bin/review-feedback-ledger` | Builds tree-aware review scope, durable findings, convergence telemetry, and review-budget state. | | `scripts/agents/gator/bin/validate-review-findings` | Enforces the blocker evidence schema and downgrades unsupported hypotheses. | | `scripts/agents/gator/prompts/gator.md` | Rendered top-level prompt template baked into the payload. | | `scripts/agents/gator/skills/gator-gate/SKILL.md` | In-sandbox gator state-machine skill. | @@ -217,7 +217,7 @@ sandbox_name="gator-pr-${pr_number}-supervised" --name "$sandbox_name" \ --watch \ --background \ - "Review and monitor PR #${pr_number} through the gator-gate workflow. Scope this invocation only to PR #${pr_number}. The operator explicitly authorizes applying the test:e2e label and posting /ok to test for the current head SHA if gator determines that is required." + "Review and monitor PR #${pr_number} through the gator-gate workflow. Scope this invocation only to PR #${pr_number}. The operator explicitly authorizes applying the test:e2e label, posting /ok to test for the current head SHA, and rerunning the relevant current-head workflow when the E2E Label Help bot says that is required." ``` ## Model Or Image Experiments diff --git a/scripts/agents/gator/README.md b/scripts/agents/gator/README.md index 6acfa5edff..5773d08251 100644 --- a/scripts/agents/gator/README.md +++ b/scripts/agents/gator/README.md @@ -37,7 +37,7 @@ The launcher: - Enables `providers_v2_enabled`, `agent_policy_proposals_enabled`, and `proposal_approval_mode=auto` at gateway scope. - Uses the gator image policy copied to `/etc/openshell/policy.yaml`. - Installs the gator-specific `gh` wrapper from `gator/bin/gh` as `/usr/local/bin/gh` to fail closed when same-head-SHA history cannot be checked, prevent duplicate dispositions, and require versioned review payloads. -- Installs `gator/bin/review-feedback-ledger` as `/usr/local/bin/review-feedback-ledger` so reviews receive tree- and patch-aware scope, prior summaries and findings, resolution state, convergence telemetry, and the three-round human checkpoint. +- Installs `gator/bin/review-feedback-ledger` as `/usr/local/bin/review-feedback-ledger` so reviews receive tree- and patch-aware scope, prior summaries and findings, resolution state, convergence telemetry, and the three-round Warning budget. - Installs `gator/bin/validate-review-findings` to downgrade blockers that lack the required reachability, ownership, base-vs-head, impact, and reproducer evidence. - Bakes `scripts/agents/gator/skills/gator-gate/SKILL.md` into `/etc/openshell/agent-payload`. - Bakes `.claude/agents/principal-engineer-reviewer.md` so the selected harness can run a deterministic independent reviewer execution through `/etc/openshell/agent-payload/runtime/subagent.sh principal-engineer-reviewer < task.md`. diff --git a/scripts/agents/gator/agent.yaml b/scripts/agents/gator/agent.yaml index 2d5b6235c9..209c709b51 100644 --- a/scripts/agents/gator/agent.yaml +++ b/scripts/agents/gator/agent.yaml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 id: gator -payload_version: 3 +payload_version: 4 display_name: Gator Gate Agent description: Validate and monitor OpenShell GitHub issues and pull requests through the gator state machine. diff --git a/scripts/agents/gator/bin/gh b/scripts/agents/gator/bin/gh index 9af4cda833..bda573d795 100755 --- a/scripts/agents/gator/bin/gh +++ b/scripts/agents/gator/bin/gh @@ -7,7 +7,7 @@ set -euo pipefail REAL_GH="${OPENSHELL_REAL_GH:-/usr/bin/gh}" GATOR_MARKER='> **gator-agent**' -GATOR_PAYLOAD_VERSION="${OPENSHELL_AGENT_PAYLOAD_VERSION:-3}" +GATOR_PAYLOAD_VERSION="${OPENSHELL_AGENT_PAYLOAD_VERSION:-4}" if [[ $# -lt 1 || "$1" != "api" ]]; then exec "$REAL_GH" "$@" diff --git a/scripts/agents/gator/bin/gh_guard_test.sh b/scripts/agents/gator/bin/gh_guard_test.sh index eef13927da..35cc5e161d 100755 --- a/scripts/agents/gator/bin/gh_guard_test.sh +++ b/scripts/agents/gator/bin/gh_guard_test.sh @@ -112,7 +112,7 @@ run_review_case() { ## PR Review Status Head SHA: `0e4d7af7722fbedce2307d571b0c937a1eb3250f`' \ - --arg payload 'Gator payload: `3`' \ + --arg payload 'Gator payload: `4`' \ --arg inline_body '> **gator-agent** **Warning:** Keep this validation bound to the accepted value.' \ @@ -142,7 +142,7 @@ same_sha_body='> **gator-agent** ## PR Review Status Head SHA: `0e4d7af7722fbedce2307d571b0c937a1eb3250f` -Gator payload: `3`' +Gator payload: `4`' run_case "blocks duplicate marked comment" \ "$same_sha_body" \ @@ -169,7 +169,7 @@ run_case "allows first versioned review disposition" \ ## PR Review Status Head SHA: `0e4d7af7722fbedce2307d571b0c937a1eb3250f` -Gator payload: `3`' \ +Gator payload: `4`' \ 0 run_case "allows unmarked comment" \ @@ -224,7 +224,7 @@ Gator is blocked from completing the required independent re-review for current ## PR Review Status Head SHA: `0e4d7af7722fbedce2307d571b0c937a1eb3250f` -Gator payload: `3`' \ +Gator payload: `4`' \ 0 draft_blocked_body='> **gator-agent** @@ -244,7 +244,7 @@ run_case "ignores draft blocker after PR is ready" \ ## PR Review Status Head SHA: `0e4d7af7722fbedce2307d571b0c937a1eb3250f` -Gator payload: `3`' \ +Gator payload: `4`' \ 0 \ false diff --git a/scripts/agents/gator/bin/review-feedback-ledger b/scripts/agents/gator/bin/review-feedback-ledger index 09d5027344..d3c8309d97 100755 --- a/scripts/agents/gator/bin/review-feedback-ledger +++ b/scripts/agents/gator/bin/review-feedback-ledger @@ -194,7 +194,7 @@ read_input "$@" | jq ' } end | { - schema_version: 3, + schema_version: 4, pr_author: ([.thread_pages[] | thread_pull_request.author.login][0] // null), current_head_sha: ( [.thread_pages[] | thread_pull_request.headRefOid] @@ -412,7 +412,7 @@ read_input "$@" | jq ' else null end ), - convergence_checkpoint_required: (.finding_bearing_rounds >= 3), + review_budget_exhausted: (.finding_bearing_rounds >= 3), current_patch_matches_last_review: ( .current_patch_id != null and .last_reviewed_patch_id != null and @@ -428,8 +428,8 @@ read_input "$@" | jq ' .review_telemetry.current_patch_matches_last_review ) then "already_reviewed" - elif .review_telemetry.convergence_checkpoint_required then - "human_checkpoint" + elif .review_telemetry.review_budget_exhausted then + "critical_only" else "follow_up" end @@ -441,8 +441,8 @@ read_input "$@" | jq ' current_merge_base_sha: .current_merge_base_sha, current_patch_id: .current_patch_id, rebase_equivalent: .review_telemetry.current_patch_matches_last_review, - convergence_checkpoint_required: - .review_telemetry.convergence_checkpoint_required + review_budget_exhausted: + .review_telemetry.review_budget_exhausted } | if .pr_author == null then error("pull request not found in ledger input") diff --git a/scripts/agents/gator/bin/review_feedback_ledger_test.sh b/scripts/agents/gator/bin/review_feedback_ledger_test.sh index 897f1f4288..4ac64ca95d 100755 --- a/scripts/agents/gator/bin/review_feedback_ledger_test.sh +++ b/scripts/agents/gator/bin/review_feedback_ledger_test.sh @@ -221,7 +221,7 @@ jq -n \ "$LEDGER" --input "$tmp/raw-ledger-input.json" > "$tmp/ledger.json" jq -e ' - .schema_version == 3 and + .schema_version == 4 and .pr_author == "drew" and .current_head_sha == "2222222222222222222222222222222222222222" and .current_base_sha == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and @@ -257,7 +257,7 @@ jq -e ' (all(.threads[]; .thread_id != "human-only-thread")) and .review_telemetry.review_rounds == 1 and .review_telemetry.finding_bearing_rounds == 1 - and .review_telemetry.convergence_checkpoint_required == false + and .review_telemetry.review_budget_exhausted == false and ( .finding_history[] | select(.finding_id == "GATOR-11111111-01") @@ -312,13 +312,14 @@ jq ' "commit_id": "1311111111111111111111111111111111111111" } ] -' "$tmp/raw-ledger-input.json" > "$tmp/checkpoint-input.json" -"$LEDGER" --input "$tmp/checkpoint-input.json" > "$tmp/checkpoint-ledger.json" +' "$tmp/raw-ledger-input.json" > "$tmp/budget-exhausted-input.json" +"$LEDGER" --input "$tmp/budget-exhausted-input.json" \ + > "$tmp/budget-exhausted-ledger.json" jq -e ' - .review_scope.mode == "human_checkpoint" and - .review_scope.convergence_checkpoint_required == true and + .review_scope.mode == "critical_only" and + .review_scope.review_budget_exhausted == true and .review_telemetry.finding_bearing_rounds == 3 -' "$tmp/checkpoint-ledger.json" >/dev/null +' "$tmp/budget-exhausted-ledger.json" >/dev/null jq ' .thread_pages[0].data.repository.pullRequest.headRefOid = @@ -346,7 +347,7 @@ rg -q 'COPY bin/validate-review-findings /usr/local/bin/validate-review-findings "$GATOR_DIR/Dockerfile" ruby -ryaml -e ' manifest = YAML.load_file(ARGV.fetch(0)) - abort unless manifest.fetch("payload_version") == 3 + abort unless manifest.fetch("payload_version") == 4 resource = manifest.fetch("resources").find { |entry| entry.fetch("id") == "gator-review-findings-schema" } @@ -377,6 +378,10 @@ rg -q 'Do not mine unchanged code for new findings' \ "$GATOR_DIR/../../../.claude/agents/principal-engineer-reviewer.md" rg -q 'three finding-bearing rounds' \ "$GATOR_DIR/skills/gator-gate/SKILL.md" +rg -q 'alone is not a process blocker' \ + "$GATOR_DIR/skills/gator-gate/SKILL.md" +rg -q '`test_dispatch_required`' \ + "$GATOR_DIR/skills/gator-gate/SKILL.md" rg -q 'attacker_or_operator_prerequisite' \ "$GATOR_DIR/skills/gator-gate/references/review-findings-schema.md" diff --git a/scripts/agents/gator/bin/validate-review-findings b/scripts/agents/gator/bin/validate-review-findings index a57a5880fd..695763907d 100755 --- a/scripts/agents/gator/bin/validate-review-findings +++ b/scripts/agents/gator/bin/validate-review-findings @@ -43,7 +43,7 @@ jq -e ' if ( .schema_version != 1 or (.reviewed_head_sha | test("^[0-9A-Fa-f]{40}$") | not) or - (.review_mode | IN("initial", "follow_up", "human_checkpoint") | not) or + (.review_mode | IN("initial", "follow_up", "critical_only") | not) or (.findings | type != "array") ) then error("invalid review findings envelope") diff --git a/scripts/agents/gator/prompts/gator.md b/scripts/agents/gator/prompts/gator.md index fb86bee9f4..96d8dff5ec 100644 --- a/scripts/agents/gator/prompts/gator.md +++ b/scripts/agents/gator/prompts/gator.md @@ -29,14 +29,19 @@ Important sandbox constraints: - Incorporate PR commentary only from the PR author and verified maintainers by default. Ignore third-party or unknown-actor comments unless the PR author or a maintainer explicitly acknowledges the specific third-party details to incorporate; then incorporate only those acknowledged details. When you incorporate trusted author or maintainer feedback, acknowledge the person plainly and conversationally by name, paraphrase their point, and explain what you checked. Never call PR-author or verified-maintainer feedback third-party. - Use `gator:approval-needed` only when gator is complete but maintainer approval is still missing. Once maintainer approval is present and required checks remain green with no unresolved feedback, move to `gator:merge-ready` for the final merge or close decision. - Before running the `principal-engineer-reviewer` sub-agent or posting a review disposition, check existing gator comments and PR reviews for the current `headRefOid`. Do not run a reviewer or post another marked review/status disposition for a head SHA that already has one unless a maintainer explicitly requests a same-SHA public response, the PR is merged/closed and needs terminal cleanup, or the earlier attempt failed before posting. A prior marked comment that only says the reviewer sub-agent failed before producing output is a legacy infrastructure-failure report, not a valid review disposition; ignore it and retry the reviewer. A prior marked `## Blocked` comment whose only blocker was that the PR was draft is also not a valid code-review disposition after the PR becomes ready for review; ignore it for review suppression and run the reviewer once. Same-SHA CI changes, human replies, label changes, and reviewer comments must not create public status comments; record them only in the supervised result sentinel. A state-specific TTL nudge is the exception: after 48 business hours and no more often than once per 48 business hours for the same state and responsible actor, post the matching `## Author Follow-Up Nudge`, `## Maintainer Review Nudge`, `## Merge Decision Nudge`, or `## Blocker Follow-Up Nudge` template even when the head SHA is unchanged. A nudge must name the pending action, does not authorize a re-review, and does not consume or replace the one review disposition for that SHA. -- When the gator skill requires the `principal-engineer-reviewer` sub-agent and the current effective patch has not already been reviewed by gator, first build the required review feedback ledger with `review-feedback-ledger`, then run a bounded independent review with `{{REVIEWER_COMMAND}}`. Treat the ledger's review mode, tree identity, patch identity, previous reviewed SHA, convergence checkpoint, and telemetry as authoritative. Use the full PR diff for an initial review; for a follow-up, inspect unresolved feedback plus the author-only delta and do not mine unchanged or upstream-only code for new findings. Carry open findings without duplicating them, and preserve resolved or waived dispositions unless the new diff materially invalidates them. +- When the gator skill requires the `principal-engineer-reviewer` sub-agent and the current effective patch has not already been reviewed by gator, first build the required review feedback ledger with `review-feedback-ledger`, then run a bounded independent review with `{{REVIEWER_COMMAND}}`. Treat the ledger's review mode, tree identity, patch identity, previous reviewed SHA, review budget, and telemetry as authoritative. Use the full PR diff for an initial review; for a follow-up, inspect unresolved feedback plus the author-only delta and do not mine unchanged or upstream-only code for new findings. Carry open findings without duplicating them, and preserve resolved or waived dispositions unless the new diff materially invalidates them. - Require reviewer output to follow the JSON evidence contract in `/etc/openshell/agent-payload/skills/gator-gate/references/review-findings-schema.md`. Normalize it with `validate-review-findings`; only entries with `blocking: true` may block or become public findings. -- After three finding-bearing rounds, stop autonomous Warnings and request the - maintainer convergence checkpoint. Only a new Critical defect introduced by - the latest author delta bypasses that checkpoint. +- After three finding-bearing rounds, stop autonomous Warnings and use + `critical_only` review mode. Review-budget exhaustion alone is not a blocker: + request a maintainer convergence decision only for a concrete unresolved + obligation, qualifying scope growth, or a specific proposed Warning that + needs authorization. If no decision is needed and no new Critical exists, + continue to required test dispatch. Do not enter `gator:watch-pipeline` until + those workflows are actually queued, running, or complete, and do not enter + `gator:approval-needed` until all required checks are green. - Keep reviews pragmatic and convergent. Block only on concrete, material problems introduced or materially worsened by the PR when the requested fix is proportionate. Require blockers to state reachability, impact, and PR ownership. Suggestions are non-blocking and must not keep the PR in `gator:in-review`. Operator request: diff --git a/scripts/agents/gator/skills/gator-gate/SKILL.md b/scripts/agents/gator/skills/gator-gate/SKILL.md index 2d97fe4ce6..c7a1dcab4b 100644 --- a/scripts/agents/gator/skills/gator-gate/SKILL.md +++ b/scripts/agents/gator/skills/gator-gate/SKILL.md @@ -112,11 +112,11 @@ state, resolver, stable finding IDs, and review-head context: review-feedback-ledger NVIDIA OpenShell \ > /tmp/gator-review-feedback-ledger.json jq -e ' - .schema_version == 3 and + .schema_version == 4 and (.dispositions | type == "array") and (.threads | type == "array") and (.review_scope.mode | - IN("initial", "follow_up", "already_reviewed", "human_checkpoint")) + IN("initial", "follow_up", "already_reviewed", "critical_only")) ' \ /tmp/gator-review-feedback-ledger.json >/dev/null ``` @@ -127,7 +127,7 @@ Treat the ledger as required reviewer input, not optional background: - Treat `review_scope.mode` and `previous_reviewed_sha` as authoritative. Use `initial` for a complete PR review, `follow_up` for an unresolved-feedback plus `..HEAD` delta review, and `already_reviewed` to - suppress another reviewer run. Use `human_checkpoint` after three + suppress another reviewer run. Use `critical_only` after three finding-bearing rounds as described below. - Use `current_patch_id`, `previous_reviewed_patch_id`, base SHA, and merge-base SHA to preserve review identity across rebases and merge-main commits. If @@ -613,22 +613,45 @@ Keep reviews proportional, scope-bound, and convergent: ### Convergence and scope-growth checkpoint -After three finding-bearing rounds, stop posting new Warnings. Set -`review_scope.mode` to `human_checkpoint`, summarize the existing root causes, -duplicate or waived history, remediation-driven scope growth, and remaining -obligations, then ask a maintainer to choose one of: accept the current scope, -split follow-up work, waive an obligation, or explicitly authorize another -autonomous review round. Move to `gator:blocked` with reason -`review_convergence_checkpoint` while waiting. - -Only a new Critical security, data-loss, or correctness defect introduced by -the latest author delta bypasses this checkpoint. Post that Critical with its -complete evidence contract, then return to the checkpoint; do not add Warnings. - -Trigger the same checkpoint before another autonomous review when remediation -introduces a new subsystem, crosses a linked issue or RFC non-goal, or expands -the public configuration or policy surface. Do not let review feedback silently -turn a focused PR into an architecture project. +After three finding-bearing rounds, the autonomous Warning budget is +exhausted. Set `review_scope.mode` to `critical_only`, stop posting new +Warnings, and inspect the latest author-only delta solely for a newly introduced +Critical security, data-loss, or correctness defect. Review-budget exhaustion +alone is not a process blocker and must not prevent required tests from +starting. + +After the critical-only review, separately determine whether a maintainer +decision is actually required. Set `maintainer_decision_required` in the +internal cycle summary to true only when at least one of these applies: + +- A prior finding remains unresolved and unwaived. +- Remediation introduced scope growth that crosses a linked issue or RFC + non-goal, adds a new subsystem, or expands the public configuration or policy + surface. +- Gator has a specific proposed Warning that it may post only if a maintainer + explicitly authorizes another autonomous Warning-bearing round. + +When a maintainer decision is required, summarize the relevant root causes, +dispositions, and scope growth; request only the concrete choice that is still +needed; and move to `gator:blocked` with reason +`review_convergence_decision_required`. Do not present generic choices that do +not apply to the PR. + +When all prior findings are resolved or waived, no qualifying scope growth +exists, and no new Critical was found, set `maintainer_decision_required` to +false and continue directly to the E2E/test-label decision. Move to +`gator:watch-pipeline` only after the required workflows are confirmed queued, +running, or complete. Do not move to `gator:approval-needed` until every +required check is green. + +A newly introduced Critical does not require a convergence decision. Post the +Critical with its complete evidence contract and keep the PR in +`gator:in-review`; do not add Warnings. + +Require the same concrete maintainer decision before another autonomous review +when remediation introduces a new subsystem, crosses a linked issue or RFC +non-goal, or expands the public configuration or policy surface. Do not let +review feedback silently turn a focused PR into an architecture project. For security-sensitive state machines, construct one remediation matrix before requesting another fix. Cover the applicable protocol adapters, identity @@ -654,7 +677,7 @@ Do not post them as author criticism. Before running the reviewer or posting any marked gator comment/review, build and validate the feedback ledger. If its review mode is `already_reviewed`, do -not run the reviewer. If its mode is `human_checkpoint`, follow the checkpoint +not run the reviewer. If its mode is `critical_only`, follow the review-budget rules above. Also check whether gator has already posted for the current PR head SHA. Search existing issue comments and PR reviews for the gator marker and either `Head SHA: `, `Head SHA: ```, or the current @@ -689,9 +712,9 @@ Use the `principal-engineer-reviewer` sub-agent. Include: - For `follow_up` mode, unresolved feedback plus the diff and affected-file context for `..HEAD`; include older code only when needed to understand that delta -- For `human_checkpoint` mode, the latest author-only delta and explicit +- For `critical_only` mode, the latest author-only delta and explicit instruction to return only newly introduced Critical defects; the main Gator - process, not the reviewer, produces the root-cause and scope-growth summary + process, not the reviewer, determines whether a maintainer decision is needed - An explicit instruction to carry open findings without duplicating them and to honor trusted resolved and waived findings across head SHAs - An explicit instruction to apply the pragmatic review calibration above @@ -829,6 +852,20 @@ The `/ok to test ` comment must contain only that command. Do not include t If you do not have maintainer authority, move to `gator:blocked` and state that a maintainer must post `/ok to test `. +Do not treat a test label or `/ok to test` comment as proof that testing +started. Confirm that every required workflow has a check or run for the +current head in `queued`, `in_progress`, or `completed` state before applying +`gator:watch-pipeline`. If the E2E Label Help bot says **Re-run all jobs** is +required: + +- If the operator explicitly authorized workflow reruns, identify the relevant + current-head run and rerun it with `gh run rerun `, then verify that a + new attempt was queued before moving to `gator:watch-pipeline`. +- If workflow reruns were not authorized or no rerunnable current-head run can + be identified, move to `gator:blocked` with reason + `test_dispatch_required` and state the exact maintainer action. Do not claim + that CI monitoring is active. + ## Step 10: Pipeline Watch Loop When in `gator:watch-pipeline`, monitor PR checks and workflow runs. @@ -955,8 +992,10 @@ Base SHA: `` Merge base SHA: `` Patch ID: `` Gator payload: `` -Review mode: `` +Review mode: `` Previous reviewed SHA: `` +Review budget exhausted: `` +Maintainer decision required: `` Blocking findings: - ``: @@ -972,12 +1011,12 @@ Docs: ` ``` -### Review Convergence Checkpoint +### Maintainer Convergence Decision ```markdown > **gator-agent** -## Review Convergence Checkpoint +## Maintainer Convergence Decision Head SHA: `` Base SHA: `` @@ -985,7 +1024,8 @@ Merge base SHA: `` Patch ID: `` Gator payload: `` -Three finding-bearing review rounds have completed. +The autonomous Warning budget is exhausted, and a specific maintainer decision +is required before review can proceed. Root-cause findings: - ``: @@ -996,10 +1036,11 @@ Scope growth: Reviewer-quality signals: - -Maintainer action: accept the current scope, split follow-up work, waive a -finding, or explicitly authorize another autonomous review round. +Maintainer action: Next state: `gator:blocked` +Blocked reason: `review_convergence_decision_required` ``` ### Human Response Disposition diff --git a/scripts/agents/gator/skills/gator-gate/references/review-findings-schema.md b/scripts/agents/gator/skills/gator-gate/references/review-findings-schema.md index b48098b44a..b9e267ae2e 100644 --- a/scripts/agents/gator/skills/gator-gate/references/review-findings-schema.md +++ b/scripts/agents/gator/skills/gator-gate/references/review-findings-schema.md @@ -6,7 +6,7 @@ Before invoking the reviewer, require JSON with this envelope: { "schema_version": 1, "reviewed_head_sha": "<40-character head SHA>", - "review_mode": "", + "review_mode": "", "findings": [] } ```