Files
fusion/packages
gsxdsm c8a6af13a0 test(census): pin file DISCOVERY, which every existing test was blind to (#3259)
Follow-through on the recommendation I made reviewing #3256: **a gate
needs a test for its file discovery, not only its matcher.**

## The gap

This suite pinned the matcher and never the scan. Every case either
feeds the classifier a source string or drives the CLI against the real
tree — so **the file list could return empty and all 53 tests would
still pass.**

Not hypothetical. `git ls-files` lists tracked files only, so a new file
with a plain `task.column === "in-review"` scored 0 until staged
(#3254). The identical bug then turned up in the move-target ratchet
**behind its own 12 matcher tests** (#3256) — I wrote those 12
specifically to stop that gate regressing, and they could not see it,
because they import the matcher and never run a scan.

## Four cases, on a synthetic tree

Driven through `FUSION_CENSUS_FILE_ROOT` + `FUSION_CENSUS_FILE_LIST`, so
discovery is testable without creating files inside a checkout the
operator writes to concurrently:

- a guard in a scanned file **reaches the classifier** and is counted
- `--strict` fails **for the right reason** (message names the file; not
an ENOENT fail-closed)
- **every** listed file is counted, not just the first
- files are read from the **scan root**, so a listed path and a read
path cannot diverge

## The second case earns its wording

Its first version asserted only `code === 1` — and **passed while
discovery was broken.** With the injected list ignored, paths come from
the real repo while reads resolve against the fixture root, every read
misses, and the gate fails closed with exit 1. Right code, unrelated
cause.

A test that cannot tell *"found a guard"* from *"could not read
anything"* is not testing the ratchet. Asserting the message is what
separates them.

I found that only by checking which cases the control actually failed —
3 of 4, not 4 of 4. Had I stopped at "the control fails, ship it", I
would have added a test that passes for the wrong reason to a suite
whose whole purpose is catching tests that pass for the wrong reason.

## Measured

| check | result |
|---|---|
| suite | **57 passed** (53 + 4) |
| anti-vacuity: `injectedList` forced undefined | **all 4 fail** (3/4
before strengthening case 2) |
| restored | 57/57 |
| `census --strict` / `check-fnxc-future-dates` | 0 / 0 |

Tests only — no gate or product change. The same four assertions port
directly to the other lifecycle gates once each grows the fixture seam;
the move-target ratchet is the obvious next one, and its `.mjs` is
currently claimed by #3256.
2026-07-31 16:03:46 -07:00
..
2026-07-26 18:11:47 -07:00
2026-07-31 14:58:53 -07:00