Skip to content

ci: run every PostgreSQL shard on cargo-nextest, not just the pilot - #853

Merged
jason931225 merged 2 commits into
mainfrom
ci/nextest-all-postgres-shards
Aug 21, 2026
Merged

ci: run every PostgreSQL shard on cargo-nextest, not just the pilot#853
jason931225 merged 2 commits into
mainfrom
ci/nextest-all-postgres-shards

Conversation

@jason931225

Copy link
Copy Markdown
Collaborator

#840 put one shard on nextest to measure it. Measured on merge_group run 32402124838, the pilot against its nearest neighbour:

shard targets runner wall
domain adapters B 45 nextest 6m
domain adapters A 40 cargo 15m

More tests, less than half the wall clock — the 2.35× benchmark reproduced on real CI against a bigger shard. The pilot has done its job, so the remaining four shards move to the same hash-pinned installer and runner.

What this does not do — and the measurement matters more than the change

The critical path of a merge_group run is not the shards:

Backend — fmt / clippy / test / gates   17m   <- critical path
Test PostgreSQL — platform              15m
Test PostgreSQL — domain adapters A     15m
Test PostgreSQL — app                   15m

Taking the shards to ~6–7m leaves wall clock pinned near 17m by Backend, whose own 17m is an accumulation rather than a hot spot: 5m dev-auth PG suites, 3m clippy, 3m console-app unit, ~4m setup, and 24 further steps at or under a minute. Splitting it is the next lever and a much larger ci.yml change.

A second measurement, taken locally while checking isolation: the platform shard runs 154 tests in 263s, and 263s of that is one testconsole-gate-writer-ownership::census_executes_against_postgres. No runner change takes that shard below ~4.5m. Shards are not uniformly runner-bound, and the remaining gains are not evenly distributed.

Isolation — the actual risk, and why it was piloted

nextest runs test binaries in parallel where cargo ran them serially, so a suite sharing state would newly fail. Verified locally before pushing: the platform shard passes 154/154 under nextest, with the cluster-global serial group in .config/nextest.toml doing its job.

Ratchets moved up: run-step coverage 126 → 130, bypass matrix 378 → 390, because each new install step goes through the same three mutations as every other. 61 preflight contract tests pass.

🤖 Generated with Claude Code

#840 put ONE shard on nextest to measure it. Measured on merge_group run
32402124838, the pilot against its nearest neighbour:

  domain adapters B  45 targets  nextest   6m
  domain adapters A  40 targets  cargo    15m

More tests, less than half the wall clock. That is the 2.35x from the
original single-target benchmark, reproduced on real CI against a bigger
shard, so the pilot has done its job.

The remaining four shards move to the same hash-pinned installer and runner.

WHAT THIS DOES NOT DO, and the measurement matters more than the change.
The critical path of a merge_group CI run is not the shards:

  Backend — fmt / clippy / test / gates   17m   <- critical path
  Test PostgreSQL — platform              15m
  Test PostgreSQL — domain adapters A     15m
  Test PostgreSQL — app                   15m

So taking the shards to ~6-7m leaves wall clock pinned near 17m by Backend,
whose own 17m is an accumulation rather than a hot spot: 5m dev-auth
PostgreSQL suites, 3m clippy, 3m console-app unit, ~4m setup, and 24 further
steps at or under a minute. Splitting it is the next lever and a much larger
ci.yml change; this one is proven and mechanical.

A second measurement, taken locally while checking isolation: the platform
shard runs 154 tests in 263s, and 263s of that is ONE test —
`console-gate-writer-ownership::census_executes_against_postgres`. No runner
change takes that shard below ~4.5m. Shards are not uniformly runner-bound,
and the remaining gains after this are not evenly distributed.

ISOLATION, which is the actual risk of this change and why it was piloted:
nextest runs test binaries in parallel where cargo ran them serially, so a
suite that shared state would newly fail. Verified locally before pushing —
the platform shard passes 154/154 under nextest, with the cluster-global
serial group in `.config/nextest.toml` doing its job.

Ratchets moved UP: run-step coverage 126 -> 130 and the bypass matrix
378 -> 390, because each new install step goes through the same three
mutations as every other run step. 61 preflight contract tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jason931225

Copy link
Copy Markdown
Collaborator Author

Executive Overview & Adversarial Quality Assessment

PR #853 rolls out cargo-nextest across the remaining four PostgreSQL test shards (app, platform, ontology, domain-a), generalizing the pilot implemented in PR #840 (domain-b). The migration replaces serial test binary execution with parallel scheduling while preserving database isolation via cluster-global serial groups in .config/nextest.toml.

The PR is exceptionally well-structured and disciplined: workflow steps use hash-pinned binary installations via tools/ci/install_nextest.sh, preflight step contracts and SHA-256 proof digests are strictly maintained, and preflight bypass ratchets are incremented monotonically (run-step count 126 → 130; mutation count 378 → 390).


16-Lens Canonical Framework Analysis

Lens Evaluation Status
1. Cartesian Doubt Solves the shard duration bottleneck proven during pilot (15m → 6m). Accurately identifies that critical path remains bound by monolithic Backend (17m). Pass
2. Essentialism / YAGNI Minimal and necessary; uniformly applies the proven pattern across all 4 remaining reachability facets. Pass
3. Chesterton's Fence Respects prior CI design and verification architecture by upholding all step contract proofs and anti-bypass constraints. Pass
4. Contrarian / 10x Validates the nextest optimization across shards while properly deferring the larger Backend pipeline decomposition to subsequent PRs. Pass
5. Socratic Contracts are tight. Identified a minor schema inconsistency in postgresReachabilityFacetSetupCommands where domain-b uses an Array while other facets use a joined String. Minor Nit
6. Pragmatism Balances immediate ~36 compute-minute CI reduction with zero runtime production risk. Pass
7. Red Team Pinned binary download is verified against NEXTEST_PINNED_SHA256 and executed within isolated runner temp paths. Pass
8. Systems Thinking Relieves GitHub Actions runner pool contention across concurrent PR merge queues. Pass
9. Operability / Day-2 Nextest provides superior test failure granularity, execution timing, and targeted rerun ergonomics. Pass
10. Opportunity Cost Standardizes all database test shards onto a single runner implementation, reducing cognitive overhead. Pass
11. Blast-radius Confined strictly to CI test execution; preflight contract tests guarantee harness integrity before merge. Pass
12. Constant-work Parallelized test binary dispatch bounds execution time across multi-core CI runners. Pass
13. Shared-nothing Independent disposable Postgres instances prevent cross-shard state pollution. Pass
14. FinOps / Unit-cost High-impact FinOps win: saves ~36 runner-minutes per full CI run across 4 shards. Pass
15. Telemetry-first Shard timing benchmarks and nextest execution metrics are fully visible. Pass
16. Zero-trust / Defense-in-depth Preflight ratchet validation increased from 378 to 390 bypass mutations to prevent unverified skips. Pass

Key Findings & Polish

  1. Data Structure Consistency (check-ci-preflight.mjs): postgresReachabilityFacetSetupCommands["postgres-reachability-domain-b"] remains an array literal [...] while the other four facets map to the string nextestInstallSetupCommands. Normalizing domain-b to nextestInstallSetupCommands improves type uniformity.
  2. Comment Typo (check-ci-preflight.test.mjs): Duplicate sentence fragment ("Coverage GREW; ... Coverage GREW: the new ...") in the ratchet history doc comment.

Findings not addressable in the diff

  • scripts/check-ci-preflight.mjs:582 [RIGHT] -- diff unavailable or unparseable: Minor consistency nit: postgres-reachability-domain-b is still assigned an array literal [...], whereas app, platform, ontology, and domain-a use nextestInstallSetupCommands (which is .join("\n")). Consider setting "postgres-reachability-domain-b": nextestInstallSetupCommands to maintain uniform type semantics across all shard keys.
  • scripts/check-ci-preflight.test.mjs:703 [RIGHT] -- diff unavailable or unparseable: Minor documentation polish: Stuttered copy-paste in comment (Coverage GREW; each new install step goes through the same three bypass mutations as every other run step. Coverage GREW: the new step goes through the same three bypass mutations as every other one.). Consider deduplicating the repeated phrase.

🤖 [Reviewed] by Oyatie Anvil

@jason931225

jason931225 commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator Author

❌ Blocked — 12 finding(s) across 72 gates; 9 gate(s) produced no measurement.

  • doc-parity — errored: doc parity probe supervision failed: Execution failed: doc parity probe exited with status exit status: 1: Error: Eligibility check failed: UNAVAILABLE (code 503): The service is currently unavailable.
    • fix: update the affected docs, or add an ADR under docs/decisions/
    • note: this gate is partial fidelity and does not fully measure what its name implies
  • clean-arch — not measured: no core/ports/adapters/facade layering found: 0 of 1 file(s) examined belong to a recognised layer
  • slo — not measured: no Prometheus or OpenTelemetry endpoint is configured, so error budget consumption over any window was never queried
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • cluster-audit — not measured: no Kubernetes API or ArgoCD cluster access is configured, so no live state was read back and no comparison against Git was performed
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • ci-wallclock — not measured: no GitHub Actions workflow-run timing API access is configured, so neither this PR's CI duration nor its billable compute was read
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • remote-cache — not measured: no sccache or Buck2 CAS statistics endpoint is configured, so no cache hit rate was read and no lockfile was hashed
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • shadow-traffic — not measured: no traffic mirror and no replay target are configured, so no production requests were sampled and no responses were compared
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • brand-absence — failed: 12 name(s) or PR-visible string(s) stamp an aspiration instead of naming what the code verifies
  • shape — warning: no shape spec adopted (.anvil/shape.json absent); see anvil shape validate-spec
    • fix: run anvil shape plan --repo-dir <clone> for the move plan; a regression on a blocking rule needs an entry in .anvil/baselines/shape.signoff.json
    • note: this gate is partial fidelity and does not fully measure what its name implies
  • automated-canary — not measured: no canary deployment and no Prometheus or OpenTelemetry metrics endpoint are configured, so no baseline or canary latency samples were ever read
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • stacked-diffs — not measured: no pull request DAG was read from the forge, so this PR's parent branch and any children stacked on it are unknown and no stack was evaluated
    • note: this gate is aspirational fidelity and does not fully measure what its name implies
  • microbench — not measured: no criterion benchmark harness or published baseline exists for this repository, so neither the base nor the head ns/op figure was ever measured
    • note: this gate is aspirational fidelity and does not fully measure what its name implies

🤖 [Blocked] by Oyatie Anvil

The first run with every shard on nextest failed ONE test:

    TIMEOUT [ 360.005s] console-gate-writer-ownership::
      census_executes_against_postgres census_binds_to_an_executed_database

Not an isolation bug. That test is EIGHT sequential migrate+enforce cycles
against a Docker PostgreSQL in a single test function -- the mutation matrix
for the canonical-enforcement census -- at ~33s a cycle. I measured it at
263s locally and noted it in #853's own message; a hosted runner took it past
nextest's 120s x 3 = 360s terminate ceiling. cargo never enforced a ceiling,
which is why the shard was green before and is how a hang would also have
passed.

The ceiling is raised for THIS binary only, via a profile.ci override on
`binary(census_executes_against_postgres)`. The global 360s stays: it is what
catches a genuinely hung test, and widening it everywhere to fit one
known-slow suite would hide hangs in the other 153.

Proven:
  - the filter selects the real binary (23 tests); a misspelt filter selects
    zero, so a typo cannot silently leave the old ceiling in force;
  - `cargo nextest run --profile ci` on that test: PASS in 174.9s, flagged
    slow, not terminated;
  - check-nextest-config and its tests pass; gate sweep 13/13.

The other four shards were already green: on the same run domain-a 6m,
app 7m, ontology 5m, domain-b 5m -- every shard now 5-8m, down from 13-15m.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jason931225

Copy link
Copy Markdown
Collaborator Author

Executive Overview

This incremental update to PR #853 introduces a targeted [[profile.ci.overrides]] rule in .config/nextest.toml for the census_executes_against_postgres test binary, raising its slow-timeout ceiling from 360s (120s × 3) to 960s (120s × 8).

During the rollout of cargo-nextest across all PostgreSQL test shards (expanding beyond the domain adapters B pilot), the platform shard encountered timeout terminations on hosted CI runners. While the heavy census test completes in ~263s in optimized local environments, hosted virtual runners experience higher I/O and Docker virtualization overhead across the test's 8 sequential migration and enforcement cycles. This override permits the long-running serial binary to complete reliably without loosening the 360s termination ceiling across the other 153 tests in the shard.


16-Lens Canonical Adversarial Review Matrix

# Lens Evaluation & Adversarial Findings
1 Cartesian Doubt Validated. The override directly targets the empirical failure mode (hosted virtualization overhead on sequential DB migrations) rather than arbitrarily bumping CI timeouts globally.
2 Essentialism / YAGNI Minimal. The diff adds only 13 lines of configuration and documentation, applying the override strictly to the single offending binary target.
3 Chesterton's Fence Preserved. The global 360s timeout ceiling (period = "120s", terminate-after = 3) was established to detect genuine deadlocks in PostgreSQL suites; it remains intact for all other test targets.
4 Contrarian / 10x Opportunity. The 8 sequential migration+enforce passes represent a legacy monolithic test pattern. Isolating them into ephemeral schemas or database instances would allow nextest to run all 8 passes concurrently.
5 Socratic Contract Sound. Filter target binary(census_executes_against_postgres) cleanly captures the integration test harness binary, accommodating the internal census_binds_to_an_executed_database test routine.
6 Pragmatism Approved. Unblocks the remaining 4 shards from adopting nextest (halving shard runtimes from ~15m to ~6m) without requiring a high-friction refactor of the census suite.
7 Red Team / Security Low Risk. The 960s ceiling prevents indefinite runner hangs or denial-of-service in CI workflows, operating well within standard CI job timeout limits.
8 Systems Thinking Cohesive. Works in tandem with the .config/nextest.toml cluster-global serial group to prevent Postgres connection and state collisions during parallel test execution.
9 Operability / Day-2 High Visibility. period = "120s" ensures nextest emits periodic slow-test heartbeat warnings to CI logs every 2 minutes, preventing silent execution blackholes.
10 Opportunity Cost Favorable. Enables immediate compute savings across all PostgreSQL shards with negligible configuration maintenance overhead.
11 Blast-Radius / Cell-based Contained. Blast radius is strictly constrained to binary(census_executes_against_postgres); no other platform, adapter, or app tests inherit the extended timeout.
12 Constant-Work / Anti-fragility Robust. The 960s threshold absorbs standard variance in hosted CI hypervisor and disk I/O performance under multi-tenant load.
13 Shared-Nothing Verified. Serial execution of the 8 cycles within the single binary guarantees migration script idempotency without interfering with concurrent shard execution.
14 FinOps / Unit-Cost Positive. Unlocks a ~50% reduction in runner-minutes across 4 shards, significantly reducing total CI billing and queue contention.
15 Telemetry-First Enabled. Nextest outputs structured JUnit timing telemetry per binary, allowing automated tracking of timing drift in the census harness.
16 Zero-Trust / Defense Compliant. Follows the principle of least privilege in CI runner configuration by isolating the timeout extension to an explicit filter.

Critical Risks & Recommendations

  1. Ceiling Proximity to Critical Path: 960s (16m) is close to the 17m Backend critical path. While this binary currently finishes in ~5–6m on hosted runners, any substantial test additions to census_executes_against_postgres could make this binary the new critical path bottleneck.
  2. Decomposition Roadmap: File a tracking issue to decompose the 8 sequential migration/enforcement cycles into discrete integration tests backed by isolated database schemas/templates.

Findings not addressable in the diff

  • .config/nextest.toml:42 [RIGHT] -- diff unavailable or unparseable: filter = 'binary(census_executes_against_postgres)' correctly scopes the extended slow-timeout to the integration test binary target. Note that while the preceding docstring mentions census_binds_to_an_executed_database (the test case function), the nextest filter properly matches the compiled binary harness name census_executes_against_postgres.
  • .config/nextest.toml:43 [RIGHT] -- diff unavailable or unparseable: slow-timeout = { period = "120s", terminate-after = 8 } raises the termination ceiling to 960s (16 minutes) with 120s heartbeat logging. This accommodates the 8 sequential migration/enforce cycles on resource-constrained hosted CI runners without weakening global timeout protections for the remaining 153 tests. As a follow-up item, consider splitting the 8 migration cycles across ephemeral databases/schemas to re-enable parallel execution under nextest.

🤖 [Reviewed] by Oyatie Anvil

@jason931225
jason931225 added this pull request to the merge queue Aug 20, 2026
Merged via the queue into main with commit bd58eb5 Aug 21, 2026
32 checks passed
@jason931225
jason931225 deleted the ci/nextest-all-postgres-shards branch August 21, 2026 00:12
jason931225 added a commit that referenced this pull request Aug 21, 2026
Measured on merge_group run 32402124838: CI wall clock was ~19m and this
one job was the 17m critical path. After #853 moved every PostgreSQL shard
to nextest (now 4-8m each), Backend is the only thing left holding the
number up. Its 17m is not a hot spot but an accumulation -- three steps are
757s of ~1,070s of work (dev-auth PG suites 355s, clippy 217s, console-app
unit 185s) and the other 25 steps are all under 82s.

So the lever is parallelism, not speed. The job becomes a three-leg
strategy.matrix:

  cargo          rustfmt, clippy, the eleven cargo gates, mutation suites,
                 PR 473 contract tests, boot smoke            (16 steps)
  buck-app       platform-authz unit, console-app unit, OpenAPI drift,
                 console-app inline PG                         (4 steps)
  buck-dev-auth  the dev-auth feature PostgreSQL suites        (1 step)

Setup, the topology reconcile and collect-failures run on every leg (7
steps). Every one of the 28 steps lands on EXACTLY one leg or on all three
-- verified by parsing the workflow, not by reading it. fail-fast is off so
one red leg never hides the others, the same fail-slow rule the step layer
already follows.

WHY A MATRIX AND NOT SEPARATE JOBS. Splitting into new jobs was designed
and refuted: it touches every pinned contract structure and creates two
false-green surfaces -- a new job not wired into required-ci's `needs` runs
and gates nothing, and a `steps.topology.outcome` condition carried into a
job with no topology step skips forever while the job stays green. A matrix
keeps the job id, its membership in required-ci, and every step's place in
the bypass-mutation matrix exactly where they were. Ratchets do not move:
run-step count and bypass-mutation count are unchanged (130 / 390 after
#853), because no step was added, removed, or renamed.

THE CACHE, and a pre-existing hole this closes. rust-cache has ONE writer by
contract. It had two: migration-expand-contract carried `save-if: main`
under a comment reading "The ONLY writer" -- copied from `backend` when that
job was split out in #817 and false in place ever since -- and was absent
from `cargoRustCacheJobs`, so the one-writer check never saw it. It is now
restore-only and listed. With a matrix, "one writer" also stops being
enough: three legs saving the same key race on every main push, and the
textual `save-if: false` test cannot tell one leg saving from three. The
writer is now exactly the cargo leg, and a new assertion requires the
writer's save-if to name exactly one leg.

TWO NEW ASSERTIONS, both mutation-proven, both from the refutation:

  a stale leg literal (rename a leg in the matrix, leave a step's `if`)
    -> "names matrix leg 'buck-app', which is not in strategy.matrix.leg --
        that step would run on ZERO legs"
  the writer's save-if no longer leg-scoped
    -> "backend's rust-cache save-if must name exactly ONE matrix leg"
  restored -> preflight exit 0

Without the first, a coordinated matrix rename plus hash recompute could
leave a proof step running on no leg at all while every leg, required-ci,
and check-executed-tests stayed green.

Preflight: exit 0. Contract suite: 61/61. Gate sweep 13/13.
check-workflow-hardening and check-executed-tests exit 0. clippy and the
first gate remain adjacent on the cargo leg, so the gate-order lock holds.

WHAT IS PREDICTED, NOT MEASURED. Per-leg setup is ~55s. The design puts the
legs at cargo ~6.7m, buck-dev-auth ~7.0m, buck-app ~8-10m -- the last
because app-unit's 185s was measured WARM after dev-auth had built the
platform crates in the same daemon, and buck-out does not cross runners. If
that holds, Backend drops from 17m to ~8-10m and the shards (4-8m) and
Backend become comparable, putting wall clock near 10m. That is a
prediction until the first merge_group run measures it. 5m is not reachable
by this change alone: the platform shard carries one 263s test, and the
buck-app leg pays a cold platform build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jason931225

Copy link
Copy Markdown
Collaborator Author

Measured outcome. This PR predicted the shards would reach ~6–7m and — explicitly — that wall clock would not move until Backend was split. Both held.

Shards across merge_group runs since: app 7–8m, platform 8–15m (noisy), ontology 5m, domain-a 4–6m, domain-b 5–6m — from 13–15m before.

Wall clock stayed ~19m until #855 split Backend, exactly as stated. It is now 14m after #855 and #857.

One correction to the reasoning here, for anyone reading this as precedent: the 2.35× runner ratio is real for these PostgreSQL suites, but it does not generalise to unit-test jobs. I measured a 27× cargo-vs-nextest ratio on the domain-unit lib sweep locally and nearly shipped a PR on it — that turned out to be a macOS process-spawn artifact applied to ~1s of real execution on the runner, where that job's 714s was 685s of compilation. See #857: the fix there was a rust-cache key, not a runner.

jason931225 added a commit that referenced this pull request Aug 21, 2026
…853)

#840 put **one** shard on nextest to measure it. Measured on merge_group
run 32402124838, the pilot against its nearest neighbour:

| shard | targets | runner | wall |
|---|---|---|---|
| domain adapters **B** | 45 | **nextest** | **6m** |
| domain adapters A | 40 | cargo | 15m |

More tests, less than half the wall clock — the 2.35× benchmark
reproduced on real CI against a bigger shard. The pilot has done its
job, so the remaining four shards move to the same hash-pinned installer
and runner.

## What this does not do — and the measurement matters more than the
change

The critical path of a merge_group run is **not** the shards:

```
Backend — fmt / clippy / test / gates   17m   <- critical path
Test PostgreSQL — platform              15m
Test PostgreSQL — domain adapters A     15m
Test PostgreSQL — app                   15m
```

Taking the shards to ~6–7m leaves wall clock pinned near **17m by
Backend**, whose own 17m is an accumulation rather than a hot spot: 5m
dev-auth PG suites, 3m clippy, 3m console-app unit, ~4m setup, and 24
further steps at or under a minute. Splitting it is the next lever and a
much larger ci.yml change.

A second measurement, taken locally while checking isolation: the
**platform shard runs 154 tests in 263s, and 263s of that is one test**
— `console-gate-writer-ownership::census_executes_against_postgres`. No
runner change takes that shard below ~4.5m. Shards are not uniformly
runner-bound, and the remaining gains are not evenly distributed.

## Isolation — the actual risk, and why it was piloted

nextest runs test binaries in **parallel** where cargo ran them
serially, so a suite sharing state would newly fail. Verified locally
before pushing: the platform shard passes **154/154** under nextest,
with the cluster-global serial group in `.config/nextest.toml` doing its
job.

Ratchets moved **up**: run-step coverage 126 → 130, bypass matrix 378 →
390, because each new install step goes through the same three mutations
as every other. 61 preflight contract tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
jason931225 added a commit that referenced this pull request Aug 21, 2026
Measured on merge_group run 32402124838: CI wall clock ~19m, and this
one job was the **17m critical path**. After #853 moved every PostgreSQL
shard to nextest (now 4–8m each), Backend is the only thing holding the
number up.

Its 17m isn't a hot spot — it's an accumulation. Three steps are **757s
of ~1,070s** (dev-auth PG suites 355s, clippy 217s, console-app unit
185s); the other 25 steps are all under 82s. So the lever is
parallelism, not speed.

## Three legs

| leg | steps |
|---|---|
| `cargo` | rustfmt, clippy, the 11 cargo gates, mutation suites, PR 473
tests, boot smoke (16) |
| `buck-app` | platform-authz unit, console-app unit, OpenAPI drift,
console-app inline PG (4) |
| `buck-dev-auth` | the dev-auth feature PostgreSQL suites (1) |

Setup, topology reconcile and collect-failures run on every leg (7).
**Every one of the 28 steps lands on exactly one leg or on all three** —
verified by parsing the workflow, not by reading it. `fail-fast: false`,
so one red leg never hides the others.

## Why a matrix and not separate jobs

Separate jobs were designed and **refuted**: they touch every pinned
contract structure and create two false-green surfaces — a new job not
wired into `required-ci`'s `needs` runs and gates nothing; a
`steps.topology.outcome` condition carried into a job with no topology
step skips forever while the job stays green. A matrix keeps the job id,
its `required-ci` membership, and every step's place in the
bypass-mutation matrix exactly where they were. **Ratchets do not move**
(130 / 390 after #853): no step was added, removed, or renamed.

## The cache — and a pre-existing hole this closes

rust-cache has *one writer* by contract. **It had two.**
`migration-expand-contract` carried `save-if: main` under a comment
reading *"The ONLY writer"* — copied from `backend` when that job was
split out in #817, and false in place ever since — and was absent from
`cargoRustCacheJobs`, so the one-writer check never saw it. Now
restore-only and listed.

With a matrix, "one writer" also stops being enough: three legs saving
the same key race on every main push, and the textual `save-if: false`
test can't tell one leg from three. The writer is now exactly the
`cargo` leg, enforced by a new assertion.

## Two new assertions, both mutation-proven, both from the refutation

| mutation | result |
|---|---|
| rename a leg in the matrix, leave a step's `if:` stale | *"names
matrix leg 'buck-app', which is not in strategy.matrix.leg — that step
would run on ZERO legs"* |
| writer's `save-if` no longer leg-scoped | *"save-if must name exactly
ONE matrix leg"* |
| restored | preflight exit 0 |

Without the first, a coordinated matrix rename plus hash recompute could
leave a proof step running on **no leg at all** while every leg,
`required-ci`, and `check-executed-tests` stayed green.

Preflight exit 0 · contract suite **61/61** · gate sweep 13/13 ·
workflow-hardening and executed-tests exit 0 · clippy→first-gate
adjacency holds on the cargo leg.

## Predicted, not measured

Per-leg setup ~55s. Design estimate: cargo ~6.7m, buck-dev-auth ~7.0m,
buck-app ~8–10m — the last because app-unit's 185s was measured **warm**
after dev-auth had built the platform crates in the same daemon, and
buck-out doesn't cross runners. If that holds, Backend drops 17m →
~8–10m and wall clock lands near **10m**. That is a prediction until
this PR's own CI run measures it. **5m is not reachable by this change
alone**: the platform shard carries one 263s test, and the buck-app leg
pays a cold platform build.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant