From 9edd74d70332c17928db26e9aea944d68dd978e1 Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Sat, 11 Jul 2026 16:10:36 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20onboard=20pr-auto-review=20to=20the=20c?= =?UTF-8?q?anary=20ring=20model=20=E2=80=94=20unmanaged=20block=20now=20em?= =?UTF-8?q?pty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the decision that pr-auto-review needs staged, blast-radius-contained rollout (a bad @v2 move breaks PR-review dispatch in all consumer repos at once), bring it under canary instead of the frozen-@v2 model. - Cut pr-auto-review/v1.0.0 + next/ring0/ring1/stable at @v2's commit (376a4fcb) — a ZERO-behavior-change migration: consumers repin off @v2 onto the namespaced channels running the exact same code. The pending pr-auto-review changes already on main (ahead of v2) will then roll out via canary SOAK (autocut cuts the next candidate; .github ring0 dogfoods it via `./`), rather than a big-bang @v2 move. - Register in canary-rings.json (host=.github, standard organic-traffic rings/gate) and REMOVE from unmanaged{} — which is now empty. Every fleet *-reusable.yml is a managed canary agent. Note: canary currently gates on reliability (run health), not correctness — a known limitation for decision-making agents, tracked as an enhancement (#668); onboarding proceeds on reliability now per that decision. Validated (read-only vs live tags): evaluate → COMPLETE; drift 0. canary_rollout.bats green (+pr-auto-review shape test). Remaining: migrate consumers off @v2 → @pr-auto-review/. Refs #668. Co-Authored-By: Claude Opus 4.8 (1M context) --- standards/canary-rings.json | 67 ++++++++++++++++++++++++++++++++++--- tests/canary_rollout.bats | 12 +++++++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/standards/canary-rings.json b/standards/canary-rings.json index 8d414bd4e..476fb267f 100644 --- a/standards/canary-rings.json +++ b/standards/canary-rings.json @@ -857,13 +857,70 @@ } } } - } - }, - "unmanaged": { + }, "pr-auto-review": { "host": "petry-projects/.github", "reusable": ".github/workflows/pr-auto-review-reusable.yml", - "reason": "Frozen-major @v2 review-dispatcher infra \u2014 not a canary-promoted agent." + "run_workflow": "PR Auto-Review \u2014 Ready Check", + "rings": [ + { + "channel": "next", + "order": 0, + "members": [ + "petry-projects/.github-private" + ] + }, + { + "channel": "ring0", + "order": 1, + "members": [ + "petry-projects/.github" + ] + }, + { + "channel": "ring1", + "order": 2, + "members": [ + "petry-projects/TalkTerm", + "petry-projects/bmad-bgreat-suite" + ] + }, + { + "channel": "stable", + "order": 3, + "members": [ + "*" + ] + } + ], + "gate": { + "_standard": "petry-projects/.github#548 \u2014 graduated dwell/sample gate over a per-candidate cumulative window. These are registry-configurable per-transition knobs; the values below are the #548 defaults.", + "baseline_window_days": 14, + "baseline_spike_cap_multiple": 3, + "benign_failure_classes": [], + "control": { + "allow_pre_existing": false + }, + "_benign_note": "benign_failure_classes (#1025 P2): per-reusable allowlist matched against a failed run's workflow name (`workflow` ERE) + failed-step signature (`step` ERE, matched via `gh run view`). Matches are excluded from cum_fail \u2014 but ONLY when the candidate's reusable is byte-identical to the prior channel (differs=0), so the allowlist can never mask a candidate-introduced regression. `control.allow_pre_existing`, or `promote --allow-pre-existing`, advances a BLOCKED+PRE_EXISTING frontier (never REGRESSION).", + "transitions": { + "next->ring0": { + "dwell_hours": 4, + "sample_fraction_permille": 250, + "sample_clamp_min": 3, + "sample_clamp_max": 15, + "waive_sample_if_no_caller": true + }, + "ring0->ring1": { + "dwell_hours": 8, + "waive_sample": true + }, + "ring1->stable": { + "dwell_hours": 12, + "sample_min": 1 + } + } + } } - } + }, + "unmanaged": {} } diff --git a/tests/canary_rollout.bats b/tests/canary_rollout.bats index da09ae53d..92c954a36 100644 --- a/tests/canary_rollout.bats +++ b/tests/canary_rollout.bats @@ -201,6 +201,18 @@ setup() { } # ── canary-rings.json SoT shape (rings + gate knobs) ────────────────────────── +@test "canary-rings.json: pr-auto-review onboarded to canary; unmanaged block emptied" { + run jq -e '.agents["pr-auto-review"].host == "petry-projects/.github"' "$RINGS" + [ "$status" -eq 0 ] + run jq -e '.agents["pr-auto-review"].run_workflow == "PR Auto-Review — Ready Check"' "$RINGS" + [ "$status" -eq 0 ] + run bash -c "jq -r '.agents[\"pr-auto-review\"].rings | sort_by(.order) | map(.channel) | join(\",\")' '$RINGS'" + [ "$output" = "next,ring0,ring1,stable" ] + # every reusable is now a managed agent — the unmanaged block holds nothing + run jq -e '(.unmanaged // {}) | length == 0' "$RINGS" + [ "$status" -eq 0 ] +} + @test "canary-rings.json: add-to-project onboarded to full ring model (#651)" { run jq -e '.agents["add-to-project"].host == "petry-projects/.github"' "$RINGS" [ "$status" -eq 0 ]