---
name: a-selector-that-can-match-twice-must-assert-cardinality
description: "A read selector that can match more than one thing mints a confident wrong verdict — three independent instances in one hour, all fixed by asserting the match COUNT rather than by a better pattern"
metadata:
  node_type: memory
  type: feedback
  originSessionId: 67eaf193-4427-47cd-bf9b-94b9db7bb25a
  modified: 2026-09-09T06:49:19.960Z
---

Building the v0.68.0 r3 attempt-2 instruments on 2026-09-09 I hit the same defect **three times in one hour**, in three unrelated selectors, and each time the failure looked like a measurement rather than a bug:

1. **Job by substring.** `"Windows"` matched both `test (self-hosted, Windows, hfenduleam)` and `n1-gate (self-hosted, Windows, hfenduleam)`. The extractor returned two lines; `[ "$v" = "success" ]` against a two-line value can NEVER be true, so **a genuinely green run would have printed a red.**
2. **Step by substring, inside the right job.** The Windows test job carries BOTH OS variants of every floor/drift step, wrong-OS skipped (`DISK docs floor (Linux)` beside `(Windows)`; `— linux` beside `— windows`). A substring match can hand back the **Linux** step's conclusion for a **Windows** criterion — the exact collapse that criterion exists to prevent, happening inside the instrument with no Linux job in the reading to make it look wrong.
3. **File by search.** Locating "the registry" by grepping the tree for a registry-ish filename and taking the first hit found `.github/ci/flake-registry.json`; the blob the gater actually named was `traceable-reqs.toml`. That check would have reported "registry blob unchanged" **truthfully, about the wrong file** — a passing assertion about nothing anyone asked for.

**Why:** all three fail toward something that *looks like a reading*. There is no error, no empty, no exception — just a value, and values get quoted to gaters. Case 1 fails toward a false RED (costs a hunt); cases 2 and 3 fail toward a false GREEN (costs the gate itself). A search that takes the first match is a guess wearing a measurement's clothes, and the gater's word for it is right: it is the stale-target shape again — a check that is TRUE about the WRONG SUBJECT.

**How to apply:** the fix is never a cleverer pattern, it is **asserting the count**. (1) Select by EXACT identity where one exists — full job name, full file path, `.name == "…"` not `contains(…)`. (2) Where the pattern must stay fuzzy, anchor it (`startswith`/`endswith` beats a substring, and it also dodges having to round-trip an EM DASH through a shell). (3) **Assert the cardinality explicitly**: exactly one job carries that name, exactly one step matched, the file exists at the named path — and treat a multi-line answer as VOID, never as a value. A column that must hold one value is only read correctly when >1 is an ERROR; pick-first and compare-the-concatenation both mint confident wrong verdicts. (4) Prove the instrument against a COMPLETED CONTROL before the real target is terminal — all three of these were caught by a control run, none by review. Kin: [[a-stale-target-makes-a-check-pass-harder-not-fail]], [[a-kill-is-only-as-scoped-as-its-filter]] (same ambiguity in a destructive filter), [[a-column-that-reads-one-value-on-every-row-is-a-broken-extractor]] (the uniform-column tell), [[a-name-grep-that-guesses-the-compound-spelling-reads-as-absence]].
