Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 10 additions & 2 deletions scripts/canary-rollout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -897,8 +897,10 @@ cmd_evaluate() {
echo "::warning::triage=SUSPECT — failure matches a suspect class (possibly candidate-caused). BLOCKS + needs a human; see the blocker issue's discriminating question, then promote --override if unrelated or roll back if a real regression."
elif [ "$downgrade" = "DOWNGRADE" ]; then
echo "::notice::triage=PRE_EXISTING (auto-downgraded from SUSPECT, #668 increment 6) — the candidate's suspect-class failure rate (${dg_cand_rate}‰ over ${dg_cand_sample} runs) is no worse than the prior version's (${dg_base_rate}‰ over ${dg_base_sample} runs), so the timeout is environmental, not a candidate regression. Report only; the SUSPECT hold auto-cleared (no human needed). Advances with --allow-pre-existing once dwell/sample pass."
else
elif [ "$triage" = "PRE_EXISTING" ]; then
echo "::warning::triage=PRE_EXISTING — failure is pre-existing/environmental. Report only; do NOT rollback, do NOT advance."
Comment thread
don-petry marked this conversation as resolved.
Outdated
else
echo "::warning::state=BLOCKED (indeterminate) — could not resolve the candidate's cut date, so the gate fails closed and holds (not a detected failure; cum_fail=$cum_fail). Clears once the candidate's cut date/tag is resolvable."
fi
elif [ "$state" = "AWAITING_CONFIRMATION" ]; then
echo "::notice::state=AWAITING_CONFIRMATION — reliability PASSED; holding for an opt-in human go/no-go at $transition (#668 Layer 3). Review the canary-confirm issue, then dispatch: promote $agent --confirm (not --override)."
Expand Down Expand Up @@ -1185,8 +1187,14 @@ $(printf '%s\n' "$guidance" | sed 's/^/> /')"
> |---|---|---|
> | candidate | \`$dg_cand_rate\` | $dg_cand_sample |
> | baseline | \`$dg_base_rate\` | $dg_base_sample |"
else
elif [ "$triage" = "PRE_EXISTING" ]; then
note="> ⚠️ **PRE_EXISTING** — the failure is pre-existing/environmental (reusable byte-identical to the prior channel). Report only; the gate will not roll back or advance. Fix-forward, and the armed timer auto-promotes once clean."
else
# Fail-closed hold (_frontier_state: cut_z empty) — state=BLOCKED but triage="-" and cum_fail=0.
# There is no detected failure; the gate could not resolve the candidate's cut date, so it
# holds rather than evaluate an unbounded window. Do NOT claim PRE_EXISTING here (there is
# nothing environmental to report) — say what actually happened.
note="> ℹ️ **INDETERMINATE (gate held — candidate cut date unresolved)** — the gate could not resolve this candidate's cut date, so it fails closed and holds the promotion instead of evaluating an unbounded run history. This is **not** a detected run failure (cumulative failures: $cum_fail). It usually clears on its own once the candidate's release tag/cut date becomes resolvable; if it persists, verify that candidate \`${cand:0:12}\` is a tagged, resolvable commit on \`$host\`."
fi
cat <<EOF
<!-- canary-blocker:$agent -->
Expand Down
35 changes: 35 additions & 0 deletions tests/canary_rollout.bats
Original file line number Diff line number Diff line change
Expand Up @@ -2041,6 +2041,41 @@ GHEOF
[[ "$output" == *"override"* ]] # the guidance names the fast path when unrelated
}

@test "_blocker_body: PRE_EXISTING triage still renders the genuine pre-existing banner" {
# Regression guard: a real PRE_EXISTING triage must keep its banner + fix-forward note.
run env CANARY_RINGS="$RINGS" bash -c \
"source '$ORCH' && _blocker_body dev-lead 'next->ring0' cccccccccccc 1 0 PRE_EXISTING petry-projects/.github-private '_(evidence)_'"
[ "$status" -eq 0 ]
[[ "$output" == *"PRE_EXISTING"* ]]
[[ "$output" == *"byte-identical"* ]]
}

@test "_blocker_body: indeterminate triage (cut date unresolved) does NOT claim PRE_EXISTING" {
# Fail-closed path (_frontier_state, cut_z empty): state=BLOCKED, triage="-", cum_fail=0.
# The body must not falsely assert an environmental/byte-identical failure — there is none.
run env CANARY_RINGS="$RINGS" bash -c \
"source '$ORCH' && _blocker_body ci-failure-analyst 'next->ring0' df3b7d462460 0 0 - petry-projects/.github-private '_(no candidate cut date resolved — cannot list failing runs)_'"
[ "$status" -eq 0 ]
[[ "$output" != *"PRE_EXISTING"* ]]
[[ "$output" != *"byte-identical"* ]]
# It must instead surface the honest reason: an unresolved cut date holding the gate.
[[ "$output" == *"cut date"* ]]
[[ "$output" == *"INDETERMINATE"* ]]
}

@test "orchestrator: evaluate warning for a fail-closed frontier does NOT claim PRE_EXISTING" {
# cmd_evaluate's BLOCKED branch must distinguish triage="-" (cut date unresolved) from a real
# PRE_EXISTING failure, so the job-log warning is not misleading.
run env CANARY_RINGS="$RINGS" bash -c '
source "'"$ORCH"'"
_frontier_state() { echo "df3b7d462460 ring0 next->ring0 BLOCKED 0 4 0 3 0 0 0 - - - 0 0 0 0"; }
cmd_evaluate ci-failure-analyst'
[ "$status" -eq 0 ]
[[ "$output" == *"BLOCKED"* ]]
[[ "$output" != *"PRE_EXISTING"* ]]
[[ "$output" == *"cut date"* ]]
}

# ── sync-issues needs-human label routing for SUSPECT triage ─────────────────────────
# The create path applies needs-human for both REGRESSION and SUSPECT (fixed in 4cd379b).
# The update path must match: when an existing open blocker is refreshed with SUSPECT
Expand Down
Loading