Make "I want to add an example" a documented path, not a reverse-engineering exercise - #203
Merged
Merged
Conversation
This was referenced Aug 14, 2026
lucapinello
added a commit
that referenced
this pull request
Aug 14, 2026
The [0.7.3] section covered #186-#198 and stopped there, while four more PRs landed under the same release. Everything in this cycle goes in 0.7.3, so the notes have to carry it. Two entries under Fixed — the README defects a new user hits first, including the ref allele that raised and took two later recipes down with it (3 of the 9 advertised recipes), and the HuggingFace gate that reads as global but is scoped to AlphaGenome in the code. Two under Added — the documented path for contributing a worked example, and the escape hatches that let an outside contributor develop an oracle without our HuggingFace dataset. Numbers in the entries are the measured ones: 114,688 bp for the Enformer mean, 64 s GPU / 59 s CPU for the quickstart, 13.7 GiB for a single-oracle install, 0.9811 for the effect percentile that had been documented as 0.962, and 138 tests collected by the guard command CONTRIBUTING now names. `chorus/cli/main.py:93` re-verified as the gate after the merges. #199 gets no entry of its own: it was the changelog PR for #196-#198, so its content is these notes. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lucapinello
added a commit
that referenced
this pull request
Aug 14, 2026
* Stop the browser job going red when UCSC does not answer The browser smoke job failed on #203, a CONTRIBUTING-only change, having passed on #202 minutes earlier against the identical corpus. Nothing about the reports had changed: IGV error: Error accessing resource: https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit Status: 0 Failed to load resource: net::ERR_CONNECTION_REFUSED All 19 committed reports resolve their reference sequence from `hgdownload.soe.ucsc.edu`, because igv.js requires a sequence source and hg38 is ~3 GB — bundling it in the repo is not an option, so this is a documented limitation rather than a defect. What was not intended is the consequence: the verdict of this file depended on a third party being up. When UCSC refused, both smoke reports reported `canvases 0/0 painted (NOT converged)` and blew the 30 s budget at the 60 s timeout — four failures, none of them about chorus. A suite that goes red when someone else's server hiccups teaches people to re-run CI until it is green, which is exactly how a real blank-panel regression gets waved through. So the two rendering checks now separate "this report is broken" from "this render could not be judged": if the *only* console errors are unreachable-host signatures **and** an external host was actually contacted, the report is skipped with the host named and the errors quoted. Deliberately narrow, because the risk here is masking a real defect: * any console error outside the signature list disqualifies the skip, so a genuine JS fault alongside an outage still fails — an outage grants no amnesty; * blank canvases with no console error still fail, which is the blank-panel regression this file exists to catch; * errors with no external request attempted are never an outage. Five offline guards pin all of that, using the failing run's error strings verbatim rather than a paraphrase. `route.abort()`'s `ERR_FAILED` is deliberately **not** in the list: that is our own blocking in the offline test, where failure is the assertion. Full browser suite with UCSC reachable: 51 passed, 0 skipped — the guard changes nothing when the host answers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Move the outage guard's own checks where they will actually run The five checks on the skip logic were written next to the tests they protect, and that file carries `pytestmark = pytest.mark.integration` because it drives Chromium over a 19-report corpus. A module-level mark applies to everything in the file, so all five were deselected from the fast suite: `pytest tests/` collected none of them, and they would only have run when someone opted into the slow suite — needing a browser they do not use. Measured before the move: the browser module went 46 -> 51 collected, all 5 integration-only. That function decides whether CI is *allowed* to fail, so it should be checked on every push. So the predicate moves to `browser_harness.unreachable_external_host` (where it belongs — the harness already owns `RenderResult` and `external_hosts`), and its checks move to `tests/test_browser_outage_guard.py`, which has no module mark. This is the same trap as the marker a docstring edit stole earlier in this release: a mark that is correct for a file is not automatically correct for everything added to it. Browser module back to 46 collected, 46 passed. The 5 guards now run in the fast suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e-engineering exercise CONTRIBUTING opened with "this guide will walk you through the process of implementing a new oracle", and Current Priorities listed three kinds of contribution, all of them models. Read literally, someone with a variant they care about and no intention of porting a neural network is told in sentence one that they are in the wrong document — and adding a worked example is the cheapest useful contribution chorus can receive. It was also genuinely undocumented. Four regeneration scripts own different example types, and the matrix mapping example -> script -> valid --oracle -> conda env lived in **CLAUDE.md** (a file for Claude sessions), the CHANGELOG, and a May audit report. None of those is where a contributor looks. That matrix exists because getting it wrong is the single most common way a regeneration silently does nothing: * `regenerate_multioracle.py` accepts chrombpnet / cherimoya / legnet / alphagenome and pointedly **not** enformer, whose report comes from `regenerate_examples.py` instead; * it also has no `--gpu`, while the other two do — passing one is an argparse error that scrolls past in a tailed log; * the wrong conda env does not fail fast. A missing oracle package logs `Failed to load <track>` once per track and carries on, so a run can spend an hour loading nothing. So: a routing table in the first screen (oracle / example / bug fix, with sizes), a "Contributing an example or walkthrough" section carrying the verified matrix, the real entry shape copied from `ENFORMER_EXAMPLES`, the four traps, and the six guard tests to expect — all of which collect (138 tests), unlike the browser recipe that shipped collecting 0. Priorities now name examples, doc corrections and tests alongside models. `examples/*/README.md` point at the one canonical section rather than restating it. Guard: 8 tests pinning the table to the scripts' argparse definitions rather than to a proofread — every documented `--oracle` value must be a real choice (negations excluded and covered separately), the no-enformer exception must remain true in both directions, the `--gpu` asymmetry must stay correctly described, the notebook generator must stay argument-free, and every test file the section tells a contributor to run must exist. Fast suite 1,993 passed / 30 skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lucapinello
force-pushed
the
docs/2026-08-14-contributing-an-example
branch
from
August 14, 2026 18:52
030c513 to
d02abae
Compare
lucapinello
added a commit
that referenced
this pull request
Aug 14, 2026
Found by reviewing this session's merges rather than by anything failing. **The itemised install size did not add up.** README stated "2.4 GiB base env + 5.9 GiB oracle env + 3.1 GiB hg38 + 1.9 GiB weights + 0.5 GiB backgrounds = 13.7 GiB", and those five figures sum to **13.8**. The total was right — the measured components are 2.41 + 5.89 + 3.05 + 1.87 + 0.52 = 13.74, which rounds to 13.7 — so the error was in the display precision, not the measurement. Rounding each component to 1 dp and then showing a total derived from the unrounded values gives a sum a reader can check and find wrong. Now stated to 2 dp, where the arithmetic closes. Whoever verifies a number I publish should be able to add it up. **CLAUDE.md still held a second, unguarded copy of the regeneration matrix.** #203 moved that matrix into CONTRIBUTING precisely because two copies drift, then left CLAUDE.md's copy in place, and the new guard pinned only CONTRIBUTING's. So the release ended with the same defect it had just fixed, one file over. CLAUDE.md's inline copy is worth keeping — it is auto-loaded into every session, so replacing it with a pointer costs an extra read on exactly the work where getting the matrix wrong is the documented way a regeneration silently does nothing. What is not worth keeping is an unchecked copy. Both are now parametrized over the same argparse-derived assertions: every documented `--oracle` value, the no-enformer exception in both directions, and the `--gpu` asymmetry. Pinned to `argparse`, deliberately not to each other — two copies checked against one another can agree and both be wrong. Verified that deleting "no enformer" from CLAUDE.md fails `[CLAUDE.md]` while `[CONTRIBUTING.md]` still passes, and that restoring it clears both. Fast suite 2,008 passed / 30 skipped (13 in this file, up from 8). Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lucapinello
added a commit
that referenced
this pull request
Aug 14, 2026
Everything in this cycle goes in 0.7.3, and the notes stopped at #203 while seven more PRs landed — most of them corrections to this release's own work, which is exactly the part a reader should not have to reconstruct from git log. Under Fixed: the five wrong published numbers and the two guards too weak to catch them; the strata table that asserted a uniformity the shipped provenance contradicts; the two documents that disagreed about whether the history was rewritten; and the audit runbook that still asked for the artefacts #198 removed. Under Changed: the browser job's narrow tolerance for an unreachable reference host, including the three ways the first version of it was too generous; pytest.ini no longer claiming an exact integration count that was never a property of the repository; and CLAUDE.md's copy of the regeneration matrix now being checked rather than merely present. The entries state how each defect happened, not just what it was — the weights figure came from a glob matching two HF mirrors, the null floor was one oracle's value read as the global minimum, and the stratification guard was defeated by prose 1,045 characters past the table it meant to check. Those are the reusable parts. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You asked about a developer who wants to contribute new models, examples, or just use chorus without friction. The model path is now well covered (#201 closed the last gap there). The example path was not covered at all.
Sentence one turned them away
CONTRIBUTING.mdopened with "this guide will walk you through the process of implementing a new oracle", and## Current Prioritieslisted three kinds of contribution — all of them models. Someone with a variant they care about, who has no intention of porting a neural network, is told immediately that they are in the wrong document. Adding a worked example is the cheapest useful contribution chorus can receive, and nothing invited it.It was also genuinely undocumented
Four regeneration scripts own different example types, and the matrix mapping example → script → valid
--oracle→ conda env lived inCLAUDE.md(a file written for Claude sessions), the CHANGELOG, and a May audit report. None of those is where a contributor looks.That matrix exists because getting it wrong is the most common way a regeneration silently does nothing:
regenerate_multioracle.pyacceptschrombpnet/cherimoya/legnet/alphagenomeand pointedly notenformer— whose report comes fromregenerate_examples.py--gpu, while the other two do; passing one is an argparse error that scrolls past in a tailed logFailed to load <track>once per track and carries on, so a run can spend an hour loading nothingWhat changed
## Contributing an example or walkthrough— the verified matrix, the real entry shape copied fromENFORMER_EXAMPLES, thestrict_refwarning aboutref, the four traps, and the six guard tests to expect. The documented pytest command collects 138 tests — verified, unlike the browser recipe that shipped collecting 0examples/walkthroughs/README.mdandexamples/notebooks/README.mdpoint at the one canonical section rather than restating itGuard
8 tests in
tests/test_contributing_example_path_matches_the_scripts.pypin the table to the scripts' argparse definitions rather than to a proofread:--oraclevalue must be a realchoices=entry — negations likeno `enformer`are stripped and covered separatelyenformer, the test demands the note be removed--gpuasymmetry must stay correctly describedgenerate_walkthrough_notebooks.pymust stay argument-free (documented as codegen-only)tests/*.pythe section names must exist — a documented command that errors is worse than noneConfirmed the choice-guard bites: a fabricated
seiin the walkthrough row is flagged, while the legitimateno `enformer`is not.Verification
test_doc_links_resolve.py70 passed — the four new in-page anchors and both cross-file links resolveadd_argumentcalls, not against CLAUDE.md🤖 Generated with Claude Code