Skip to content

Commit 0423986

Browse files
JamesKaneclaude
andcommitted
docs(grid): the est_bases hole is closed
§12.8. ENA had been publishing base_count on read_run the whole time; RUN_FIELDS never asked for it. Migration 0076 gives it a typed column rather than a JSONB provenance slot, because a missing key in a blob reads identically to a zero and this number decides what a contributor is paid. Records why old rows needed a backfill job rather than a re-crawl (ingest_libraries is idempotent at sample granularity, which is worth keeping), and the two ledger safety properties: the backfill only fills a NULL, and an empty figure from ENA stays NULL rather than becoming a zero. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SequryftjcFkLnjQRMKCx3
1 parent aba1014 commit 0423986

1 file changed

Lines changed: 46 additions & 14 deletions

File tree

documents/design/distributed-compute-grid.md

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -820,16 +820,12 @@ reads. `build_libraries` already prefers aligned over FASTQ per sample, so the t
820820
deciding it again here means a manifest can never list a file the data kind says the node will not
821821
open, and the download budget cannot be inflated by files nobody fetches.
822822

823-
**The hole: `est_bases` is `NULL` for essentially every unit.** It is `reads × read_length`, and the
824-
crawl sets `read_length` to `None` — ENA's `filereport` does expose `base_count`, but
825-
`du-external`'s `RUN_FIELDS` does not request it and `genomics.sequence_library` has nowhere to put
826-
it. So the **per-Gbp term of the credit formula (§6.3) has nothing to weigh a FASTQ unit by**.
827-
828-
A byte-derived estimate was the tempting fix and is the wrong one: a fabricated number in a ledger
829-
that pays people is worse than an honest null. So curation publishes the null and the job *warns*
830-
with a count, rather than leaving a silent hole. **The fix, before credit goes live:** add
831-
`base_count` to `RUN_FIELDS`, carry it through `crawl_project`, and store it — either as a column on
832-
`sequence_library` or in the `atproto` provenance slot that already holds `run_accession`.
823+
**The hole it found — now CLOSED, see [§12.8](#128-closing-the-est_bases-hole).** `est_bases` was
824+
`reads × read_length` and the crawl never set `read_length`, so it was `NULL` for essentially every
825+
unit and the per-Gbp term of §6.3 had nothing to weigh a FASTQ unit by. A byte-derived estimate was
826+
the tempting fix and the wrong one — a fabricated number in a ledger that pays people is worse than
827+
an honest null — so curation published the null and warned. The real fix was to ask ENA for the
828+
figure it had been publishing all along.
833829

834830
### 12.6 Validation, and two contracts that did not need to exist
835831

@@ -910,13 +906,49 @@ position a contributor *would* hold, but to a node with its first unit still in
910906
as "you are last" — a discouraging answer to a question nobody asked, about a board the contributor
911907
does not yet appear on. `null` means unranked, which is what is true.
912908

909+
### 12.8 Closing the `est_bases` hole
910+
911+
By the time `grid-validate` shipped, §12.4's gap had stopped being theoretical: the validator pays
912+
`BASE_CREDIT + per-Gbp`, so with `est_bases` null a 90 Gbp realignment earned exactly what a CRAM
913+
passthrough earned. The ledger would have gone live quietly wrong.
914+
915+
**ENA had the figure all along.** `filereport` publishes `base_count` on `read_run`; `RUN_FIELDS`
916+
simply never asked for it. It now does, and migration `0076` adds
917+
`genomics.sequence_library.base_count` to hold it.
918+
919+
**A typed column, not the `atproto` JSONB slot** — which was the other option, since that slot
920+
already carries `{source, run_accession}` for crawled runs. But that slot is *provenance*: where a
921+
row came from. `base_count` is a measurement of the library, the same kind of fact as the `reads`
922+
and `read_length` columns beside it, and it is summed in an aggregate that feeds a ledger paying
923+
real people. In a JSON blob a missing key reads identically to a zero; in a typed column a NULL is
924+
visible. That distinction is the whole point here.
925+
926+
**It is the measured total, not the product.** `est_bases` now prefers `base_count` and falls back
927+
to `reads × read_length` only where a row predates the column. The product is a mean-length
928+
approximation and is wrong outright for variable-length reads — which is to say for every long-read
929+
platform the Grid will see.
930+
931+
**Old rows needed a job, not a re-crawl.** `sequence::ingest_libraries` is idempotent at *sample*
932+
granularity and skips a sample that already has files. That property is what keeps re-crawls cheap,
933+
and weakening it for one column would be a bad trade. So `run-once ena-base-count` fills the column
934+
directly, one run at a time — `filereport` filters on whatever accession it is given, so a run
935+
accession returns just that run — in bounded batches with the same politeness gap as the study
936+
crawl. Re-run until it reports nothing examined.
937+
938+
Two properties made explicit rather than left incidental, both about not corrupting a ledger:
939+
940+
- **The backfill only ever fills a NULL.** Re-running it cannot overwrite a measurement and silently
941+
change what a contributor was already paid for.
942+
- **An empty `base_count` from ENA leaves the NULL.** A submitter who never supplied the figure is
943+
not the same as a run that sequenced nothing, and writing a zero would conflate them.
944+
945+
Where no honest figure exists the null survives and `grid-curate` still warns with a count. That was
946+
right before and is still right; this only makes the null rare instead of universal.
947+
913948
### What is NOT yet built
914949

915950
`Provenance` in `du-domain` (§5.1) and the whole Navigator edge (`ena.rs`, `grid.rs`, the driver,
916-
the `contribute` CLI). Plus the `est_bases` gap in §12.4, which **must close before credit goes
917-
live**`grid-validate` already pays `BASE_CREDIT + per-Gbp`, and with `est_bases` null every
918-
FASTQ unit pays the base only, so a 90 Gbp realignment currently earns exactly what a passthrough
919-
does.
951+
the `contribute` CLI).
920952

921953
### 12.5 What the reaper is actually for
922954

0 commit comments

Comments
 (0)