# GAP-1 — six permanent capture-days are already lost, and charter gauge G4 claims they are machine-checked when no instrument can see them

status: open · raised panel run 1 (2026-08-06) · migrated 2026-08-24 (body verbatim below) · class: moat / instrument-calibration · judgement: **YES** · effort 0.75 pd · horizon: detector kill resolves ~2026-09-04

---

**4. GAP-1 — six permanent capture-days are already lost, and charter gauge G4
claims they are machine-checked when no instrument can see them.** ·
judgement: **YES** · effort 0.75 pd · horizon: detector kill resolves in 20 td
(~2026-09-04)

*Mechanism.* Verified interior holes inside the pinned clean-clock window:

| stream | class | missing trading days |
|---|---|---|
| `data/processed/portfolio_snapshots.jsonl` | TIME-GATED | 2026-06-17, 07-16, 07-17 |
| `data/processed/order_log.jsonl` | TIME-GATED | 2026-06-17, 07-16, 07-17 |
| `data/pit_snapshots/` | TIME-GATED | 2026-06-16, 07-15, 07-16 (T-1 lag) |
| `data/equity_history.jsonl` | BACKFILLABLE | **0** — healed by `backfill-equity` |

Causes: the 2026-06-17 Tiingo 429 and the 07-16/17 clock-rotted
`test_fleet_gather_and_renders` fail-close. Both incidents are marked **CLOSED**
in `AUDIT.md` — but both closures were written against the one *backfillable*
stream ("gaps self-heal on today's backfill-equity", "fully green"). The three
irreplaceable streams were never mentioned. `data/options_skew.jsonl` has all
four dates, so these were ordinary trading days, not calendar effects.

*Why nothing caught it.* `thales captures` reports only `last` +
`staleness_td` of the newest file — I ran it: every stream reads **OK**,
including all three carrying holes. `capture_qa()` iterates over files that
exist, so an interior hole is invisible by construction. Meanwhile
`ops/DAILY_AUDIT.md` step 7 instructs "No gap days", and charter G4 asserts
capture-day gaps are "measured by `thales captures` / capture-qa,
machine-checked". **That claim is false today** — a pinned gauge reading pass
while blind, on the asset the charter calls irreplaceable (§1 asset #2: "a
missed day is a permanent notch").

*Precondition, before any code:* enumerate every existing interior hole across
all registered streams' full history and record them in `CAPTURES.md` as
permanent notches. G4's metric is "capture-day gaps (target zero)" and the
current count is literally unknown.

*Kill criterion.* Negative control first: delete one interior day from a temp
copy of each time-gated stream and assert the checker reds **naming the date**,
and greens on the untouched copy. The scan must cover full history, not a
trailing window, or it re-blinds by drift. Then: **if the census surfaces zero
interior gaps beyond the six above, AND a 20-trading-day live shadow run raises
zero true alerts while raising ≥1 lag/calendar false positive, abandon the
standing detector** — record the six notches and stop. Do not tune the detector
to survive.

*Owner judgement required:* G4's wording is in the hash-frozen §1–§5 span. The
honest fix may be to make the gauge true (build the check) rather than amend
the text — but if amendment is wanted, that is a countersigned append, not a
panel action.

---

## Triage note — 2026-08-31 (annotation only; the body above is untouched)

**PARTIALLY OVERTAKEN — most of this row was built; two residuals are live and
one of them is a permanent notch that exists in no ledger at all.** Kept open
rather than dismissed, because the residuals are exactly what the row's own
kill criterion forbade.

**What was built since 2026-08-06** (verified at HEAD `528793d`): an
interior-gap detector — `captures.capture_gaps()` with an `ACKNOWLEDGED_GAPS`
ledger, a `GAPPED` status wired into `capture_status`, and
`acknowledged_gaps_seen()`. `pit_snapshots` was swept and its notches recorded
in `CAPTURES.md`. Charter gauge G4's "machine-checked" claim is much closer to
true than when this row was raised.

**Residual 1 — the detector is a 20-trading-day TRAILING WINDOW, which this
row pre-registered against.** The body reads: *"The scan must cover full
history, not a trailing window, or it re-blinds by drift."* The shipped
`capture_gaps` takes `lookback_td: int = 20`. The code carries its own comment
arguing for the window; that argument may well be right, but it is a decision
taken against a pre-registered constraint and should be recorded as such
(amended, or the constraint honoured) rather than left as a silent divergence.

**Residual 2 — 2026-06-17 is a permanent notch that is in NO ledger.**
Independently verified by triage this run, not taken from the row: `2026-06-17`
(a Wednesday, an ordinary trading day) is absent from BOTH
`data/processed/order_log.jsonl` run-summaries (06-15, 06-16, **—**, 06-18)
and `data/processed/portfolio_snapshots.jsonl` (same three dates). It appears
in neither `ACKNOWLEDGED_GAPS` nor `CAPTURES.md`. It is 50+ trading days old,
so the 20-td window can never surface it. **This is the re-blinding the row
predicted, already materialised, on a date the row itself named.**

**The "~2026-09-04" horizon in the status line is stale and should not be read
as an expiry.** It assumed a build starting 2026-08-06; the detector landed
~08-07 and was wired ~08-20, so the 20-td shadow window matures nearer
**2026-09-17**. Separately, the row's abandon-the-detector kill criterion is
conditional on a shadow run that was never armed (this row was never approved),
so nothing lapses on 09-04 in either reading.

**Recommended re-scope (triage does not edit the body): narrow this row to the
two residuals** — the full-history census for `order_log` and
`portfolio_snapshots` (starting with 2026-06-17), and an explicit ruling on
trailing-window vs full-history — rather than re-running the row whole. Effort
falls well below the 0.75 pd in the status line.
