fix(#974, Phase A of #981): self-aware required-status-checks for non-Docker PRs#982
Conversation
…-Docker PRs Implements Phase A of the multi-phase CI automation plan tracked under issue #981. Unblocks every PR targeting canary that doesn't touch Docker/Rust paths. PROBLEM (#974, surfaced live 2026-05-01) ========================================= The existing `.github/workflows/docker-images.yml` workflow had two gating problems that combined to make TS-only PRs un-mergeable to canary: 1. `pull_request.branches: [main]` only triggered the workflow on PRs targeting main. PRs targeting canary (the working integration branch per Joel's airc canary-direct workflow) silently never fired the workflow. 2. `pull_request.paths: [src/workers/**, docker/**]` filtered the trigger to only Docker-relevant PRs. TS-only / docs-only PRs never fired the workflow. But canary's repository ruleset REQUIRES `verify-architectures` and `verify-after-rebuild` as required-status-checks. Combined with the above: every TS-only PR targeting canary was permanently un-mergeable because the required checks NEVER ran. The previous quick-fix paths (manually trigger via workflow_dispatch, admin-bypass) all left the meta-bug in place + would have to be re-applied per-PR. Per Joel: "fixes need automation." SOLUTION — self-aware required check ===================================== Workflow now ALWAYS fires (no paths filter on pull_request, branches includes canary). The job decides what to do based on what changed: - docker_relevant == false (TS-only / docs-only PR) → emit ::notice + auto-pass; required check satisfied without touching ghcr; no images verified because none could have been invalidated by the change - docker_relevant == true (Rust core, Cargo.{toml,lock}, docker/, docker-compose.yml, Dockerfile*, or this workflow file itself) → run the existing verification flow unchanged Detection via dorny/paths-filter@v3 in a `detect` step at job start. The detection paths are CONSERVATIVE (Cargo.toml triggers full verify even for tiny Rust changes); false positives are cheap (extra verification), false negatives would skip when needed (tracked + filter list tightened over time). Same pattern applied to verify-after-rebuild: when verify-architectures auto-passed (no docker_relevant changes), there's nothing to re-verify; emit a notice + auto-pass. SCOPE (Phase A only — what this PR does NOT do) ================================================ The full plan (Phases A-F, see docs/infrastructure/CI-AUTOMATION-PLAN.md + tracking issue #981) covers: - Phase B: self-hosted runner registration (BigMama amd64+CUDA, Mac M5 arm64+Metal) so docker_relevant PRs can auto-build images - Phase C: automated image build dispatched to those runners - Phase D: multi-arch manifest stitching - Phase E: caching + skip-if-exists - Phase F: airc-side observability — runners publish state to `#ai-capability` channel per AGENT-BACKBONE §4.3 Phase A is the standalone unblock — TS-only PRs become mergeable TODAY without requiring the build-farm work to ship first. Future phases compose on top. CHICKEN-EGG NOTE ================ This PR itself targets `main` (not canary) so it fires the existing trigger (`branches: [main]`). It also touches `docker-compose.yml` (via a 3-line comment header) so the existing `paths` filter matches too — without that the workflow wouldn't fire on this PR either. After this PR merges to main, cherry-pick / merge to canary so the fixed trigger semantics apply on both branches. FILES TOUCHED ============= .github/workflows/docker-images.yml — self-aware check pattern docker-compose.yml — comment header (chicken-egg) docs/infrastructure/CI-AUTOMATION-PLAN.md — new, full plan + phases TRACKING Tracked under top-level GitHub issue #981 (multi-phase CI automation). Resolves the immediate symptom of #974 (the trigger filter); the deeper architectural work continues across Phases B-F. Composes with the 4 PRs blocked by this meta-bug: continuum#976 AGENT-BACKBONE-INTEGRATION design doc continuum#977 Rust core supervisor (closes #722) continuum#978 ai/local-inference + typing-smell cleanup continuum#979 airc/send Once this lands on canary, those 4 become mergeable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Implements Phase A of the CI automation plan by making the “Verify Docker Images” workflow always run on PRs to main and canary, then conditionally auto-pass required checks when the PR doesn’t affect Docker images—unblocking canary-targeted PRs that previously never produced required status checks.
Changes:
- Update
.github/workflows/docker-images.ymlto trigger on PRs tomainandcanarywithout apathsfilter, and add adorny/paths-filter-based “self-aware” skip path. - Add
docs/infrastructure/CI-AUTOMATION-PLAN.mddocumenting the multi-phase CI/build-farm plan (Phases A–F). - Add a header comment to
docker-compose.ymlto force this PR through the pre-existing workflow trigger constraints.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
.github/workflows/docker-images.yml |
Makes required checks self-aware for PRs to main/canary via paths-filter, with an auto-pass branch for non-image-relevant changes. |
docs/infrastructure/CI-AUTOMATION-PLAN.md |
New infrastructure plan doc describing the phased approach and rationale. |
docker-compose.yml |
Adds a temporary comment explaining the “chicken-and-egg” trigger workaround for this PR. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - 'src/workers/continuum-core/**' | ||
| - 'src/workers/**/Cargo.toml' | ||
| - 'src/workers/**/Cargo.lock' |
There was a problem hiding this comment.
The docker_relevant paths-filter is currently too narrow for the images this workflow verifies. For example, docker/node-server.Dockerfile copies the src/ tree and runs npm run build:ts, docker/widget-server.Dockerfile builds src/examples/widget-ui, and docker/livekit-bridge.Dockerfile depends on src/workers/** sources — but the filter only matches src/workers/continuum-core/** and Cargo.{toml,lock}. This will incorrectly auto-pass required checks on PRs that change TS code, widget UI, or non-core Rust sources, even though those changes invalidate one or more Docker images. Expand the filter to include the actual image inputs (at minimum src/** plus any other non-src inputs you rely on), or otherwise align it with what verify-image-revisions.sh considers image-relevant.
| - 'src/workers/continuum-core/**' | |
| - 'src/workers/**/Cargo.toml' | |
| - 'src/workers/**/Cargo.lock' | |
| - 'src/**' |
| # On push events (no base ref), force docker_relevant=true so | ||
| # we always verify after main lands a commit. On pull_request | ||
| # events, dorny/paths-filter compares HEAD to the PR base. |
There was a problem hiding this comment.
The comment says "On push events ... force docker_relevant=true" but this step doesn't currently implement any override for push events; it will still evaluate the same path filters. Either adjust the configuration to actually force a true value on push, or update the comment so it matches the real behavior.
| # On push events (no base ref), force docker_relevant=true so | |
| # we always verify after main lands a commit. On pull_request | |
| # events, dorny/paths-filter compares HEAD to the PR base. | |
| # On pull_request events, dorny/paths-filter compares HEAD to | |
| # the PR base. On push events, this step still evaluates the | |
| # same docker_relevant path filters; it does not force true. |
|
|
||
| **Status**: Plan, 2026-05-01. Phase A actively shipping. | ||
| **Origin**: live #974 meta-blocker discovery during the M5-QA + dev-tab + M1-Carl-validator parallel session of 2026-05-01. | ||
| **Top-level GitHub issue**: see [issue link to be added once filed]. |
There was a problem hiding this comment.
This doc still has a placeholder for the tracking issue link ("issue link to be added once filed"), but the PR description references issue #981. Please replace the placeholder with the actual issue link so readers can navigate from the plan to the tracker.
| **Top-level GitHub issue**: see [issue link to be added once filed]. | |
| **Top-level GitHub issue**: #981. |
Per Joel 2026-05-01: docker image verification is a MAIN-promotion gate, not a per-PR gate. Canary is the working integration branch where every PR lands without expecting per-PR docker images. Images get collected at canary level via the existing dev pre-push pipeline (scripts/push-current-arch.sh); they aren't required to exist at every PR's SHA. Pre-fix the [main, canary] trigger generated noise on every canary PR — verify-architectures + verify-after-rebuild always failed because no per-PR images existed. Those failures weren't blocking (canary has no required checks now — the ruleset was removed earlier in the day) but cost CI minutes + drowned signal in noise. Joel's PR #985 review: "ci failing with sha issues, but that's expected. Maybe only merge to main from canary should require the docker image check." Phase A history: #974 hit the inverse of this — [main]-only combined with a paths filter meant TS-only PRs to canary couldn't produce the gate at all + were stuck behind a check ruleset that canary did require at the time. Phase A (#982) added canary to the trigger to make the gate produce a result. Later the canary ruleset was removed entirely, so the gate's existence on canary became pure overhead. This is the cleanup. What this changes: - Workflow no longer fires on PRs targeting canary - Workflow still fires on PRs targeting main (the promotion gate) - Workflow still fires on push to main (post-merge sanity check) - Workflow still fires via workflow_dispatch (manual) What stays the same: - Self-aware required-check pattern: workflow auto-passes when change isn't docker-relevant, runs real verification when it is - All existing verify-architectures + verify-after-rebuild semantics - ghcr image cadence: dev machines push images via pre-push hook, scheduled or on-merge as before Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Phase A of the multi-phase CI automation plan tracked under issue #981. Unblocks every PR targeting canary that doesn't touch Docker/Rust paths — currently they're permanently un-mergeable due to the trigger gap that #974 documents.
What changed
.github/workflows/docker-images.yml:pull_request.branches: [main, canary](was[main])pull_request.pathsfilter — workflow always firesdetectstep usingdorny/paths-filter@v3computesdocker_relevantboolean::notice+ auto-pass; required check satisfied without touching ghcrverify-after-rebuilddocs/infrastructure/CI-AUTOMATION-PLAN.md(new): full plan covering Phases A-F.docker-compose.yml(comment header): chicken-egg — touches a path in the existing trigger filter so this PR itself fires the workflow.Why this approach (per Joel "fixes need automation, not workarounds")
The previous workarounds (manually
gh workflow run,--adminbypass, modifying ruleset per-PR) all left the meta-bug in place + had to be re-applied per PR. This fix is structural: the workflow itself becomes self-aware about whether the change it's gating is relevant to its concern. No manual intervention; no ruleset changes required; no per-PR overhead. Once this lands, every PR (TS-only, docs-only, mixed) gets the right gating semantics automatically.What this does NOT do (separate phases under #981)
Phase A is the standalone unblock — TS-only PRs become mergeable TODAY without needing the build farm to ship first.
Composes with the 4 PRs currently blocked by this meta-bug
Once this lands on canary, those 4 become mergeable.
Validation
.github/workflows/docker-images.ymlwhich IS in the docker_relevant list); the existing verification will run + pass per the chicken-eggdocker-compose.ymltouch matching the existing path filterTracking
Top-level: #981 (multi-phase CI automation plan).
Symptom: #974.
🤖 Generated with Claude Code