Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4325,6 +4325,32 @@ jobs:
changed_files_summary="bounded current-head evidence"
fi

if low_risk_model_exhaustion_fallback_applies; then
body="$(printf '%s\n' \
"## Pull request overview" \
"" \
"OpenCode exhausted the configured model pool without a usable current-head review conclusion, but this PR only changes workflow files and all current-head peer gates passed." \
"" \
"## Findings" \
"" \
"No blocking findings." \
"" \
"## Summary" \
"" \
"- Result: APPROVE" \
"- Reason: model output was unavailable, but deterministic current-head gates passed for a workflow-only change." \
"- Deterministic evidence: current-head changed-file evidence (${changed_files_summary}); coverage-evidence result ${COVERAGE_EVIDENCE_RESULT:-unknown}; peer checks from statusCheckRollup excluding this OpenCode check; no unresolved human review threads; mergeability was not dirty." \
"- Model outcome: model_pool=${OPENCODE_MODEL_POOL_OUTCOME:-unknown}; selected_model=${OPENCODE_MODEL_POOL_MODEL:-none}." \
"- Head SHA: \`${HEAD_SHA}\`" \
"- Workflow run: ${RUN_ID}" \
"- Workflow attempt: ${RUN_ATTEMPT}" \
"" \
"This bounded workflow-only fallback does not apply to source, test, lockfile, dependency manifest, generated artifact, or documentation changes.")"
body="$(ensure_review_body_has_change_graph "$body")"
create_pull_review "APPROVE" "$body"
return 0
fi

first_line_file="$(mktemp)"
if gh pr diff "$PR_NUMBER" --repo "$GH_REPOSITORY" --patch 2>/dev/null |
awk '
Expand Down Expand Up @@ -4408,6 +4434,26 @@ jobs:
return 0
}

low_risk_model_exhaustion_fallback_applies() {
local changed_count=0
local changed_path

if [ ! -s "${OPENCODE_CHANGED_FILES_FILE:-}" ]; then
return 1
fi

while IFS= read -r changed_path; do
[ -n "$changed_path" ] || continue
changed_count=$((changed_count + 1))
case "$changed_path" in
.github/workflows/*.yml|.github/workflows/*.yaml) ;;
*) return 1 ;;
esac
done <"$OPENCODE_CHANGED_FILES_FILE"

[ "$changed_count" -gt 0 ] && [ "$changed_count" -le 2 ]
}

request_changes_for_merge_conflict_if_present() {
local pr_json merge_state mergeable base_ref head_ref body change_graph

Expand Down
11 changes: 6 additions & 5 deletions scripts/ci/test_strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -578,14 +578,16 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() {
assert_file_not_contains "$workflow_file" 'approve_review_tooling_bootstrap_after_model_failure' "opencode approval must not use deterministic review-tooling bootstrap approval after model-output failures"
assert_file_not_contains "$workflow_file" 'Deterministic review-tooling bootstrap fallback approval was used' "opencode approval must not publish model-exhaustion approvals"
assert_file_not_contains "$workflow_file" 'model-exhaustion approval did not apply' "opencode approval failure text should describe retry exhaustion, not model-exhaustion criteria"
assert_file_contains "$workflow_file" "low_risk_model_exhaustion_fallback_applies" "opencode approval has a narrow workflow-only fallback after green current-head gates"
assert_file_contains "$workflow_file" "This bounded workflow-only fallback does not apply to source, test, lockfile, dependency manifest, generated artifact, or documentation changes." "opencode workflow-only fallback documents its excluded surfaces"
assert_file_contains "$workflow_file" 'wait_for_peer_github_checks "$pending_file"' "model-failure hold waits for peer checks before changing review state"
assert_file_contains "$workflow_file" 'pending_checks_file="$(mktemp)"' "model-failure hold writes pending-check evidence to a real temp file"
assert_file_contains "$workflow_file" 'collect_github_checks_with_retry collect_failed_github_checks "$failed_file"' "model-failure hold rejects current-head failed peer checks"
assert_file_contains "$workflow_file" 'run_failed_check_diagnosis "$failed_file" "$failed_check_evidence_file" "$failed_check_review_body_file" "$failed_check_review_payload_file" "$failed_check_inline_failure_body_file"' "model-failure hold diagnoses late current-head failed peer checks before falling back to unavailable"
assert_file_contains "$workflow_file" "request_changes_for_merge_conflict_if_present" "model-failure hold still gates on mergeability"
assert_file_contains "$workflow_file" 'unresolved_human_threads_file="$(mktemp)"' "model-failure hold writes human-thread evidence to a real temp file"
assert_file_contains "$workflow_file" 'collect_unresolved_human_review_threads "$unresolved_threads_file"' "model-failure hold rechecks human review threads"
assert_file_contains "$workflow_file" "No PR approval was posted because model-output failure is not evidence that the PR has no blockers." "model-failure path fails closed instead of publishing model-exhaustion"
assert_file_contains "$workflow_file" "No PR approval was posted because model-output failure is not evidence that the PR has no blockers." "model-failure path fails closed instead of publishing model-exhaustion for non-workflow-only changes"
assert_file_contains "$workflow_file" 'Detect central review-process fallback scope' "opencode approval detects central review-process fallback scope before model attempts"
assert_file_contains "$workflow_file" 'id: central_review_process_fallback_scope' "opencode approval exposes central review-process fallback scope as a step output"
assert_file_not_contains "$workflow_file" 'steps.central_review_process_fallback_scope.outputs.eligible != '\''true'\''' "opencode model pool is not skipped for central review-process diffs"
Expand All @@ -600,8 +602,8 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() {
assert_file_contains "$workflow_file" 'scripts/ci/test_strix_quick_gate.sh)' "opencode central review fallback allowlist includes only the central gate self-test"
assert_file_contains "$workflow_file" 'wait_for_peer_github_checks "$pending_checks_file"' "opencode model-failure path waits for peer checks before failing closed"
assert_file_contains "$workflow_file" 'collect_unresolved_human_review_threads "$unresolved_human_threads_file"' "opencode model-failure path re-queries human threads before failing closed"
assert_file_not_contains "$workflow_file" "model-exhaustion fallback verified this is a no-diff or central review-process-only change" "opencode approval must not publish no-diff or central review model-exhaustions after model failures"
assert_file_not_contains "$workflow_file" "so the approval gate used source-backed current-head evidence instead of model prose" "opencode approval must not publish guarded model-exhaustion after model-output failures"
assert_file_contains "$workflow_file" ".github/workflows/*.yml|.github/workflows/*.yaml" "opencode model-exhaustion fallback is limited to workflow files"
assert_file_contains "$workflow_file" '[ "$changed_count" -gt 0 ] && [ "$changed_count" -le 2 ]' "opencode workflow-only fallback caps changed-file count"
assert_file_contains "$workflow_file" "all configured OpenCode model attempts failed to produce a usable current-head control block" "opencode model-output failures fail the check without publishing a review"
assert_file_contains "$workflow_file" "no model produced a valid review control block" "opencode model-failure path documents why approval is withheld"
assert_file_contains "$workflow_file" 'OPENCODE_MODEL_ATTEMPTS: "2"' "opencode primary and deepseek review paths retry model execution"
Expand Down Expand Up @@ -855,8 +857,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() {
assert_file_contains "$REPO_ROOT/scripts/ci/emit_opencode_failed_check_fallback_findings.sh" '^CMD \["/app/scripts/docker_entrypoint\.sh"\]' "opencode failed-check fallback maps missing Docker entrypoint reports to the Dockerfile CMD line"
assert_file_contains "$workflow_file" "Unrelated speculative findings are invalid when failed-check evidence is present." "opencode review prompt forbids unrelated failed-check findings"
assert_file_contains "$workflow_file" "run_failed_check_diagnosis" "opencode approval gate reruns OpenCode diagnosis when checks fail after the initial review"
assert_file_not_contains "$workflow_file" "so the approval gate used source-backed current-head evidence instead of model prose." "opencode approval gate must not record deterministic model-failure approval"
assert_file_not_contains "$workflow_file" "Deterministic fallback approval was used only after model-output instability and did not bypass coverage, failed-check, mergeability, or human-review gates." "opencode approval gate must not document deterministic model-failure approval"
assert_file_contains "$workflow_file" "deterministic current-head gates passed for a workflow-only change" "opencode approval gate records the narrow workflow-only model-failure fallback"
assert_file_contains "$workflow_file" "request_changes_after_model_exhaustion" "opencode model-failure path reuses green current-head gates only to decide fail-closed diagnostics"
assert_file_contains "$workflow_file" "request_changes_for_merge_conflict_if_present" "opencode approval gate checks mergeability before approving model or fallback output"
assert_file_contains "$workflow_file" "Merge Conflict Guidance" "opencode approval gate emits explicit conflict guidance when mergeability is dirty"
Expand Down
Loading