Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
43c4002
fix(noema): preserve long-running substantive reviews
seonghobae Aug 31, 2026
8084b2a
test(noema): cover unbounded provider calls
seonghobae Aug 31, 2026
6955bab
docs(adr): prohibit fixed model inference timeouts
seonghobae Aug 31, 2026
e19447f
fix(review): remove fixed orchestration deadlines
seonghobae Aug 31, 2026
1b9ed49
fix(noema): truncate diffs at complete lines
seonghobae Aug 31, 2026
6344fe3
test(review): refresh dispatch blob pin
seonghobae Aug 31, 2026
958e8e5
fix(noema): isolate standalone review concurrency
seonghobae Aug 31, 2026
8b32373
fix(review): keep Noema independent and preserve diff locations
seonghobae Aug 31, 2026
0fb80aa
fix(noema): bind reviews to requested head
seonghobae Aug 31, 2026
c82fe5f
fix(noema): compare expected heads case-insensitively
seonghobae Aug 31, 2026
c724864
test(noema): guard case-insensitive workflow head checks
seonghobae Aug 31, 2026
c4fb9c1
fix(review): fail closed on stalled review evidence
seonghobae Aug 31, 2026
b6c7532
fix(review): remove elapsed-time cutoffs
seonghobae Aug 31, 2026
63aaf4b
fix(review): bound sidecar health probes
seonghobae Aug 31, 2026
55da0a2
fix(review): keep health polling unbounded
seonghobae Sep 1, 2026
4555462
merge(review): keep verdict polling unbounded
seonghobae Sep 1, 2026
3462ccd
test(opencode): accept live head advances safely
seonghobae Sep 1, 2026
8a01a66
Merge remote-tracking branch 'origin/main' into fix/noema-exact-locat…
seonghobae Sep 1, 2026
6ee78b8
fix(review): bind long-running reviews to exact head
seonghobae Sep 1, 2026
739f9c6
fix(autofix): retire superseded head workers
seonghobae Sep 1, 2026
014bf3b
test(review): refresh dispatch workflow pin
seonghobae Sep 1, 2026
c496f86
fix(strix): cancel superseded heads outside scan queue
seonghobae Sep 1, 2026
a23c7cc
fix(noema): preserve active same-head review
seonghobae Sep 1, 2026
2bdb519
fix(autofix): inspect every active worker page
seonghobae Sep 1, 2026
9ee4f1b
test(autofix): cover active worker on later page
seonghobae Sep 1, 2026
c0603e6
test(autofix): isolate active-run inventory boundary
seonghobae Sep 1, 2026
ed33e00
test(strix): align cleanup queue contract
seonghobae Sep 1, 2026
5344daa
Merge remote-tracking branch 'origin/main' into fix/noema-exact-locat…
seonghobae Sep 1, 2026
495373f
fix(autofix): revalidate head before mutation
seonghobae Sep 1, 2026
c86911a
test(autofix): isolate live head validation
seonghobae Sep 1, 2026
fbd3e2b
test(sidecar): enforce unbounded discovery and health waits
seonghobae Sep 1, 2026
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
42 changes: 29 additions & 13 deletions .github/workflows/noema-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ run-name: >-
Required Noema Review ${{ github.event.client_payload.target_repository ||
github.event.pull_request.base.repo.full_name || github.repository }}#${{
github.event.client_payload.pr_number || github.event.pull_request.number ||
github.event.workflow_run.pull_requests[0].number || 'event' }}@${{
'event' }}@${{
github.event.client_payload.pr_head_sha || github.event.pull_request.head.sha ||
github.event.workflow_run.head_sha || github.sha }}
github.sha }}

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review, closed]
workflow_run:
workflows: ["Required OpenCode Review", "Strix Security Scan"]
types: [completed]
# Default-branch-only retry entrypoint; no caller-selected workflow ref.
repository_dispatch:
types: [noema-review]
Expand All @@ -22,10 +19,12 @@ concurrency:
noema-review-${{
github.event.pull_request.base.repo.full_name ||
github.event.client_payload.target_repository || github.repository }}-${{
github.event.pull_request.number || github.event.workflow_run.pull_requests[0].number ||
github.event.pull_request.number ||
github.event.client_payload.pr_number ||
github.run_id }}
Comment thread
seonghobae marked this conversation as resolved.
cancel-in-progress: true
cancel-in-progress: >-
${{ github.event_name == 'pull_request_target' &&
(github.event.action == 'synchronize' || github.event.action == 'closed') }}

permissions:
contents: read
Expand All @@ -45,10 +44,6 @@ jobs:
runs-on: ubuntu-latest
if: >-
github.event_name == 'repository_dispatch'
|| (
github.event_name == 'workflow_run'
&& github.event.workflow_run.conclusion != 'cancelled'
)
|| (
github.event_name == 'pull_request_target'
&& github.event.action != 'closed'
Expand All @@ -57,7 +52,8 @@ jobs:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
TARGET_REPOSITORY: ${{ github.event.pull_request.base.repo.full_name || github.event.client_payload.target_repository || github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.workflow_run.pull_requests[0].number || github.event.client_payload.pr_number || '' }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.client_payload.pr_number || '' }}
Comment thread
seonghobae marked this conversation as resolved.
EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.client_payload.pr_head_sha || '' }}
steps:
- name: Skip events without pull request context
if: env.PR_NUMBER == ''
Expand Down Expand Up @@ -248,6 +244,25 @@ jobs:
echo "::add-mask::$app_token"
echo "token=$app_token" >>"$GITHUB_OUTPUT"

- name: Validate current pull request head
if: env.PR_NUMBER != ''
env:
GH_TOKEN: ${{ secrets.NOEMA_REVIEW_TOKEN || steps.noema_github_app_token.outputs.token || steps.noema_oidc_token.outputs.token }}
run: |
set -euo pipefail
if ! [[ "$EXPECTED_HEAD_SHA" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "::error::Noema expected head must be a full commit SHA."
exit 1
fi
pull_request_json="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")"
live_state="$(jq -r '.state // empty' <<<"$pull_request_json")"
live_head_sha="$(jq -r '.head.sha // empty' <<<"$pull_request_json")"
if [ "$live_state" != "open" ] || [ "${live_head_sha,,}" != "${EXPECTED_HEAD_SHA,,}" ]; then
printf '::error::Noema review target is closed or stale. expected head=%s; live state=%s head=%s.\n' \
"$EXPECTED_HEAD_SHA" "${live_state:-missing}" "${live_head_sha:-missing}"
exit 1
fi

- name: Resolve Noema target repository visibility
if: env.PR_NUMBER != ''
id: target_visibility
Expand Down Expand Up @@ -327,4 +342,5 @@ jobs:
export NOEMA_LLM_VIA_ORCHESTRATOR=1
python3 -m scripts.ci.noema_review_gate \
--repo "$TARGET_REPOSITORY" \
--pr-number "$PR_NUMBER"
--pr-number "$PR_NUMBER" \
--expected-head-sha "$EXPECTED_HEAD_SHA"
38 changes: 2 additions & 36 deletions .github/workflows/opencode-review-dispatch.yml
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -2309,7 +2309,6 @@ jobs:
# 36-minute publication gate, the 18-minute Noema handoff, and setup/cleanup
# overhead without truncating a late current-head verdict, handoff, merge
# scheduler follow-up, or bounded failure reason.
timeout-minutes: 325
permissions:
actions: read
checks: read
Expand Down Expand Up @@ -3990,7 +3989,6 @@ jobs:
- name: Run OpenCode PR Review model pool
id: opencode_review_model_pool
if: needs.coverage-evidence.result == 'success'
timeout-minutes: 205
continue-on-error: true
env:
SHARE: "false"
Expand All @@ -4001,14 +3999,7 @@ jobs:
# the SAME model 5x let a rate-limited/hung leader consume the whole
# step, so the pool never reached a healthy fallback model.
OPENCODE_MODEL_ATTEMPTS: "1"
# Preserve reviews that legitimately need tens of minutes to inspect a
# large repository. Changed-file count is not a repository-complexity
# proxy, so every cadence class gets 90 minutes per candidate while the
# bounded provider-pool watchdog remains the outer guard.
OPENCODE_RUN_TIMEOUT_SECONDS: "5400"
OPENCODE_EXPORT_TIMEOUT_SECONDS: "180"
OPENCODE_TOTAL_RETRY_BUDGET_SECONDS: "11700"
OPENCODE_POOL_STEP_TIMEOUT_SECONDS: "12000"
# A second pass through the same provider catalog repeats the same
# quota/format failures and can occupy the required check for hours.
# Exhaust each distinct candidate once, then publish the bounded
Expand All @@ -4017,23 +4008,10 @@ jobs:
OPENCODE_DYNAMIC_REVIEW_CADENCE: "true"
OPENCODE_SMALL_CHANGE_FILE_THRESHOLD: "3"
OPENCODE_MEDIUM_CHANGE_FILE_THRESHOLD: "20"
OPENCODE_SMALL_CHANGE_RUN_TIMEOUT_SECONDS: "5400"
OPENCODE_SMALL_CHANGE_TOTAL_BUDGET_SECONDS: "11700"
OPENCODE_MEDIUM_CHANGE_RUN_TIMEOUT_SECONDS: "5400"
OPENCODE_MEDIUM_CHANGE_TOTAL_BUDGET_SECONDS: "11700"
OPENCODE_LARGE_CHANGE_RUN_TIMEOUT_SECONDS: "5400"
OPENCODE_LARGE_CHANGE_TOTAL_BUDGET_SECONDS: "11700"
OPENCODE_UNKNOWN_CHANGE_RUN_TIMEOUT_SECONDS: "5400"
OPENCODE_UNKNOWN_CHANGE_TOTAL_BUDGET_SECONDS: "11700"
OPENCODE_DYNAMIC_RUN_TIMEOUT_CAP_SECONDS: "5400"
OPENCODE_DYNAMIC_TOTAL_BUDGET_CAP_SECONDS: "11700"
OPENCODE_DYNAMIC_MAX_CYCLES_CAP: "1"
OPENCODE_FREE_RUN_TIMEOUT_SECONDS: "3600"
OPENCODE_DYNAMIC_MAX_CYCLES: "1"
CENTRAL_REVIEW_PROCESS_FALLBACK_ELIGIBLE: ${{ steps.central_review_process_fallback_scope.outputs.eligible || 'false' }}
CENTRAL_REVIEW_PROCESS_FALLBACK_SCOPE_LABEL: ${{ steps.central_review_process_fallback_scope.outputs.scope_label || 'unsupported' }}
OPENCODE_CENTRAL_REVIEW_PROCESS_FALLBACK_RUN_TIMEOUT_SECONDS: "5400"
OPENCODE_CENTRAL_REVIEW_PROCESS_FALLBACK_TOTAL_BUDGET_SECONDS: "11700"
OPENCODE_CENTRAL_REVIEW_PROCESS_FALLBACK_MAX_CYCLES: "1"
OPENCODE_BACKOFF_INITIAL_SECONDS: "30"
OPENCODE_BACKOFF_MAX_SECONDS: "30"
Expand All @@ -4056,18 +4034,9 @@ jobs:
set -euo pipefail
source "$GITHUB_WORKSPACE/scripts/ci/load_contextual_orchestrator_token.sh"
set +e
timeout --kill-after=30s "${OPENCODE_POOL_STEP_TIMEOUT_SECONDS:-3600}s" \
bash "$GITHUB_WORKSPACE/scripts/ci/run_opencode_review_model_pool.sh"
bash "$GITHUB_WORKSPACE/scripts/ci/run_opencode_review_model_pool.sh"
pool_status=$?
set -e
if [ "$pool_status" -eq 124 ] || [ "$pool_status" -eq 137 ] || [ "$pool_status" -eq 143 ]; then
printf 'OpenCode model pool exceeded the outer %ss step budget; marking the pool exhausted so current-head evidence fallback can publish a bounded reason instead of blocking the org queue.\n' \
"${OPENCODE_POOL_STEP_TIMEOUT_SECONDS:-3600}"
{
printf 'review_model=\n'
printf 'review_status=exhausted\n'
} >>"$GITHUB_OUTPUT"
fi
exit "$pool_status"

- name: Exchange OpenCode app token for review writes
Expand Down Expand Up @@ -4620,7 +4589,6 @@ jobs:
# The approval gate normally waits about six minutes, with bounded
# extensions for image validation or package/GPU builds plus API and
# publication overhead.
timeout-minutes: 36
env:
GH_TOKEN: ${{ steps.opencode_app_token.outputs.token || secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
CHECK_LOOKUP_GH_TOKEN: ${{ github.token }}
Expand Down Expand Up @@ -4675,7 +4643,6 @@ jobs:
# failed-check diagnosis in this publish step is a short best-effort
# augmentation; current-head logs/SARIF remain the authoritative
# reason source when the augmentation is unavailable.
OPENCODE_RUN_TIMEOUT_SECONDS: "120"
OPENCODE_EXPORT_TIMEOUT_SECONDS: "60"
run: |
set -euo pipefail
Expand Down Expand Up @@ -6029,8 +5996,7 @@ jobs:
} >"$prompt_file"

cd "$OPENCODE_REVIEW_WORKDIR"
if ! timeout --kill-after=30s "${OPENCODE_RUN_TIMEOUT_SECONDS:-120}s" \
env -u GH_TOKEN -u GITHUB_TOKEN -u OPENCODE_APP_TOKEN \
if ! env -u GH_TOKEN -u GITHUB_TOKEN -u OPENCODE_APP_TOKEN \
-u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL \
opencode run "$(cat "$prompt_file")" \
--pure \
Expand Down
17 changes: 2 additions & 15 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,6 @@ jobs:
name: opencode-review
needs: [coverage-evidence]
runs-on: ubuntu-latest
# Must stay >= opencode-review-dispatch.yml's own opencode-review-target
# job ceiling (currently 325m; see that workflow's
# test_opencode_job_timeout_contains_full_sequential_review_budget). That
# job's model-pool step alone is budgeted 205m for contextual-orchestrator
# sidecar preflight/escalation across its free-tier candidate pool, so a
# shorter poll budget here fails a legitimate slow-but-successful review
# indistinguishably from a genuinely broken dispatch (see
# ContextualWisdomLab/.github#1500, #1506, contextual-orchestrator#968,
# #946: dispatch always succeeded, but the 90-minute-bounded poll below
# always gave up before the dispatched job could post a verdict).
timeout-minutes: 340
permissions:
contents: read
pull-requests: read
Expand Down Expand Up @@ -302,7 +291,7 @@ jobs:
exit 1
fi
verdict=""
for attempt in $(seq 1 660); do
while :; do
reviews="$(gh api --paginate "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}/reviews")"
verdict="$(printf '%s\n' "$reviews" | jq -r -s --arg sha "$HEAD_SHA" '
(add // [])
Expand Down Expand Up @@ -335,9 +324,7 @@ jobs:
if [ -n "$verdict" ]; then
break
fi
if [ "$attempt" -lt 660 ]; then
sleep 30
fi
sleep 30
done
if [ -z "$verdict" ]; then
echo "::error::No APPROVED or CHANGES_REQUESTED from opencode-agent on the current head. This required check is not a review and must not succeed until the authenticated dispatch posts a current-head verdict."
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pr-review-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ jobs:
trap restore_workspace_config EXIT
cd "$TARGET_WORKSPACE"
env -u GITHUB_TOKEN -u GH_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL \
timeout 18000 opencode run "$(cat "$prompt_file")" \
opencode run "$(cat "$prompt_file")" \
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
--pure \
--agent ci-autofix \
--model "$MODEL" \
Expand Down Expand Up @@ -653,7 +653,7 @@ jobs:
}
trap restore_workspace_config EXIT
env -u GITHUB_TOKEN -u GH_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL \
timeout 18000 opencode run "$(cat "$prompt_file")" \
opencode run "$(cat "$prompt_file")" \
--pure \
--agent ci-autofix \
--model "$MODEL" \
Expand Down
Loading
Loading