From 1e799bb81916be7ca824599df3e867a2630a9778 Mon Sep 17 00:00:00 2001 From: Dimitri Kennedy <344842+roodboi@users.noreply.github.com> Date: Fri, 13 Nov 2026 07:35:42 -0500 Subject: [PATCH 1/2] fix(ci): let active next push runs finish --- .github/workflows/ci.yml | 7 ++++--- docs/reference/ci-test-selection.md | 11 ++++++++--- tests/ci-trusted-policy.test.ts | 4 ++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f778062b..4bcd937da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,10 +18,11 @@ on: default: true concurrency: - # Only the newest next push needs evidence. Main pushes and explicit release - # qualification keep unique groups; a pending main run must never be replaced. + # Let the active next run finish, including jobs waiting for macOS capacity. + # New next pushes replace only the pending run. PRs still cancel stale runs; + # main pushes and explicit release qualification keep unique groups. group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || (github.event_name == 'push' && github.ref == 'refs/heads/next' && 'push-next') || format('push-{0}', github.run_id) }} - cancel-in-progress: ${{ github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/next') }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: changes: diff --git a/docs/reference/ci-test-selection.md b/docs/reference/ci-test-selection.md index d821b9875..20eee4b8e 100644 --- a/docs/reference/ci-test-selection.md +++ b/docs/reference/ci-test-selection.md @@ -109,9 +109,14 @@ prerelease gate requires that lane explicitly. macOS ARM qualification remains separate from candidate tests because their repeated setup is small compared with the compiler's transport and bundle checks. -`next` pushes share a cancelling concurrency group; each new push cancels its -predecessor. `main` pushes retain unique, non-cancelling groups. Manual full runs -have unique groups and cannot be cancelled by a later `next` push. +`next` pushes share a non-cancelling concurrency group: the active run finishes, +including jobs waiting for macOS capacity. GitHub retains at most one pending run; +a newer push replaces that pending run, so intermediate revisions may not run. +This preserves all selected macOS coverage without changing runner capacity or +the PR layout. It does not reserve macOS slots or guarantee a queue wait bound. +PRs still cancel stale runs for the same PR. `main` pushes retain unique, +non-cancelling groups. Manual full runs have unique groups and cannot be cancelled +by a later `next` push. ## Historical replay diff --git a/tests/ci-trusted-policy.test.ts b/tests/ci-trusted-policy.test.ts index c2197b2b2..b9a36bb06 100644 --- a/tests/ci-trusted-policy.test.ts +++ b/tests/ci-trusted-policy.test.ts @@ -315,12 +315,12 @@ test("retargeting reclassifies through the ordinary pull_request event", () => { expect(workflow.on.pull_request.types).toContain("edited"); }); -test("only next pushes share a cancelling group; main and dispatch remain unique", () => { +test("next pushes serialize without cancelling active runs; only PRs cancel", () => { expect(workflow.concurrency.group).toBe( "${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || (github.event_name == 'push' && github.ref == 'refs/heads/next' && 'push-next') || format('push-{0}', github.run_id) }}" ); expect(workflow.concurrency["cancel-in-progress"]).toBe( - "${{ github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/next') }}" + "${{ github.event_name == 'pull_request' }}" ); }); From 2f7fd93dd82274d918d6e159e02adbe557da8b57 Mon Sep 17 00:00:00 2001 From: Dimitri Kennedy <344842+roodboi@users.noreply.github.com> Date: Fri, 13 Nov 2026 07:36:54 -0500 Subject: [PATCH 2/2] docs(ci): align coverage map with non-cancelling next runs --- docs/reference/ci-test-selection.md | 2 ++ docs/reference/v5-model-coverage.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/reference/ci-test-selection.md b/docs/reference/ci-test-selection.md index 20eee4b8e..c0dceaa59 100644 --- a/docs/reference/ci-test-selection.md +++ b/docs/reference/ci-test-selection.md @@ -112,6 +112,8 @@ the compiler's transport and bundle checks. `next` pushes share a non-cancelling concurrency group: the active run finishes, including jobs waiting for macOS capacity. GitHub retains at most one pending run; a newer push replaces that pending run, so intermediate revisions may not run. +As described above, a cancelled or missing predecessor forces full selection, +so replacing a pending run cannot omit its merged changes from coverage. This preserves all selected macOS coverage without changing runner capacity or the PR layout. It does not reserve macOS slots or guarantee a queue wait bound. PRs still cancel stale runs for the same PR. `main` pushes retain unique, diff --git a/docs/reference/v5-model-coverage.md b/docs/reference/v5-model-coverage.md index 1dd7bf9d5..60b1e212f 100644 --- a/docs/reference/v5-model-coverage.md +++ b/docs/reference/v5-model-coverage.md @@ -36,7 +36,7 @@ must be attached to the eventual exact integration revision. | Property and critical states | Model coverage | Implementation/regression boundary | Remaining qualification | | --- | --- | --- | --- | -| CI cancellation must not lose merged-change coverage; only exact-head full evidence may qualify a prerelease | No maintained GitHub scheduler model. Finite fixture interleavings cover predecessor success/failure/cancellation, two competing full/scoped runs and two rerun attempts | `ci.yml` shares only the next-push cancellation group and requires a successful before run for selection. `selectPrereleaseCiRun` reads current attempts; `requireBranchChecks` binds suite and job check IDs. `ci-trusted-policy`, `prerelease-plan` and `release-prepare-gate` regressions reject cancelled predecessors, green subsets, stale checks, skipped hosts and changed attempts | API snapshots and GitHub group/event semantics are assumptions; races after the last read remain possible. Publication rechecks the frozen protected head and full evidence but does not transactionally lock GitHub. Hosted dispatch/cancellation checks qualify wiring; no scheduler liveness or formal refinement claim. | +| CI cancellation must not lose merged-change coverage; only exact-head full evidence may qualify a prerelease | No maintained GitHub scheduler model. Finite fixture interleavings cover predecessor success/failure/cancellation, two competing full/scoped runs and two rerun attempts | `ci.yml` serializes next pushes in one non-cancelling group (GitHub cancels only the replaced pending run), cancels stale PR runs, and requires a successful before run for selection. `selectPrereleaseCiRun` reads current attempts; `requireBranchChecks` binds suite and job check IDs. `ci-trusted-policy`, `prerelease-plan` and `release-prepare-gate` regressions reject cancelled predecessors, green subsets, stale checks, skipped hosts and changed attempts | API snapshots and GitHub group/event semantics are assumptions; races after the last read remain possible. Publication rechecks the frozen protected head and full evidence but does not transactionally lock GitHub. Hosted dispatch/cancellation checks qualify wiring; no scheduler liveness or formal refinement claim. | | Native log follower versus lifecycle mutation, frontend loss, stopped container and transport loss | No new state model: the follower observes without a mutation lease and grants no cleanup authority | `provider/graph/log_follow.rs` and its native counterpart pin Ready admission, container and start generation; `provider/engine/log_follow.rs` bounds framing and distinguishes real EOF from stopped-service idle cutoff. `lifecycle_log_follow_tests.rs` keeps the production transport on a fake Engine socket active while acquiring startup and operation leases, with a same-lock contention control and output while each lease is held. `native-log-follow-source.test.ts` guards the observer-only route; process tests cover cancellation, frontend loss, real output-pipe closure while idle, replacement-container restart (including retained adopted run/owner IDs) with one marker, NDJSON admission failures, truncated/partial output and slow idle-end delivery. `native-log-restart.test.ts` covers bounded re-admission, unchanged-container refusal and prompt down; `native-log-selection.test.ts` covers strict finite admission responses and owned-child cancellation/timeouts; advisory markers grant no authority | 4 KiB payload envelopes, 8 KiB wire lines, 64 Ki-character retained payload prefixes excluding Engine timestamps, 30-second restart wait, 1000-line new-container backlog. The portable lease test fakes identity/state checks; it does not exercise host process/disk auditing, graph admission or the VM relay. Real relay EOF on stop/down/restart, VM loss and concurrent lifecycle latency require Apple Silicon acceptance. No performance or whole-product parity claim. | | Foreground group interrupt; publisher exit before authenticated stop; dead owner's pending cleanup enrollment and bridge release | native-publisher-stop | [Process adapter](../../src/backends/native-project-process.ts) isolates Compose owners regardless of hooks; Rust `process::publisher_command` isolates publishers; `legacy_cleanup_enrollment` binds the old coordinator and inventories before a distinct recovery intent. [Group regression](../../tests/native-foreground-group-interrupt.test.ts) signals the whole group for fresh/restore owners; Rust real-publisher process, frontend-loss, exact child-reaping and enrollment tests check grouping, lifetime wakeups and stale selectors. | One graph, one publisher, one crash, one identity replacement and one audited successor boot; 168 states. Publisher exit observation is separate from lease-bound reaping/proof commitment; `NoUncommittedExit` rejects owner cleanup while proof is pending. A busy lease stutters without delaying stop control. SIGHUP requests retaining cleanup; a reaped publisher enters an observable publisher-down state until explicit stop. Native process tests and frontend framing/ps tests cover signal delivery and notices. Dependency release is a separate post-completion step; `NoStrandedReservation` rejects success with a held reservation. Real reservation-file regressions check retry, capacity reuse and refusal fences. Separate stopped-receipt and intent-completion commits are collapsed; TypeScript dispatch and Rust completion-digest regressions cover that interruption window. Publication-registry sync/rename is abstracted and covered by portable commit-interruption tests. Kernel identity, socket/inode proofs, guest observations, durable storage and existing next.13 home recovery remain implementation/Apple Silicon VM gates. No eventual recovery is asserted. | | Exclusive claims; competing writers; partial owner publication | graph-admission, registry-writer, publication-journal, missing-publication-lock, native-frontend-recovery | Admission/registry locks, pending publication and exact saved owner; related runtime ownership tests | Real filesystems, boot/incarnation identity and unsupported writers remain independent. |