From c79ad1080169ae55983388ad8a5a1bb1f1a74324 Mon Sep 17 00:00:00 2001 From: mrjf Date: Fri, 10 Jul 2026 00:33:11 -0500 Subject: [PATCH 1/2] Dispatch repair after CI activation failures --- .github/workflows/evergreen.lock.yml | 106 ++++++++++++++++-- .github/workflows/evergreen.md | 104 ++++++++++++++++- .../workflows/shared/evergreen/repo-policy.md | 13 ++- 3 files changed, 207 insertions(+), 16 deletions(-) diff --git a/.github/workflows/evergreen.lock.yml b/.github/workflows/evergreen.lock.yml index 8e2acbb8..c6008c34 100644 --- a/.github/workflows/evergreen.lock.yml +++ b/.github/workflows/evergreen.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"0f396f50935c8f16ec533e43058978b14bf053bc2c6f489fc5e8612b2e68ec55","body_hash":"145147ca182cc8ee81f803eb3eab5c35bd5bb1da0ed427b93dfc341f5bc4025b","compiler_version":"v0.79.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"7b4265834623b5573eebad7d2e52d7bad77148f346e70b69712b8cdc65c5f9fe","body_hash":"058a426b7066098fbd3fa66e0c77d3199f52fe4f89a196f98b2a01cb6580158c","compiler_version":"v0.79.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"d059700c6a8ec3b5fd798b9ea60f5d048447b918","version":"v0.79.4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.0"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.0"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]} # ___ _ _ # / _ \ | | (_) @@ -1827,6 +1827,30 @@ jobs: return 1 } + any_configured_check_failing() { + local payload="$1" + local required="$2" + local count + local state + + count="$(jq 'length' <<<"$required")" + if [ "$count" -eq 0 ]; then + has_failing_check "$payload" + return + fi + + while IFS= read -r name; do + state="$(check_state_for "$payload" "$name")" + case "$state" in + FAILURE|failure|FAILED|failed|ERROR|error|TIMED_OUT|timed_out|CANCELLED|cancelled) + return 0 + ;; + esac + done < <(jq -r '.[]' <<<"$required") + + return 1 + } + evaluate_readiness() { local payload="$1" local required @@ -1850,6 +1874,11 @@ jobs: return 0 fi + if any_configured_check_failing "$payload" "$required"; then + echo "needs_repair" + return 0 + fi + if any_configured_check_missing "$payload" "$required"; then echo "needs_ci" return 0 @@ -1944,7 +1973,7 @@ jobs: if [ -z "$run_id" ]; then echo "No CI run found for PR #$pr ($head_sha); leaving for scheduled/PR CI to start." - return 0 + return 1 fi case "$status" in @@ -1957,14 +1986,58 @@ jobs: case "$conclusion" in success) echo "CI run $run_id for PR #$pr ($head_sha) already succeeded; not rerunning green checks." - return 0 + return 1 ;; esac echo "Reactivating CI run $run_id for PR #$pr ($head_sha) (status=$status conclusion=$conclusion)." - ci_gh gh run rerun "$run_id" --repo "$REPO" --failed || \ - ci_gh gh run rerun "$run_id" --repo "$REPO" || \ - echo "Could not reactivate CI run $run_id; scheduled monitor will retry." + if ci_gh gh run rerun "$run_id" --repo "$REPO" --failed; then + return 0 + fi + + echo "Failed-jobs rerun was unavailable for CI run $run_id; trying full rerun." + if ci_gh gh run rerun "$run_id" --repo "$REPO"; then + return 0 + fi + + echo "Could not reactivate CI run $run_id; scheduled monitor will retry." + return 1 + } + + wait_for_ci_activation() { + local pr="$1" + local head_sha="$2" + local timeout="${CI_ACTIVATION_WAIT_SECONDS:-0}" + local deadline payload current_head state + + if ! grep -Eq '^[0-9]+$' <<<"$timeout" || [ "$timeout" -le 0 ]; then + return 1 + fi + + deadline=$((SECONDS + timeout)) + while [ "$SECONDS" -lt "$deadline" ]; do + sleep 10 + payload="$(pr_json "$pr")" + current_head="$(jq -r '.headRefOid' <<<"$payload")" + if [ "$current_head" != "$head_sha" ]; then + echo "PR #$pr head changed from $head_sha to $current_head while waiting for CI." + return 0 + fi + + state="$(evaluate_readiness "$payload")" + case "$state" in + waiting|needs_ci) + echo "CI for PR #$pr is still $state; continuing to wait." + ;; + *) + echo "CI for PR #$pr settled to $state." + return 0 + ;; + esac + done + + echo "CI for PR #$pr did not settle within ${timeout}s; a later Evergreen run will continue." + return 1 } update_branch_if_needed() { @@ -2042,7 +2115,25 @@ jobs: return 1 ;; needs_ci) - trigger_ci_if_needed "$pr" "$head_sha" + if trigger_ci_if_needed "$pr" "$head_sha" && + wait_for_ci_activation "$pr" "$head_sha"; then + payload="$(pr_json "$pr")" + head_sha="$(jq -r '.headRefOid' <<<"$payload")" + state="$(evaluate_readiness "$payload")" + if ! reconcile_ready_label "$pr" "$state" "$payload"; then + echo "Could not reconcile $READY_LABEL for PR #$pr after CI activation; refusing to dispatch the agent." + set_result "false" "$pr" "$head_sha" "blocked" "$reason:ready_label_failed" + return 1 + fi + + if [ "$state" = "needs_repair" ]; then + if ! claim_active_label "$pr" "$head_sha" "$reason:ci_failed_after_activation"; then + return 1 + fi + set_result "true" "$pr" "$head_sha" "$state" "$reason:ci_failed_after_activation" + return 0 + fi + fi return 1 ;; needs_branch_update) @@ -2099,6 +2190,7 @@ jobs: env: ACTIVE_LABEL: evergreen_active CHECK_GATE_MODE: configured + CI_ACTIVATION_WAIT_SECONDS: "300" CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN || '' }} EVENT_ACTION: ${{ github.event.action }} EVENT_NAME: ${{ github.event_name }} diff --git a/.github/workflows/evergreen.md b/.github/workflows/evergreen.md index 8e66399c..64c27dd0 100644 --- a/.github/workflows/evergreen.md +++ b/.github/workflows/evergreen.md @@ -66,6 +66,7 @@ jobs: EXHAUSTED_LABEL: evergreen-exhausted REQUIRED_CHECKS_JSON: '["Test & Lint","Playground E2E (Playwright)","Build","Validate Python Examples"]' CHECK_GATE_MODE: configured + CI_ACTIVATION_WAIT_SECONDS: "300" MANUAL_PR: ${{ github.event.inputs.pr || '' }} MANUAL_HEAD_SHA: ${{ github.event.inputs.head_sha || '' }} MANUAL_REASON: ${{ github.event.inputs.reason || '' }} @@ -187,6 +188,30 @@ jobs: return 1 } + any_configured_check_failing() { + local payload="$1" + local required="$2" + local count + local state + + count="$(jq 'length' <<<"$required")" + if [ "$count" -eq 0 ]; then + has_failing_check "$payload" + return + fi + + while IFS= read -r name; do + state="$(check_state_for "$payload" "$name")" + case "$state" in + FAILURE|failure|FAILED|failed|ERROR|error|TIMED_OUT|timed_out|CANCELLED|cancelled) + return 0 + ;; + esac + done < <(jq -r '.[]' <<<"$required") + + return 1 + } + evaluate_readiness() { local payload="$1" local required @@ -210,6 +235,11 @@ jobs: return 0 fi + if any_configured_check_failing "$payload" "$required"; then + echo "needs_repair" + return 0 + fi + if any_configured_check_missing "$payload" "$required"; then echo "needs_ci" return 0 @@ -304,7 +334,7 @@ jobs: if [ -z "$run_id" ]; then echo "No CI run found for PR #$pr ($head_sha); leaving for scheduled/PR CI to start." - return 0 + return 1 fi case "$status" in @@ -317,14 +347,58 @@ jobs: case "$conclusion" in success) echo "CI run $run_id for PR #$pr ($head_sha) already succeeded; not rerunning green checks." - return 0 + return 1 ;; esac echo "Reactivating CI run $run_id for PR #$pr ($head_sha) (status=$status conclusion=$conclusion)." - ci_gh gh run rerun "$run_id" --repo "$REPO" --failed || \ - ci_gh gh run rerun "$run_id" --repo "$REPO" || \ - echo "Could not reactivate CI run $run_id; scheduled monitor will retry." + if ci_gh gh run rerun "$run_id" --repo "$REPO" --failed; then + return 0 + fi + + echo "Failed-jobs rerun was unavailable for CI run $run_id; trying full rerun." + if ci_gh gh run rerun "$run_id" --repo "$REPO"; then + return 0 + fi + + echo "Could not reactivate CI run $run_id; scheduled monitor will retry." + return 1 + } + + wait_for_ci_activation() { + local pr="$1" + local head_sha="$2" + local timeout="${CI_ACTIVATION_WAIT_SECONDS:-0}" + local deadline payload current_head state + + if ! grep -Eq '^[0-9]+$' <<<"$timeout" || [ "$timeout" -le 0 ]; then + return 1 + fi + + deadline=$((SECONDS + timeout)) + while [ "$SECONDS" -lt "$deadline" ]; do + sleep 10 + payload="$(pr_json "$pr")" + current_head="$(jq -r '.headRefOid' <<<"$payload")" + if [ "$current_head" != "$head_sha" ]; then + echo "PR #$pr head changed from $head_sha to $current_head while waiting for CI." + return 0 + fi + + state="$(evaluate_readiness "$payload")" + case "$state" in + waiting|needs_ci) + echo "CI for PR #$pr is still $state; continuing to wait." + ;; + *) + echo "CI for PR #$pr settled to $state." + return 0 + ;; + esac + done + + echo "CI for PR #$pr did not settle within ${timeout}s; a later Evergreen run will continue." + return 1 } update_branch_if_needed() { @@ -402,7 +476,25 @@ jobs: return 1 ;; needs_ci) - trigger_ci_if_needed "$pr" "$head_sha" + if trigger_ci_if_needed "$pr" "$head_sha" && + wait_for_ci_activation "$pr" "$head_sha"; then + payload="$(pr_json "$pr")" + head_sha="$(jq -r '.headRefOid' <<<"$payload")" + state="$(evaluate_readiness "$payload")" + if ! reconcile_ready_label "$pr" "$state" "$payload"; then + echo "Could not reconcile $READY_LABEL for PR #$pr after CI activation; refusing to dispatch the agent." + set_result "false" "$pr" "$head_sha" "blocked" "$reason:ready_label_failed" + return 1 + fi + + if [ "$state" = "needs_repair" ]; then + if ! claim_active_label "$pr" "$head_sha" "$reason:ci_failed_after_activation"; then + return 1 + fi + set_result "true" "$pr" "$head_sha" "$state" "$reason:ci_failed_after_activation" + return 0 + fi + fi return 1 ;; needs_branch_update) diff --git a/.github/workflows/shared/evergreen/repo-policy.md b/.github/workflows/shared/evergreen/repo-policy.md index 95dd48d5..69164dd6 100644 --- a/.github/workflows/shared/evergreen/repo-policy.md +++ b/.github/workflows/shared/evergreen/repo-policy.md @@ -42,9 +42,14 @@ readiness controller and the agentic orchestrator must both respect this file. (new head SHA, pending, failing, missing check, conflict, out of scope). - Current-head SHA policy: readiness is evaluated only against the current PR head SHA. A new push invalidates prior readiness. -- Pending check policy: `waiting` — do not repair pending or in-progress checks. +- Failing check policy: `needs_repair` — if a configured gate is visibly + failing for the current head SHA, dispatch the repair agent even when other + configured checks are still missing or skipped. +- Pending check policy: `waiting` — do not repair pending or in-progress checks + unless another configured gate has already failed. - Missing/stale check policy: `needs_ci` — reactivate the latest `CI` run for the - head SHA once (see CI/CD Activation). Never rerun green checks. + head SHA once, wait briefly for a result, then dispatch repair in the same run + if the gate fails (see CI/CD Activation). Never rerun green checks. - Branch freshness ready criterion: not required to be up to date with `main`; freshness is only enforced when the branch is conflicted (`DIRTY`/`UNKNOWN`). - Additional deterministic ready criteria: PR open, has `evergreen`, not @@ -100,7 +105,9 @@ readiness controller and the agentic orchestrator must both respect this file. - Workflows/checks Evergreen may dispatch: none by name in v1; activation is rerun-based only. - Stale check policy: reactivate the latest `CI` run for the head SHA once per - head; never rerun green checks; never re-trigger an already in-progress run. + head; briefly wait for it to settle; dispatch repair immediately if a + configured gate fails; never rerun green checks; never re-trigger an already + in-progress run. - Missing check policy: if no `CI` run exists for the head SHA, wait for the normal `pull_request`/schedule CI to start rather than forcing activation. - Empty commit policy: empty trigger commits are a last resort only, requested From 3f83820474fa64c215ef3e12bf22d842416d7c26 Mon Sep 17 00:00:00 2001 From: mrjf Date: Fri, 10 Jul 2026 00:35:37 -0500 Subject: [PATCH 2/2] Keep CI activation controller-only --- .github/workflows/evergreen.lock.yml | 59 +------------------ .github/workflows/evergreen.md | 57 +----------------- .../workflows/shared/evergreen/repo-policy.md | 8 +-- 3 files changed, 6 insertions(+), 118 deletions(-) diff --git a/.github/workflows/evergreen.lock.yml b/.github/workflows/evergreen.lock.yml index c6008c34..88d74f31 100644 --- a/.github/workflows/evergreen.lock.yml +++ b/.github/workflows/evergreen.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"7b4265834623b5573eebad7d2e52d7bad77148f346e70b69712b8cdc65c5f9fe","body_hash":"058a426b7066098fbd3fa66e0c77d3199f52fe4f89a196f98b2a01cb6580158c","compiler_version":"v0.79.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"d45f839a4ad149d101caba80163b04d9a444aac746fb65fe7469d58d44a7ee40","body_hash":"a4d7db91f7e9ca4e7cba1676052255426f43cca5d5bf193047ff845a5ba81892","compiler_version":"v0.79.4","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"d059700c6a8ec3b5fd798b9ea60f5d048447b918","version":"v0.79.4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.0"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.0"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]} # ___ _ _ # / _ \ | | (_) @@ -2004,42 +2004,6 @@ jobs: return 1 } - wait_for_ci_activation() { - local pr="$1" - local head_sha="$2" - local timeout="${CI_ACTIVATION_WAIT_SECONDS:-0}" - local deadline payload current_head state - - if ! grep -Eq '^[0-9]+$' <<<"$timeout" || [ "$timeout" -le 0 ]; then - return 1 - fi - - deadline=$((SECONDS + timeout)) - while [ "$SECONDS" -lt "$deadline" ]; do - sleep 10 - payload="$(pr_json "$pr")" - current_head="$(jq -r '.headRefOid' <<<"$payload")" - if [ "$current_head" != "$head_sha" ]; then - echo "PR #$pr head changed from $head_sha to $current_head while waiting for CI." - return 0 - fi - - state="$(evaluate_readiness "$payload")" - case "$state" in - waiting|needs_ci) - echo "CI for PR #$pr is still $state; continuing to wait." - ;; - *) - echo "CI for PR #$pr settled to $state." - return 0 - ;; - esac - done - - echo "CI for PR #$pr did not settle within ${timeout}s; a later Evergreen run will continue." - return 1 - } - update_branch_if_needed() { # Deterministic branch freshness handling. Keep base-branch merges out # of agent patches so safe outputs only contain repair edits. @@ -2115,25 +2079,7 @@ jobs: return 1 ;; needs_ci) - if trigger_ci_if_needed "$pr" "$head_sha" && - wait_for_ci_activation "$pr" "$head_sha"; then - payload="$(pr_json "$pr")" - head_sha="$(jq -r '.headRefOid' <<<"$payload")" - state="$(evaluate_readiness "$payload")" - if ! reconcile_ready_label "$pr" "$state" "$payload"; then - echo "Could not reconcile $READY_LABEL for PR #$pr after CI activation; refusing to dispatch the agent." - set_result "false" "$pr" "$head_sha" "blocked" "$reason:ready_label_failed" - return 1 - fi - - if [ "$state" = "needs_repair" ]; then - if ! claim_active_label "$pr" "$head_sha" "$reason:ci_failed_after_activation"; then - return 1 - fi - set_result "true" "$pr" "$head_sha" "$state" "$reason:ci_failed_after_activation" - return 0 - fi - fi + trigger_ci_if_needed "$pr" "$head_sha" || true return 1 ;; needs_branch_update) @@ -2190,7 +2136,6 @@ jobs: env: ACTIVE_LABEL: evergreen_active CHECK_GATE_MODE: configured - CI_ACTIVATION_WAIT_SECONDS: "300" CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN || '' }} EVENT_ACTION: ${{ github.event.action }} EVENT_NAME: ${{ github.event_name }} diff --git a/.github/workflows/evergreen.md b/.github/workflows/evergreen.md index 64c27dd0..d6713e89 100644 --- a/.github/workflows/evergreen.md +++ b/.github/workflows/evergreen.md @@ -66,7 +66,6 @@ jobs: EXHAUSTED_LABEL: evergreen-exhausted REQUIRED_CHECKS_JSON: '["Test & Lint","Playground E2E (Playwright)","Build","Validate Python Examples"]' CHECK_GATE_MODE: configured - CI_ACTIVATION_WAIT_SECONDS: "300" MANUAL_PR: ${{ github.event.inputs.pr || '' }} MANUAL_HEAD_SHA: ${{ github.event.inputs.head_sha || '' }} MANUAL_REASON: ${{ github.event.inputs.reason || '' }} @@ -365,42 +364,6 @@ jobs: return 1 } - wait_for_ci_activation() { - local pr="$1" - local head_sha="$2" - local timeout="${CI_ACTIVATION_WAIT_SECONDS:-0}" - local deadline payload current_head state - - if ! grep -Eq '^[0-9]+$' <<<"$timeout" || [ "$timeout" -le 0 ]; then - return 1 - fi - - deadline=$((SECONDS + timeout)) - while [ "$SECONDS" -lt "$deadline" ]; do - sleep 10 - payload="$(pr_json "$pr")" - current_head="$(jq -r '.headRefOid' <<<"$payload")" - if [ "$current_head" != "$head_sha" ]; then - echo "PR #$pr head changed from $head_sha to $current_head while waiting for CI." - return 0 - fi - - state="$(evaluate_readiness "$payload")" - case "$state" in - waiting|needs_ci) - echo "CI for PR #$pr is still $state; continuing to wait." - ;; - *) - echo "CI for PR #$pr settled to $state." - return 0 - ;; - esac - done - - echo "CI for PR #$pr did not settle within ${timeout}s; a later Evergreen run will continue." - return 1 - } - update_branch_if_needed() { # Deterministic branch freshness handling. Keep base-branch merges out # of agent patches so safe outputs only contain repair edits. @@ -476,25 +439,7 @@ jobs: return 1 ;; needs_ci) - if trigger_ci_if_needed "$pr" "$head_sha" && - wait_for_ci_activation "$pr" "$head_sha"; then - payload="$(pr_json "$pr")" - head_sha="$(jq -r '.headRefOid' <<<"$payload")" - state="$(evaluate_readiness "$payload")" - if ! reconcile_ready_label "$pr" "$state" "$payload"; then - echo "Could not reconcile $READY_LABEL for PR #$pr after CI activation; refusing to dispatch the agent." - set_result "false" "$pr" "$head_sha" "blocked" "$reason:ready_label_failed" - return 1 - fi - - if [ "$state" = "needs_repair" ]; then - if ! claim_active_label "$pr" "$head_sha" "$reason:ci_failed_after_activation"; then - return 1 - fi - set_result "true" "$pr" "$head_sha" "$state" "$reason:ci_failed_after_activation" - return 0 - fi - fi + trigger_ci_if_needed "$pr" "$head_sha" || true return 1 ;; needs_branch_update) diff --git a/.github/workflows/shared/evergreen/repo-policy.md b/.github/workflows/shared/evergreen/repo-policy.md index 69164dd6..4e69f5a1 100644 --- a/.github/workflows/shared/evergreen/repo-policy.md +++ b/.github/workflows/shared/evergreen/repo-policy.md @@ -48,8 +48,8 @@ readiness controller and the agentic orchestrator must both respect this file. - Pending check policy: `waiting` — do not repair pending or in-progress checks unless another configured gate has already failed. - Missing/stale check policy: `needs_ci` — reactivate the latest `CI` run for the - head SHA once, wait briefly for a result, then dispatch repair in the same run - if the gate fails (see CI/CD Activation). Never rerun green checks. + head SHA once, then stop so a later reconciliation can classify the resulting + checks (see CI/CD Activation). Never rerun green checks. - Branch freshness ready criterion: not required to be up to date with `main`; freshness is only enforced when the branch is conflicted (`DIRTY`/`UNKNOWN`). - Additional deterministic ready criteria: PR open, has `evergreen`, not @@ -105,9 +105,7 @@ readiness controller and the agentic orchestrator must both respect this file. - Workflows/checks Evergreen may dispatch: none by name in v1; activation is rerun-based only. - Stale check policy: reactivate the latest `CI` run for the head SHA once per - head; briefly wait for it to settle; dispatch repair immediately if a - configured gate fails; never rerun green checks; never re-trigger an already - in-progress run. + head; never rerun green checks; never re-trigger an already in-progress run. - Missing check policy: if no `CI` run exists for the head SHA, wait for the normal `pull_request`/schedule CI to start rather than forcing activation. - Empty commit policy: empty trigger commits are a last resort only, requested