---
name: gate-population-excludes-consumers
description: "A wave gate that changes a shared predicate but runs only the changing crate's tests reports green about a population that excludes every consumer — the failure surfaces at assembly, not at the gate."
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 5893ae58-5dde-49e3-bcfd-5aab31b20008
  modified: 2026-08-02T14:08:17.278Z
---

When a wave changes a **shared predicate** (a resolver, a status derivation, a liveness probe), the gate must run the tests of every CONSUMER of that predicate, not just the crate that holds it. A filtered gate over the owning crate answers a true question about the wrong population.

BAROMETER W2 (releases#78, 2026-08-02): the wave changed `shell_pid_provably_dead` to a pid+birth-stamp pair test. Its gate ran `cargo nextest -p spt-daemon --lib -E 'test(shellwake) or test(shellhost) or test(reconcile) or test(heal)'` plus `spt-store` lib — 72/72 and 428/428 green, honestly reported. Golden then went red on three tests in the **`spt`** crate: `shell_relink_relaunches_offline_instances_only`, `linkhost::prepare_drive_is_live_or_drop_and_never_spools`, `activity_link_push_e2e`. Those three are *precisely* the class-(a) DERIVE consumers that KNOWN-HAZARDS 2.6 enumerates by name — relink's already-online refusal, drive's drop-if-offline, the activity fan-out's online filter. Three-for-three against a documented consumer list.

The cause was test-only (fixtures overwrote `shell.pid` after a real launch had written a genuine pid+stamp pair, manufacturing exactly the mismatched pair the new probe correctly calls a corpse) — but the *gate* is what let it reach an assembled head.

**Why:** the hazard doc already listed the consumers. The gate filter was written around the code that changed rather than around the behavior that changed, so the population and the blast radius were different sets and nothing compared them. Green was uninformative, not wrong — the [[discriminator-question]] answered by construction, the sibling of [[zero-match-filter-reads-as-absent]].

**How to apply:** when reviewing or building a wave gate for a predicate change, take the consumer list from the requirement or hazard entry that documents it (they name sites — 2.6 names five) and require the gate to run each consumer's tests, naming the crates. If the consumers live in another crate, the gate spans crates or it is not a gate. As a reader of someone else's gate report, ask which population the filter could not reach before accepting a count as coverage.

Falsifier that settled it in one step: run the failing tests against the wave's own tip alone (`d57bcd3`), pre-assembly. Red there ⇒ wave-local and every cross-lane interaction hypothesis drops out.

Related: [[discriminator-question]], [[zero-match-filter-reads-as-absent]], [[nextest-zero-match-filter-trap]], [[every-return-arm-is-a-copy]], [[barometer-triaged]].
