diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78d31a84..0559df0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,10 @@ on: # can still turn the gate red — without this it fires no run and a PR # merges on a false green. - 'motion/**' + # The Pages redirect stubs land on slave alone; a docs-redirects-only + # tip fired no run, and the fail-closed release gate read the missing + # conclusion as "unknown" — silently blocking every release proposal. + - 'docs-redirects/**' pull_request: branches: - master @@ -70,6 +74,7 @@ on: - 'CHANGELOG.md' - 'docs/**' - 'motion/**' + - 'docs-redirects/**' workflow_dispatch: # A fleet branch that's also an open PR head can get both a `push` and a diff --git a/CHANGELOG.md b/CHANGELOG.md index 743cd85d..0b265fb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,10 +30,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changed +- **The `opus` alias upgrades from Claude Opus 4.6 to Claude Opus 4.8.** `MODEL_MAP["opus"]` now resolves to `claude-opus-4-8` — the newest Opus tier, at the same price as 4.6 — so every Opus-routed role (PR reviewer, Auditor, Board, CEO, Intake, Secretary) rides it at next spawn. Pricing already covered the id via the `claude-opus-4` fragment; a new `test_opus_is_priced` guard keeps the alias from ever pointing at an unpriced model. - **Panel dialogs converge on one shape: one disclosure primitive, DialogFooter everywhere, three dialog widths.** `collapsible-section` becomes the single sectioned-disclosure primitive — task dialogs' raw `Collapsible` and create-project's ad-hoc `showAdvanced` both move onto it; every hand-rolled dialog footer becomes `DialogFooter`; dialog widths collapse from ten ad-hoc classes to three named sizes, with deliberate outliers annotated. No behavioral change. ### Fixed +- **docs-redirects-only commits fire a CI run so the release gate gets a verdict.** The CI paths filter covered docs/panel/motion-only slave commits but not `docs-redirects/**`, so a redirect-stub commit landing as the slave tip produced no CI run at all — and the fail-closed release-readiness gate read the missing conclusion as "unknown", silently holding back every release proposal until an unrelated code commit happened to land. - **Mix-mode routing gained its escape hatch (#663).** A fully-pinned fleet had no way back to a global mode: mode switches deliberately spare per-agent pins, but the server refused an empty mix map and the panel refused an empty save — so with every agent pinned, the mode buttons were permanent no-ops behind a success toast and the mode label read "mix" forever. An empty per-agent map is now the explicit clear-all, Save mix with nothing picked confirms and clears instead of erroring, a Clear-all button resets every agent to inherit-global in one click, and the Routing-mode section warns when per-agent overrides outrank the mode buttons. - **The lazy DB engine rebinds per event loop (#663).** The global engine cache was loop-agnostic while its pooled connections are loop-bound, so a second event loop touching it (a test's `asyncio.run`, a second server thread, the eval bench's disposable stack) eventually drew a foreign-loop connection and died with "Future attached to a different loop" — the eval-bench smoke's flaky CI timeout. The engine/factory accessors now stamp the owning loop and discard-and-rebuild on cross-loop access; production runs one loop, so nothing changes there. - **Expired-unacked notifications re-escalate with backoff instead of forever (#652).** The re-escalation sweep fired on every ~60s tick for every expired unacked row — 3 escalations/minute to the CEO in the live incident. Each row now carries a backoff schedule (first fire at expiry, doubling from a 1h base capped at 24h, permanently parked past 5 attempts), and the attempt slot is claimed by compare-and-set before any delivery, so racing sweep ticks can never double-send.