# Anti-canary Coverage Gate (goal-item #7) Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: cursor-orchestrator (per bs-cursor) executes this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **IRON LAW: all implementation code is written by cursor-agent, never by the orchestrator.** This plan IS the handoff artifact.

**Goal:** Make the false-raise (anti-canary / GREEN-on-safe) precision axis a machine check — prompt-hash-bound, k≥3-enforced — by reusing `recall_gate.py` as-is over a negative-polarity records file, and surfacing the coverage in `ledger.py`.

**Architecture:** Three DRY deliverables, zero new gate/primitive. (1) `domains/security/recall/precision_records.json` = negative-polarity rate records (schema `recall-records/v1`, `metric:"anti-canary-green-rate"`). (2) one new line in `check.sh` runs `recall_gate.py --records …/precision_records.json` — a SECOND invocation of the same binary, mirroring the existing recall line (`check.sh:25`), ZERO functional change to `recall_gate.py` = the STALE-on-drift TEETH. (3) `ledger.py` imports `recall_gate`, calls its pure `run()` over the precision file, consumes `rate_validated`, and upgrades `discriminator_tested` from the `ships_safe` boolean to a tri-state MEASUREMENT grade (`measured`/`present`/`none`) — GRADED, never a gap.

**Tech Stack:** Python 3 (stdlib only), pytest. No new dependencies.

**SoT:** `docs/specs/2026-06-21-discriminator-coverage-gate-design.md` (advisor-blessed, contract-locked). Read it before any structural change.

**Done-bar (user-locked):** real completion = mechanism built + conformance-green on AVAILABLE cells + documented rate-pending gap. **NEVER a k≥3 anti-canary RATE claim over the corpus this session** — the seed is n=1 (S2-team-owner 3/3); the rate is pending real anti-canary rolls.

**Worktree:** `.worktrees/goal-anticanary-gate` (branch `goal-anticanary-gate`). Never bare master.

**Vocabulary:** testing-native ONLY (detector/domain/corpus/cell/band/oracle/roll/recall; `adapter` licensed). NEVER module/package/layer/tier/seam/plugin.

---

## Wave Plan

| Wave | Tasks | Files touched | Safe to parallelize? |
|------|-------|---------------|----------------------|
| 1 | Task 1 | `domains/security/recall/precision_records.json` | single task |
| 2 | Task 2, Task 3 | T2: `ledger.py`, `tests/test_ledger_precision.py` · T3: `check.sh` | ✅ zero file overlap (both blocked by T1) |
| 3 | Task 4 | `docs/validation/2026-06-21-anticanary-coverage-gate.md` (verification record only) | single task |

Wave 2 tasks both READ the Task-1 file at runtime but neither edits it; they touch disjoint files → parallel-safe.

---

## File Structure

- **Create** `domains/security/recall/precision_records.json` — the negative-polarity records bag (data only; sibling of `records.json`). One responsibility: hold faithfully-transcribed anti-canary rates.
- **Modify** `ledger.py` — add module-level `precision_grade()` (mirror of `resolution_grade`), import `recall_gate` via the existing `_load` pattern, consume `recall_gate.run()` in `main()`, thread `precision_validated` through `build()`, upgrade the `discriminator_tested` grade + `_md` render, add the mutant-axis note.
- **Modify** `check.sh` — one new `run` line (the second `recall_gate` invocation, pointed at the precision file).
- **Create** `tests/test_ledger_precision.py` — unit conformance for `precision_grade` (measured/present/none + below-floor-not-masked + graded-not-a-gap + render), mirroring `tests/test_ledger_lifecycle.py`.
- **Create** `docs/validation/2026-06-21-anticanary-coverage-gate.md` — the verification record (Task 4).

`recall_gate.py` is NOT edited (reused as-is). Its own test suite is untouched.

---

### Task 1: precision_records.json (the negative-polarity seed)

**Wave:** 1
**Blocks:** Task 2, Task 3
**Blocked by:** —

**Files:**
- Create: `domains/security/recall/precision_records.json`

**Seed provenance (do NOT fabricate):** The ONLY explicit numeric k≥3 anti-canary count in the current-prompt validation evidence is **S2-team-owner safe = 3/3** (`docs/validation/2026-06-19-citation-prompt-recall.md` §Discriminator, lines 87-89: "S2-team-owner safe … 3/3 … PASS"). The other 16 discriminator cells are recorded as aggregate "PASS" with NO per-cell numeric k → NOT transcribable as k=3 (recall_gate HARD-fails k<3, and inventing a count is forbidden). The zync precision-hold stubs (`cardcom.ts`/`stripe.ts`, n=3) are NOT corpus cells (no `canonical.json`) → would `UNKNOWN_CELL` hard-fail → unseedable. The "k=3 sweep emit JSONs" (citation doc line 114) are transient and not on disk. **Therefore the faithful seed is n=1.** This is honest and expected, not a failure (every unseeded cell is surfaced `present` by the ledger = rate-pending, the no-false-coverage truth).

**cell_id constraint:** MUST be a CORPUS cell. `recall_gate.load_corpus` enumerates `domains/security/corpus/*/canonical.json` ONLY. `S2-team-owner-invariant` is a corpus cell (`domains/security/corpus/S2-team-owner-invariant/canonical.json` exists and its recall record validates). A detector cell would `UNKNOWN_CELL` → hard red.

- [ ] **Step 1: Confirm the prompt hash is current (born not-STALE)**

Run:
```bash
cd .worktrees/goal-anticanary-gate
python3 -c "import hashlib,json,os; d='domains/security/detectors/baseline'; pf=json.load(open(os.path.join(d,'detector.json')))['prompt']; print(hashlib.sha256(open(os.path.join(d,pf),'rb').read()).hexdigest())"
```
Expected: `2154ff82435c60781c46a6c91fc29f9b9a8acc62e87a79306a4ad37cc0a84886`
If it differs, STOP — the prompt drifted since 2026-06-19; the S2 3/3 anti-canary was measured against a prompt that no longer exists and seeding it would be a STALE claim. Re-measurement is out of done-bar (no fresh rolls this session). Report and halt.

- [ ] **Step 2: Confirm the cell_id resolves in the corpus**

Run:
```bash
test -f domains/security/corpus/S2-team-owner-invariant/canonical.json && echo OK
```
Expected: `OK`

- [ ] **Step 3: Write the file**

Create `domains/security/recall/precision_records.json` with EXACTLY this content (the `metric` is the polarity discriminant; the `_comment` documents the corpus-cell constraint for future editors):

```json
{
  "schema": "recall-records/v1",
  "_comment": "NEGATIVE-POLARITY (anti-canary) twin of records.json. Each record's `catches` = rolls that stayed GREEN on the cell's SAFE artifact (did NOT re-raise the canonical) out of `k` safe rolls; `metric` is 'anti-canary-green-rate' (the polarity discriminant). recall_gate.py validates these IDENTICALLY to recall records (metric-agnostic): k>=3 HARD, prompt-hash STALE HARD, MALFORMED/UNKNOWN_CELL HARD, floor report-only. CONSTRAINT: cell_id MUST be a CORPUS cell (domains/security/corpus/*/canonical.json) — recall_gate.load_corpus enumerates corpus/* only; a detector cell would UNKNOWN_CELL hard-fail. SEED IS n=1 by faithfulness: docs/validation/2026-06-19-citation-prompt-recall.md gives an explicit numeric anti-canary count for S2-team-owner only (3/3); the other 16 discriminator cells are aggregate 'PASS' with no per-cell k and are honestly UNSEEDED (surfaced 'present' = rate-pending). The discriminator-MUTANT axis (rename/cosmetic/polarity/null mutation) is a separate, unbuilt rate-pending BLIND_SPOT — this file does NOT claim mutant coverage.",
  "records": [
    {"cell_id": "S2-team-owner-invariant", "detector": "baseline", "catches": 3, "k": 3, "metric": "anti-canary-green-rate", "measured_against": "2154ff82435c60781c46a6c91fc29f9b9a8acc62e87a79306a4ad37cc0a84886", "measured_when": "2026-06-19", "report_ref": "docs/validation/2026-06-19-citation-prompt-recall.md (Discriminator §: S2-team-owner safe 3/3 — canonical owner-demotion guard NOT re-raised on safe.ts)"}
  ]
}
```

- [ ] **Step 4: Verify recall_gate validates the file GREEN (the teeth pass on the seed)**

Run:
```bash
python3 recall_gate.py --records domains/security/recall/precision_records.json; echo "exit=$?"
```
Expected: `exit=0`, output shows `[  ok] OK          S2-team-owner-invariant    rate=1.000 k=3 [anti-canary-green-rate]` and `rate-validated cells   : 1 (classes: S2)`. NO `HARD FAILURE`.

- [ ] **Step 5: Verify the JSON parses + has the derived set**

Run:
```bash
python3 recall_gate.py --records domains/security/recall/precision_records.json --json
```
Expected: JSON with `"rate_validated"` containing one entry `{"cell_id": "S2-team-owner-invariant", "rate": 1.0, "k": 3, "metric": "anti-canary-green-rate", "status": "OK", "waived": false}` and `"rate_validated_classes": ["S2"]`.

- [ ] **Step 6: Commit**

```bash
git add domains/security/recall/precision_records.json
git commit -m "feat(#7): anti-canary precision records (n=1 seed, S2-team-owner 3/3, born hash-current)"
```

---

### Task 2: ledger.py — precision_grade (consume recall_gate, upgrade the grade)

**Wave:** 2
**Blocks:** Task 4
**Blocked by:** Task 1

**Files:**
- Modify: `ledger.py` (add `precision_grade`; thread `precision_validated` through `build`; upgrade grade + `_md`; wire `main`)
- Create: `tests/test_ledger_precision.py`

**Reuse facts (verified):** `recall_gate.run(records_path, corpus_root, detectors_root, floor, strict_floor)` → `(exit_code, result)` where `result["rate_validated"]` is a list of `{"cell_id","rate","k","metric","status","waived"}` for every k≥3, hash-current, well-formed record (EXCLUDES HARD failures; INCLUDES BELOW_FLOOR — `rate_validated` = "not in HARD"). On a MISSING file `run` returns a result dict WITHOUT a `rate_validated` key → consume with `.get("rate_validated", [])`. `recall_gate` exposes `DEF_CORPUS`, `DEF_DETECTORS`, `DEF_FLOOR` at module level. `ledger.py` already loads sibling files via `_load(name, path)` (`ledger.py:39-45`).

- [ ] **Step 1: Write the failing test**

Create `tests/test_ledger_precision.py`:

```python
# tests/test_ledger_precision.py — anti-canary (precision) coverage grade (goal-item #7).
# Negative-polarity twin of test_ledger_lifecycle.py: discriminator_tested upgraded from the ships_safe
# boolean to a tri-state MEASUREMENT grade consuming recall_gate's rate_validated set. GRADED, never a gap.
import importlib.util, os
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def _load(name, path):
    s = importlib.util.spec_from_file_location(name, path); m = importlib.util.module_from_spec(s); s.loader.exec_module(m); return m
cov = _load("sg_ledger", os.path.join(ROOT, "ledger.py"))

def _det(tmp, did, **kw):
    d = {"id": did, "_dir": str(tmp / did)}; d.update(kw); (tmp / did).mkdir(exist_ok=True); return d

def _det_with_safe(tmp, did, covers):
    d = _det(tmp, did, covers=covers)
    cdir = tmp / did / "cells"; cdir.mkdir(parents=True, exist_ok=True)
    (cdir / "safe.ts").write_text("// safe conformance cell\n")
    return d

def _cell(cls, cid):
    return {"class": cls, "canonical_symbol": cls + "sym", "fix_sha": "h" + cid, "id": cid,
            "file": cid + ".ts", "_dir": "/nowhere/" + cid}

def test_precision_measured_present_none(tmp_path):
    classes = ["S1", "S2", "S3"]
    cells = [_cell("S1", "c1"), _cell("S2", "c2"), _cell("S3", "c3")]
    # baseline covers+ships-safe S1,S2; d_s3 covers S3 but ships NO safe cell (avoids an incidental uncovered gap)
    dets = [_det_with_safe(tmp_path, "baseline", ["S1", "S2"]), _det(tmp_path, "d_s3", covers=["S3"])]
    # only c1 (class S1) has a measured anti-canary record
    precision_validated = [{"cell_id": "c1", "rate": 1.0, "k": 3, "metric": "anti-canary-green-rate",
                            "status": "OK", "waived": False}]
    reg = cov.build(cells, dets, [], classes, (), precision_validated)
    by = {g["class"]: g for g in reg["classes"]}
    assert by["S1"]["discriminator_tested"] == "measured" and by["S1"]["discriminator_rate"] == "3/3"
    assert by["S2"]["discriminator_tested"] == "present" and by["S2"]["discriminator_rate"] is None
    assert by["S3"]["discriminator_tested"] == "none" and by["S3"]["discriminator_rate"] is None

def test_precision_below_floor_rate_not_masked(tmp_path):
    classes = ["S1"]
    cells = [_cell("S1", "c1")]
    dets = [_det_with_safe(tmp_path, "baseline", ["S1"])]
    # a sub-floor anti-canary rate (1/3) must still render the rate, NOT a bare green 'measured'
    precision_validated = [{"cell_id": "c1", "rate": 1 / 3, "k": 3, "metric": "anti-canary-green-rate",
                            "status": "BELOW_FLOOR", "waived": False}]
    reg = cov.build(cells, dets, [], classes, (), precision_validated)
    g = reg["classes"][0]
    assert g["discriminator_tested"] == "measured" and g["discriminator_rate"] == "1/3"

def test_precision_graded_not_a_gap(tmp_path):
    classes = ["S1"]
    cells = [_cell("S1", "c1")]
    dets = [_det_with_safe(tmp_path, "baseline", ["S1"])]
    reg = cov.build(cells, dets, [], classes, (), [])
    assert not any(("precision" in g["kind"]) or ("discriminator" in g["kind"]) for g in reg["gaps"])

def test_md_renders_rate_and_mutant_note(tmp_path):
    classes = ["S1"]
    cells = [_cell("S1", "c1")]
    dets = [_det_with_safe(tmp_path, "baseline", ["S1"])]
    precision_validated = [{"cell_id": "c1", "rate": 1.0, "k": 3, "metric": "anti-canary-green-rate",
                            "status": "OK", "waived": False}]
    md = cov._md(cov.build(cells, dets, [], classes, (), precision_validated))
    assert "measured 3/3" in md
    assert "discriminator-mutant" in md
```

- [ ] **Step 2: Run test to verify it fails**

Run: `python3 -m pytest tests/test_ledger_precision.py -q`
Expected: FAIL — `build()` does not accept a 6th `precision_validated` arg yet / `discriminator_tested` is a bool, not `"measured"` / no `discriminator_rate` key / no `discriminator-mutant` in `_md`.

- [ ] **Step 3: Add the module-level `precision_grade` function**

In `ledger.py`, immediately AFTER `resolution_grade` (ends `ledger.py:93`) and BEFORE `_solution_conformance_gap`, insert:

```python
def precision_grade(cls, cells_by_cls, prec_by_cell, ships_safe_fn):
    """Anti-canary (precision / GREEN-on-safe) measurement grade for a class — the negative-polarity twin of the
    Re-discovery rate (goal-item #7). Tri-state:
      'measured' — a k>=3, hash-current anti-canary record exists for >=1 cell of the class (consumed from
                   recall_gate.run() over precision_records.json).
      'present'  — a safe/anti-canary cell ships (ships_safe) but its GREEN-on-safe rate is UNMEASURED (rate-pending).
      'none'     — no safe cell.
    Returns (grade, rate_str|None). rate_str surfaces the WORST measured anti-canary rate (min over the class's
    measured cells) so a BELOW_FLOOR cell is NOT masked behind a green 'measured' word (recall_gate's
    rate_validated INCLUDES below-floor records by design). GRADED, never a gap — the HARD STALE/k<3 teeth live in
    check.sh's recall_gate-on-precision line, NOT here (mirror of resolution_grade)."""
    measured = [prec_by_cell[c["id"]] for c in cells_by_cls.get(cls, []) if c.get("id") in prec_by_cell]
    if measured:
        worst = min(measured, key=lambda d: d["rate"])
        return "measured", f"{round(worst['rate'] * worst['k'])}/{worst['k']}"
    if ships_safe_fn(cls):
        return "present", None
    return "none", None
```

- [ ] **Step 4: Thread `precision_validated` through `build` and upgrade the grade**

In `ledger.py`, change the `build` signature (`ledger.py:130`) from:
```python
def build(cells, detectors, confirmed, classes, solutions=()):
```
to:
```python
def build(cells, detectors, confirmed, classes, solutions=(), precision_validated=()):
```

Immediately AFTER the `ships_safe` nested function (after `ledger.py:143`, the `return False` line), add:
```python
    prec_by_cell = {d["cell_id"]: d for d in precision_validated}  # cell_id -> {rate,k,...} from recall_gate
```

In the per-class grade loop (`ledger.py:172-189`), add the `precision_grade` call on its own line just BEFORE `grades.append({` (alongside the existing `dets`/`n_def`/`deterministic` locals):
```python
        disc_grade, disc_rate = precision_grade(cls, cells_by_cls, prec_by_cell, ships_safe)
```
Then replace the single line `"discriminator_tested": ships_safe(cls),` (`ledger.py:188`) with the two clean keys:
```python
            "discriminator_tested": disc_grade,   # tri-state grade (was the ships_safe bool)
            "discriminator_rate": disc_rate,       # "3/3" | None — surfaced so a below-floor cell is not masked
```

- [ ] **Step 5: Add the discriminator-mutant note to the summary**

In `build`'s `summary = {...}` dict (`ledger.py:210-220`), add this key (anywhere inside the dict literal, e.g. after `"deterministic": [...]`):
```python
        "discriminator_mutant": "unbuilt — 0 artifacts (rate-pending BLIND_SPOT); this gate does NOT claim "
                                "mutant coverage (rename/cosmetic/polarity/null anti-overfit mutation)",
```

- [ ] **Step 6: Upgrade the `_md` discrim render + emit the mutant note**

In `_md` (`ledger.py:224`), replace the class-row append (`ledger.py:229-230`):
```python
        out.append(f"| {g['class']} | {g['n_cells']} | {g['sample']} | {g['coverage']} | "
                   f"{'y' if g['discriminator_tested'] else '-'} | {', '.join(g['detectors']) or '—'} |")
```
with:
```python
        disc = g["discriminator_tested"] + (f" {g['discriminator_rate']}" if g.get("discriminator_rate") else "")
        out.append(f"| {g['class']} | {g['n_cells']} | {g['sample']} | {g['coverage']} | "
                   f"{disc} | {', '.join(g['detectors']) or '—'} |")
```

Then, immediately AFTER the class-row `for` loop and BEFORE the `if reg["gaps"]:` block (`ledger.py:231`), add:
```python
    out += ["", f"_discriminator-mutant axis: {s['discriminator_mutant']}_"]
```

- [ ] **Step 7: Wire `main()` to compute `precision_validated` from recall_gate**

In `ledger.py`, after the existing `_load` calls for `bench`/`manifest` (`ledger.py:44-45`), add:
```python
recall = _load("sg_recall_gate", os.path.join(ROOT, "recall_gate.py"))  # the rate validator (#5), reused as-is
PRECISION_RECORDS = os.path.join(ROOT, "domains", "security", "recall", "precision_records.json")
```

In `main()`, after `solutions, sol_skipped = manifest.load(ROOT, kind="solution")` (`ledger.py:252`), add:
```python
    _, prec_res = recall.run(PRECISION_RECORDS, recall.DEF_CORPUS, recall.DEF_DETECTORS, recall.DEF_FLOOR, False)
    precision_validated = prec_res.get("rate_validated", [])  # .get guards the missing-file shape (no key there)
```

Change the `build(...)` call (`ledger.py:253`) from:
```python
    reg = build(cells, detectors, load_confirmed(), taxonomy_classes(), solutions)
```
to:
```python
    reg = build(cells, detectors, load_confirmed(), taxonomy_classes(), solutions, precision_validated)
```

- [ ] **Step 8: Run the new test to verify it passes**

Run: `python3 -m pytest tests/test_ledger_precision.py -q`
Expected: 4 passed.

- [ ] **Step 9: Run the FULL existing ledger suite — no regression**

Run: `python3 -m pytest tests/test_ledger.py tests/test_ledger_lifecycle.py -q`
Expected: all pass (the bool→string change of `discriminator_tested` is asserted nowhere; lifecycle test passes `solutions` positionally, `precision_validated` defaults to `()`).

- [ ] **Step 10: Run ledger --check — stays green (GRADED, not a gap)**

Run: `python3 ledger.py --check >/dev/null; echo "exit=$?"`
Expected: `exit=0` (precision_grade NEVER appends to `gaps[]`).

- [ ] **Step 11: Eyeball the real-repo render (S2 shows the measurement)**

Run: `python3 ledger.py --md | grep -E "^\| S2 |discriminator-mutant"`
Expected: the S2 row's `discrim` column reads `measured 3/3`; the mutant-axis note line is present.

- [ ] **Step 12: Commit**

```bash
git add ledger.py tests/test_ledger_precision.py
git commit -m "feat(#7): ledger precision_grade — consume recall_gate over precision file; tri-state measured/present/none, rate surfaced, GRADED"
```

---

### Task 3: check.sh — the STALE-on-drift teeth (second recall_gate invocation)

**Wave:** 2
**Blocks:** Task 4
**Blocked by:** Task 1

**Files:**
- Modify: `check.sh:25` region (add one `run` line + a header-comment line)

- [ ] **Step 1: Add the precision-rate gate line**

In `check.sh`, immediately AFTER the existing recall-gate line (`check.sh:25`):
```bash
run "recall-gate"     python3 recall_gate.py
```
add:
```bash
run "precision-gate"  python3 recall_gate.py --records domains/security/recall/precision_records.json
```

And in the header gate-list comment block (`check.sh:6-12`), after the line documenting gate `5. recall_gate.py …`, add a line:
```bash
#   6. recall_gate.py (precision) — anti-canary GREEN-on-safe RATE gate (#7): same binary, SECOND invocation over
#                       domains/security/recall/precision_records.json. STALE on prompt drift = the precision teeth.
```

- [ ] **Step 2: Run check.sh — all 6 lines green**

Run: `./check.sh; echo "exit=$?"`
Expected: `exit=0`. Output shows six `PASS:` lines: `pytest`, `ledger --check`, `bench --routing`, `bench --solutions`, `recall-gate`, `precision-gate`. Final line `check.sh: all deterministic dev gates green.`

- [ ] **Step 3: Prove the teeth bite (STALE on drift) — then REVERT**

Verify the gate actually reds when the precision record goes stale (mutate `measured_against` to 64 zeros, confirm STALE exit 1, then `git checkout --` to REVERT and confirm exit 0 — do NOT leave the mutation):
```bash
python3 -c "import json; f='domains/security/recall/precision_records.json'; d=json.load(open(f)); d['records'][0]['measured_against']='0'*64; json.dump(d, open(f,'w'), indent=2)"
python3 recall_gate.py --records domains/security/recall/precision_records.json; echo "drift exit=$?"
git checkout -- domains/security/recall/precision_records.json
python3 recall_gate.py --records domains/security/recall/precision_records.json; echo "restored exit=$?"
```
Expected: `drift exit=1` with a `STALE` HARD FAILURE line for `S2-team-owner-invariant` ("measured_against != current prompt hash — re-roll required"); `restored exit=0`.

- [ ] **Step 4: Commit**

```bash
git add check.sh
git commit -m "feat(#7): check.sh precision-gate line — second recall_gate over precision_records.json (STALE-on-drift teeth)"
```

---

### Task 4: End-to-end verification record + done-bar honesty

**Wave:** 3
**Blocks:** —
**Blocked by:** Task 2, Task 3

**Files:**
- Create: `docs/validation/2026-06-21-anticanary-coverage-gate.md`

- [ ] **Step 1: Re-run the full dev gate**

Run: `./check.sh; echo "exit=$?"`
Expected: `exit=0`, all six gates PASS.

- [ ] **Step 2: Capture the ledger projection**

Run: `python3 ledger.py --md | sed -n '1,40p'`
Capture: the class table (S2 → `measured 3/3`; other classes → `present` or `none`) + the discriminator-mutant note line.

- [ ] **Step 3: Write the verification record**

Create `docs/validation/2026-06-21-anticanary-coverage-gate.md` stating, concretely:
- Mechanism built: the 3 deliverables (precision_records.json + check.sh precision-gate line + ledger precision_grade).
- Conformance-green on AVAILABLE cells: `recall_gate --records precision_records.json` exit 0; the S2-team-owner anti-canary record validates k=3, hash-current (rate 1.000); `check.sh` exit 0 across 6 gates; `pytest` for `precision_grade` green.
- Teeth proven: STALE-on-drift demonstrated (Task 3 Step 3) — a hash mutation reds the gate, revert restores green.
- **Documented rate-pending gap (done-bar honesty):** seed is **n=1** (S2-team-owner 3/3) by faithfulness — the citation doc gives no other explicit per-cell k≥3 anti-canary count; 16 cells surfaced `present` (safe ships, rate unmeasured); the discriminator-MUTANT axis is unbuilt (0 artifacts, rate-pending BLIND_SPOT). **NO k≥3 anti-canary RATE is claimed over the corpus.**
- SoT pointer: `docs/specs/2026-06-21-discriminator-coverage-gate-design.md`.

- [ ] **Step 4: Commit**

```bash
git add docs/validation/2026-06-21-anticanary-coverage-gate.md
git commit -m "docs(#7): anti-canary coverage gate verification — mechanism green, n=1 seed, rate-pending gap documented"
```

---

## Self-Review

**1. Spec coverage** (each spec deliverable → task):
- precision_records.json (schema/metric/cell-id-constraint/_comment/seed) → Task 1 ✓
- check.sh reuse recall_gate AS-IS, zero functional change to #5 → Task 3 ✓ (no edit to recall_gate.py anywhere)
- ledger consume `run()` → tri-state precision_grade → Task 2 ✓
- rate surfaced so below-floor not masked → Task 2 Step 3 (`min` rate) + test_precision_below_floor_rate_not_masked ✓
- mutant-axis note → Task 2 Steps 5-6 + test_md_renders_rate_and_mutant_note ✓
- GRADED never a gap (ledger --check green) → Task 2 Step 10 + test_precision_graded_not_a_gap ✓
- detector-cell UNKNOWN_CELL constraint → Task 1 `_comment` + cell_id is a corpus cell ✓
- seed = faithful k≥3 only (S2 3/3), build-phase first step (check emit JSONs → none on disk → n=1) → Task 1 provenance ✓
- done-bar (mechanism + available-cell green + rate-pending gap; no rate claim) → Task 4 ✓
- green-bar check.sh exit 0 across 6 lines → Task 3 Step 2 + Task 4 Step 1 ✓

**2. Placeholder scan:** No TBD/TODO. Task 3 Step 3 flags its OWN deliberate heredoc typo (`p=0`) with an explicit instruction to write a correct one-liner — not a silent placeholder. Every code step is exact.

**3. Type consistency:** `discriminator_tested` is a string (`measured`/`present`/`none`) everywhere after Task 2; `discriminator_rate` is `str|None`; `_md` uses `.get("discriminator_rate")`. `build` 6th param `precision_validated=()` is consistent across signature (Step 4), `main` call (Step 7), and all three test call-sites + the two existing test files (positional, default applies). `precision_grade(cls, cells_by_cls, prec_by_cell, ships_safe_fn)` args match the call in Step 4 (`cells_by_cls`, `prec_by_cell`, `ships_safe` all in scope at `ledger.py:188`). `recall_gate.run` return shape (`result["rate_validated"]` items have `rate`,`k`) matches `precision_grade`'s `worst['rate']`/`worst['k']`.

**4. Wave plan check:** Every task has Wave/Blocks/Blocked-by. Wave 2 (T2 ledger.py+test ∥ T3 check.sh) — zero file overlap confirmed. T2/T3 both blocked by T1 (both read precision_records.json at runtime; recall_gate.run on a missing file would exit 1 → T3 must follow T1; T2's real-repo render Step 11 needs the file). T4 (verification) blocked by T2+T3. Topological order holds.

**Edit-hook note:** No task writes a deliberate-violation fixture via the Edit/Write tool. `precision_records.json` is valid data. The test's `safe.ts` is created at pytest runtime under `tmp_path` (not the Edit tool, not committed) → no PostToolUse lint-hook interception.

---

## Execution Handoff

Plan complete and saved to `docs/plans/2026-06-21-anticanary-coverage-gate.md`. Per bs-cursor, cursor-orchestrator executes — cursor-agent writes all implementation code; per-wave two-tier code gate + advisor() process gate between waves and before completion.
