---
title: Stop signalling a keeptradecut zeroed-liquidity slot that the recovery pass repairs
type: task
status: draft
description: >-
  The 04:30 keeptradecut importer still exits 1 on an all-zero liquidity payload, minting a medium
  signal for a condition the 12:30/20:30 recovery slots now fully repair.
base_uri: user:task/league/stop-signalling-recovered-keeptradecut-zeroed-liquidity.md
created_at: '2026-08-09T03:14:53.603Z'
entity_id: 0f827487-942a-436d-b3ba-87ed3d96dfc0
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: Low
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-08-09T03:17:23.136Z'
visibility_analyzed_at: '2026-11-06T00:18:06.017Z'
---

## Problem

`scripts/import-keeptradecut.mjs` exits 1 and raises a `pipeline_failure` signal whenever
KeepTradeCut serves an all-zero liquidity payload at the 04:30 ET slot. That exit was the
right design when a zeroed slot meant the day's liquidity was permanently lost. It no
longer does.

`██████████████████████████████████████████████████████████████` (Completed 2026-08-05)
added two liquidity-only recovery slots at 12:30 and 20:30 ET as
`scripts/import-keeptradecut-liquidity.mjs`. That recovery works: every zeroed day since
has been fully backfilled. The daily importer nevertheless still hard-fails, so a
condition that is now automatically repaired continues to mint a medium signal that a
human has to triage.

## Evidence

Measured 2026-08-09 against `league_production` and the league host.

- `service:league-import-keeptradecut-liquidity` created 2026-08-05 21:42:57, 8/8 success,
  zero failures, last success 2026-08-09 00:30:05.
- The daily importer failed on the zeroed payload on 2026-08-06 and 2026-08-08, and
  succeeded on 2026-08-07 — the zeroed slot is intermittent, roughly the 22% rate the
  recovery task measured.
- Both failure days were fully recovered. `keeptradecut_liquidity` holds 922 rows for
  `observed_at` 2026-08-06 and 922 rows for 2026-08-08, with 754 and 762 nonzero
  `trade_count` respectively — indistinguishable from healthy neighbours.
- The three forensic captures in the host's keeptradecut zero-liquidity log directory
  (2026-07-30, 2026-08-06, 2026-08-08) are identical in shape:
  `player_count: 500`, `all_three_zero: 1000`, `fields_absent: 0`,
  `missing_values_object: 0`, `fields_non_numeric: 0`, `present_nonzero: 0`.
  `rawLiquidity`, `stdLiquidity` and `tradeCount` are all present, numeric and exactly
  zero. This rules out an upstream markup change, a field rename, a moved endpoint, and
  a rate-limit or blackhole — a throttled fetch does not return a full 500-player payload.

So the oracle is firing on a real upstream condition that is real, benign, and already
remediated by a downstream job.

## Scope

Decide what the 04:30 importer should do when `has_liquidity_data` is false, given that a
recovery pass now owns the repair. The obvious shape is to log and skip rather than exit 1,
leaving the liquidity write refusal exactly as it is — a stored zero must still never mean
"we did not collect it". The failure should then belong to the recovery pass: if 12:30 and
20:30 both draw zeros, that day really is at risk and is worth a signal.

Two things not to break:

- The liquidity write refusal itself is correct and must stay.
- The two recovery slots are also a live measurement — the recovery task notes that WHICH
  slot recovers is the only bound anyone has on the zeroed-window length. Do not collapse
  them to one while that measurement is still wanted.

## Oracle

`service:league-import-keeptradecut` produces no `pipeline_failure` on a day whose 04:30
payload is zeroed but whose liquidity is subsequently backfilled by a recovery slot, while
still failing on a day where liquidity is genuinely never collected.
