RM index, items 1–99¶
One page of the RM index, which is paged by number: every item numbered
1–99, under the status or round heading it had when the index was one file. The rules
for adding an entry, and the allocator that claims a number, are on the index page.
✅ Shipped¶
0.4
- RM1 — compiler materializes every 0.4 table → parquet, lossless round-trip. · also in ROADMAP, CHANGELOG
- RM2 — composed modules:
variants.csvoptional, a module carries only the kinds it uses. · also in ROADMAP, CHANGELOG, SCHEMAS - RM3 ⚠ — PharmGKB row shape. Superseded by RM20, and the cautionary row: marked shipped against a hand-authored sample, then the real corpus rejected ~97% of itself. · also in ROADMAP, PROPOSAL_0_5
- RM8 — generated authoring reference (
authoring_reference()/json_schemas()), reachable since 0.5 asjust-dna-compiler reference. · also in ROADMAP, SCHEMAS, COMPILER, CHANGELOG - RM9 — recommended colour / icon palette (
RECOMMENDED_COLORS/RECOMMENDED_ICONS). · also in ROADMAP, COMPILER, CHANGELOG - RM11 —
doiprovenance column onStudyRow. · also in USE_CASES, SCHEMAS, COMPILER, CHANGELOG - RM12 — provenance locator:
provenance_quote/provenance_regex. · also in USE_CASES, SCHEMAS, COMPILER, CHANGELOG -
RM14 — structured per-version
authorship(identity / role / kind). · also in USE_CASES, COMPILER, CHANGELOG 0.5 -
RM6 — callability as first-class state:
requires_callable+callable_from. · also in USE_CASES, SCHEMAS, COMPILER, CHANGELOG, PROPOSAL_0_5 - RM13 — network-first resolution tier, realized as
just-dna-enricher. · also in USE_CASES, CHANGELOG, PROPOSAL_0_5 - RM17 — SemVer enforcement on
module.version, coercing. · also in COMPILER, CHANGELOG, PROPOSAL_0_5 - RM18 — frequency + gene-constraint sidecars (
frequencies.csv,gene_metrics.csv). · also in ROADMAP - RM19 — GA4GH VRS allele identity:
vrs_id,caid, VA-derivedvariant_key. Satisfies RM15's build-naming condition; multi-build minting stays RM15. · also in ROADMAP - RM20 — PharmGKB annotations are per-genotype and per-category. Corrects RM3. · also in USE_CASES, PROPOSAL_0_5
- RM21 — data-source licensing as data:
sources.csv+ the compile gate. · also in USE_CASES, COMPILER, ENRICHER, CHANGELOG, PROPOSAL_0_5 -
RM22 — PGx tables join resolution (
enrich()reads the PGx CSVs too). · also in USE_CASES, PROPOSAL_0_5 Found by dogfooding on 2026-08-03 — the batch of five that produced RM31–RM35. Four were fixed in that same window and are listed here; RM32 was held back as a question about identity and shipped in 0.5, below. Each entry keeps the probe, the repairs that stayed rejected, and (for three of the five) the part of the original argument that turned out to be wrong on probing. -
RM31 — ✅ shipped in 0.5: ClinVar's
X:634689 CAG>Cand Ensembl'sX:634690 AGAG>AGare the same 2 bp deletion, and string comparison called itnot_found. Closed by a frame-free parsimony reduction with a tri-state verdict; one residual (the authored genotype keeps its source's frame) is stated there. · also in CLAUDE.md, SCHEMAS, COMPILER, CHANGELOG - RM33 — ✅ shipped in 0.5:
sourcenamed a link inresolution.csvand a licensed source insources.csv, compared by string equality. Closed byResolutionRow.authority+ the link→authority map in the enricher; the two repairs the entry rejected stayed rejected. · also in CLAUDE.md, SCHEMAS, ENRICHER, CHANGELOG - RM34 — ✅ shipped in 0.5: CYP2D6 drafted 16,290 rows, 73%
Indeterminate, with no way to take a subset. Closed bydraft --allele, applied to all three tables; six alleles make CYP2D6 21 diplotypes. · also in ENRICHER, CHANGELOG - RM35 — ✅ shipped in 0.5: inclusive bounds + overlap-is-error + hole-is-warning were jointly unsatisfiable on a continuous measure. Resolved as a shared endpoint is a boundary and the higher bin owns it; half-open bounds lost on authorship. · also in CLAUDE.md, SCHEMAS, create-module skill, CHANGELOG
- RM37 — ✅ shipped in 0.5:
compile → reverse → compilemovedcontent_signaturefor a module authoringcurator/methodper row, because reverse re-emits the value underdefaults:and the hash read the CSVs before defaults applied. Closed by resolvingdefaults:into each row before hashing, reusing RM36's omit-the-model-default normalization so only a module stating something non-built-in moves (one of eleven reference examples). Also closed an unfiled defect: two modules differing only indefaults.curatorhashed equal. The other two candidate repairs stayed rejected, with reasons. · also in CLAUDE.md, create-module skill, CHANGELOG -
RM36 — ✅ shipped in 0.5: a model property that mints an identity had no module in scope, so
HeteroplasmyRow.variant_keygave a GRCh37 module's locus a GRCh38 VA whilevariants.csvgave it a coordinate key. Closed by injection — the loader tells each row the build via aPrivateAttr, so the declaration stays inmodule_spec.yamlalone and reaches no CSV, parquet or digest. Per-row and per-CSV ("service row") declaration were both rejected, with reasons. Carried the correction thatcontent_signaturewas not build-independent: it now hashes a non-defaultgenome_build, leaving every GRCh38 module's signature untouched. · also in CLAUDE.md, SCHEMAS, CHANGELOG The post-cut round of the same 0.5.0, which was still unpublished at the time. These carried a0.5.1label for a while; no 0.5.x had been published, so they shipped as 0.5.0 like everything above — see the note at the top of CHANGELOG.md. 0.5.0 released 2026-08-07.** -
RM26 — all three drafting providers: CPIC, ClinPGx, ClinVar. Partially dissolves RM4. · also in ENRICHER, CHANGELOG
- RM29 — cofactor columns:
quality_from/min_qualityonVariantRow,clinical_contextonDiplotypeRow. Dissolved thedraft --populationrefusal. · also in CHANGELOG - RM30 — one haplotype-name rule across all three PGx tables. · also in REFERENCE_EXAMPLES, CHANGELOG
- RM32 — ✅ shipped in 0.5, the fifth of the 2026-08-03 dogfooding batch and the one held back as a question: a pseudoautosomal locus is one place on two contigs, modelled as two variants (10 SHOX findings → 20 rows). The probe the entry named refuted its own preferred direction — ClinGen mints two CA ids per PAR base, so there is no place identity to adopt — while the objection that had parked the enricher policy also failed: ClinVar and gnomAD place PAR annotation on X exclusively, so selecting X records the sources' convention, not the consumer's analysis set. Closed by
vrs.par_partner+ X-spelling selection (--keep-par-twinkeeps both), per locus because XG and SPRY3 straddle a boundary. Carried a false-absence fix infrequencies.csv(not_covered) with it. · also in CLAUDE.md, SCHEMAS, ENRICHER, COMPILER, create-module skill, REFERENCE_EXAMPLES, CHANGELOG 0.5.1 — the network tier alone (enricher + compiler; format untouched at 0.5.0)
Not a schema release. Every item is enricher/compiler API shape, out of artifact.digest, and touches
no parquet — which is what makes a patch legal inside the closed 0.5 digest window (P3/P8). RM38 came
from design; RM39–RM42 are a just-dna-registry consumer field report, and the through-line is one
this codebase already makes elsewhere: a number this workspace computed and then discarded gets
recomputed by every consumer, and a recomputation is a place to drift.
- RM38 — ✅ shipped in 0.5.1: the three licence-gated PGx sources were the only ones with no cache, so a hosted enricher either fetched them live per request on the operator's own credentials or skipped the check. Closed by
cpic_build/pharmvar_build,locations.resolve_{cpic,pharmvar,clinpgx}_reference,download.ensure_{cpic,clinpgx}_snapshot, duckdb snapshot clients duck-typed against the live ones, and a real--offlineonpgx/draft. PharmVar is build-only — its key is personal and non-transferable, so no publish and noensure_*. Two prerequisite defects fixed on the way (LICENSE.txtnever published; the layout constants imported from a[dev]builder) and two integration defects found by probing (PharmVar's GRCh37-first coordinates; CPIC'sgene.chr). · also in CLAUDE.md, ENRICHER, CHANGELOG - RM39 — ✅ shipped in 0.5.1:
enrich_dosage_sensitivitywas the only pass with noofflineparameter, so one member of a family run under one flag egressed on a path documented as making none. Closed additively: the flag,ClinGenResult.skipped_offline,--offlineondosage. An injectedcuration_textstill wins — that is not egress. · also in ENRICHER, CHANGELOG - RM40 — ✅ shipped in 0.5.1:
enrich()computed theMintResultthe compiler later stamps into the manifest and dropped it, so a pre-compile consumer re-implemented per-ALT-slot counting and could disagree with the manifest a publish would produce. Closed byEnrichmentResult.vrs;Nonewhen the pass did not run, never a coverage of zero. · also in ENRICHER, CHANGELOG - RM41 — ✅ shipped in 0.5.1:
compiler._load_csv_rowswas private and the only correct authored-CSV loader, so consumers chose between a private symbol and a re-implementation with two known traps. Closed both ways:compiler.load_csv_rowsis public (old name kept as an alias),compiler.load_spec_variantsdoes the build injection and re-stamp, andverify_acmg_sf/check_identifiersacceptspec_dir=besidevariants=. · also in COMPILER, ENRICHER, CHANGELOG - RM42 — ✅ shipped in 0.5.1: nine
stop_after_attempt(3..4)decorator arguments with no setting, so a server inside an unattended publish could not ask for more persistence than an author at a terminal wants; a consumer was walking the package to reassignpolicy.stop. Closed bynet.attempt_floor+$JUST_DNA_HTTP_RETRY_ATTEMPTS— a floor that preserves the deliberate per-client tuning, never a flat set. · also in ENRICHER, CHANGELOG
✅ Also shipped in 0.6.0 — open items, not design-round decisions¶
Why these three sit apart from the section below: they were already open RMn items when the 0.6
cycle started and landed together on 2026-08-12, a day before the design round, so their outcomes live
with the other shipped items under
ROADMAP_HISTORY § Shipped items rather than in that file's
§ 0.6.0 section, and none of them was argued in
PROPOSAL_0_6.md. Same release, different provenance.
- RM44 — ✅ shipped in 0.6.0:
fully_resolvedisall()overvariants.csv, hence vacuously true for a table-only module, and a catalog following the documented trust rule servedtrusted: truefor modules that join to no VCF. Fixed downstream by substring-matching the 0.5.3 warning's prose, which makes a sentence load-bearing (compiler.UNJOINABLE_PHRASEpins it meanwhile). The fix is one additive integer —resolution_subjects— beside the flag, the same parts-not-conveniences pattern asvrs_alleles. Do not make the flagNone-able, and it does not retireUNJOINABLE_PHRASE(that count belongs with RM43). Counted after rsID expansion, since that is the list the flag iterates. One thing the item missed and the history entry records: the number was already available asStats.weights_rows— publishing it beside the flag is still right, because that equality is a property of the materializer rather than a contract andStatsis display facets, but check for an existing carrier before adding a computed field. · also in CLAUDE.md, COMPILER, CHANGELOG, CONSUMER_SUGGESTIONS_HISTORY § S13 - RM49 — ✅ shipped in 0.6.0, together with RM51 and sharing its resolver: nothing in a spec listing says which files a human wrote and which the enricher produced, so a registry gave publishers a
derived/tree and found it is onecompilerefuses; their layout stays transport-only (flatten on upload, re-split on download). The byte-attestation half of S26 shipped asmanifest.derivedin 0.6.0; this is the half that did not. Not the one-line fallback it looks like:spec_dir / "resolution.csv"is resolved in eight places across two packages, and tolerating the layout on input without deciding the write side breaks on first use —enrichon a downloaded split module writes to the root, producing the both-copies-present collision by following the documented workflow. Three candidate repairs named and refused: search any subdirectory (blinds_check_misspelled_tables, re-opening S16's hole), makederived/canonical (two supported layouts, andreverseemitting a tree older compilers in the same major cannot read), extend it to authored tables (two legal homes forvariants.csv, so the ignored copy is invisible). Shipped asjust_dna_format.layout— tolerated, never canonical; write to the file you read; both present is an error naming both. Two things the item did not record:_check_misspelled_tableshad to be extended into the subdirectory or a single fixed name blinds it just as a tree walk would, andmanifest.derivedcarries the relative path so a re-splitting registry can use it. · also in CHANGELOG, CONSUMER_SUGGESTIONS_HISTORY § S26 - RM51 — ✅ shipped in 0.6.0: accept
licensing.csvas a second spelling ofsources.csvin 0.6 (enricher writes it, compiler falls back to it), so the 1.0 rename only has to remove a spelling rather than add one. Minor-legal for a checked reason: the fact sidecars are not in_INPUT_FILES, so the filename enters no identity —content_signatureis rows,source_signatureis facts,manifest.derivedis transport-only. What cannot come along issources.parquet(insideartifact.digest, read by name) and themanifest.sourceskey — both removals, both major — so the 0.x tail readslicensing.csv→sources.parquet→manifest.sources, which is the cost. Both files present is RM49's collision (fact-hashed and human-overridable, so no merge and no newest-wins) — write to the file you read, error naming both; the two items shipped together for exactly that reason. The item estimated five enricher write sites and there were nine, sorecord_source_terms/merge_sources_filetake the spec directory now and no pass names a spelling by hand. Old spelling deprecated in 0.6, removed at 1.0. · also in CHANGELOG, SCHEMAS, COMPILER, ENRICHER
✅ The 0.6 design round — decided, then built¶
All decided on 2026-08-13 in PROPOSAL_0_6.md and all built in the batch that
followed. Eleven have their own outcome entry — RM4, RM5, RM24, RM25, RM27, RM43, RM45, RM46, RM47,
RM48, RM50 — and their numbers link to it in ROADMAP_HISTORY § 0.6.0,
which records what probing changed along the way. The VCF 4.4 cluster deliberately has none: RM53–RM65
came from VCF_4_4_AUDIT.md, which stays their evidence document (spec quotations,
file:line, probe transcripts) and would only be restated by a history section, so those numbers link
into the proposal instead. Either way the proposal stays the authoritative record of the reasoning:
the problem, the facts probed, the decision, the repairs that were rejected and why, and the
consequences that follow without being chosen. Where an entry below and the built result disagree, the
history entry wins.
Landed on the 0.6 branch in eleven parallel lanes plus a charter amendment that went first and alone
(schema-change cost by layer: a parquet column is ~free, a derived CSV half, an authored schema full —
four of the decisions turn on it). Corpus effect of that batch, measured across the eleven reference
examples it had: content_signature moved on two modules (both re-authored on purpose),
artifact.digest on seven, resolution_signature was gained by the four table-only modules that
never had one, and the source signature moved nowhere. Suite 1535 → 2046. Left as that round's own
numbers rather than refreshed — a measurement of a batch is not a running total.
A second round followed on 2026-08-14: dogfooding the batch produced five probe modules, a corpus
sweep and the findings ledger DOGFOOD_0_6_FINDINGS.md, then twelve parallel units fixed
what it classed fix (PRs #12–#23; the release view is the newest CHANGELOG.md entry).
It changed no decision — where it changed what an item shipped as, the entry below says so, and the
five findings whose repair is itself a design decision became RM68–RM72 in the 0.7 section. Its own
corpus effect, over the sixteen examples there are now: content_signature, resolution_signature and
the source signature are unchanged on every module, and artifact.digest moved on the three carrying
literature.csv, where LiteratureRow gained an optional doi_checked. Suite 2046 → 2221.
- RM4 — gene-panel materialization. Off the compiler: the surface is enricher draft-scaffolding, and the author's no-op over the drafted subset is the authorial act. Takes the
panel:block with it (deprecated, removal at 1.0; the tautology check now keys on a ClinVar releaseclinvar_draftstamps into the licence row, both sides calling one shared label function) and re-keys that check on a mode ladder —strictaudits every row into copied / authored / conflicting / no_record. Two findings came out of building it: a never-clobber merge turns a machine-stamped release label into a stale claim, so it is withdrawn rather than re-labelled; and "copied" had to become allele-exact, since a locus-wide match can be a sibling allele's call. · also in CHANGELOG, CLAUDE.md, ENRICHER, SCHEMAS, USE_CASES, ROADMAP_1_0, PROPOSAL_0_6 - RM5 — symbolic / structural alleles. The five closed VCF first-level types and nothing beyond the standard — no declaration mechanism, no named aliases. The length rides inside the token (
<DEL:1500>,<CNV:TR:30>), decided on evidence: SVLEN isNumber=A, so a scalar column cannot describealts=<DEL:5>,<DUP:9>and three of the columns holding an allele have no row to hang a length on. A lengthless one is dropped with a warning that says dropped, refused understrict, and fatal in both modes on the composite tables. 5-HTTLPR is a plain indel; CPIC's IUPAC codes stay unexpressible, deliberately. The 2026-08-14 round found the tier this was never told about:enrichcrashed outright on a symbolic allele, and offline the compiler called it an indel and prescribed a re-run that was the crash. Both fixed, with a permanent reason class rather than an--offlinelimitation, and the lengthless message now names the token it was given instead of always saying<DEL>. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, USE_CASES, REFERENCE_EXAMPLES, DOGFOOD_0_6_FINDINGS §§ D1, D3, PROPOSAL_0_6 - RM24 — gene–disease validity. Built as a derived sidecar:
gene_validity.csv, machine-written, half cost, its own signature and manifest block, and a new non-taintinggene_validitysource layer. Probing moved the stated key twice — mode of inheritance joins it (59 ClinGen gene/disease pairs differ only there) and so doessubmitter, because GenCC is a nineteen-submitter aggregate whose disagreement is the data. HPO ships no route: its licence URL 404s and OBO Foundry records no SPDX id, so its terms cannot be established, and an inject-only tier does not assume them. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, PROPOSAL_0_6 - RM25 — ClinVar assertion tier. Built as a derived sidecar,
clinical_assertions.csv: the clinical call, the review wording, the star rating and ClinVar's own VariationID, one row per allele × record. Compute-and-discard, the fourth instance —draft_gene_panelwas already filtering on the star rating and throwing it away. A one-star single submission and a practice guideline are no longer flattened to the sameclin_sig. The cross-check's severity stays parked, deliberately. · also in CHANGELOG, COMPILER, ENRICHER, SCHEMAS, PROPOSAL_0_6 - RM27 — redistribution. Record only, verdict in the manifest; no gate in these four packages, because gating belongs at publish and publish lives downstream. It ships with an explicit ask addressed to the registry in SCHEMAS.md rather than an implication, which is the whole difference from the status quo it was filed about: a recorded right nobody is told to enforce, versus a recorded right with a named enforcer. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, PROPOSAL_0_6
- RM43 — resolution reaches the SNP core only. The positional parquets are filled now, in
validate_specas well ascompile_module, each model gaining stamped parquet-onlyvariant_keyandauthored_identplusaltsonPharmVariantRow/HaplotypeRowas data, not identity. Noresolution.parquet; reverse rebuilds the lookup table from the positional parquets, which P7 forces.pgx_slco1b1_simvastatinwent from nine all-null rows to12 / 21178615 / T / A,C. One deviation kept: the stamped fields areField(exclude=True), orcontent_signaturemoves on all five positional modules — which leavesVariantRow's own two inconsistent with them, grandfathered and filed as a 1.0-cleanup candidate. The fill is skipped off GRCh38 (RM15), which is what RM69 is about. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, CONSUMER_SUGGESTIONS_HISTORY § S9, ROADMAP_0_8, PROPOSAL_0_6 - RM45 — the manifest cannot say what was verified. Shipped as
verification.json, a derived attestation the enricher writes and the compiler stamps intomanifest.verification, dropping it with a warning when stale: counts rather than booleans, two fields rather than one union-typed slot, two closed vocabularies, hash-bound with a ~0.4 s median proof-of-work per sidecar and a deterministic nonce, every field marked untrusted because a forged pass is worse than silence. A JSON document rather than a fifth fact CSV. Depended on RM43. The 2026-08-14 round found the vocabulary half-wired — twelve of the seventeen check members were emitted by nothing. Six were wired then (three fromliterature, one each frompgxandvrs mint, and rsid↔coordinate insideenrich, a check that turned out to be unreachable fromenrich()at all); the remaining six are RM72. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, CONSUMER_SUGGESTIONS_HISTORY § S8, DOGFOOD_0_6_FINDINGS § D4, PROPOSAL_0_6 - RM46 — per-article literature terms. Four licence columns on the derived literature row, filled from the Europe PMC response the pass already makes and mapped at read time, so a mapping fix reaches rows already written. No
PUBMED_TERMSconstant: one "pubmed, fine" row would clear a module quoting a CC-BY-NC article, which is wrong in the dangerous direction. Quoting a restrictive article warns, never gates — arbitrating copyright is the same overreach as arbitrating a clinical dispute. · also in CHANGELOG, CLAUDE.md, ENRICHER, SCHEMAS, CONSUMER_SUGGESTIONS_HISTORY § S10, PROPOSAL_0_6 - RM47 — a threshold has nowhere to cite. A pointer on the bin row —
MeasureBinRow.pmid, one optional column on the binning base reaching all four kinds — and the citation subject relaxed, so astudies.csvrow may name no variant at all. The bin cites, the citation table describes, which is what stopsStudyRow's provenance columns migrating onto binning rows one at a time. The same-release obligation was met rather than deferred: the compiler's cross-check and the enricher's literature pass both read the new site, reached through public compiler symbols rather than a private import. Corrected on 2026-08-14: the grounding check was also clearing a bin that carried a variant identity, on the reasoning that a study row could name it back — inside a branch that had already established the module records none — so aheteroplasmy.csvmodule stating four thresholds and citing nothing was silent while the same thresholds onrepeat_alleles.csvwere reported. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, CONSUMER_SUGGESTIONS_HISTORY § S19, DOGFOOD_0_6_FINDINGS § D1, PROPOSAL_0_6 - RM48 — old-assembly coordinates. rs-number recovery only, no liftover, no chain file — the stated blocker was checked and is false, since Ensembl's GRCh37 REST service is permanent, unauthenticated and same-shaped. Reporting, never filling. The offline half (a position past its contig's end, a contig only one build names) went into the compiler as an error in both modes; the online build-guessing half stayed in the enricher and supersedes the ±1 shift reading only from its two strong evidence tiers. Its sensitivity is ~3 in 4 and now measured rather than asserted, so "the compiler catches wrong-build coordinates" is not a reading to take. · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, CONSUMER_SUGGESTIONS_HISTORY § S22, ROADMAP_0_8 (RM68), PROPOSAL_0_6
- RM50 — PubMed vs PubMed Central ids. Guard + the PMC id on the derived row + a reporting reverse lookup (
hint citation --pmcid) that never fillspmid, because filling it would make the existence check compare NCBI with itself. The live hazard was the accepted spelling, not the refused one:PMC 3110566used to extract as PMID 3110566, a real id for an unrelated article, so a cell that compiled before may refuse now. The authored half is 1.0 with the requiredness demotion. · also in CHANGELOG, CLAUDE.md, ENRICHER, SCHEMAS, PROPOSAL_0_6 - RM53 — a bare VCF field name means two different fields (
DP,AD,MQ,AF,CN). Accept the qualified form; warn on a bare colliding name. Both shipped reference examples were wrong and were re-authored, which is whymt_heteroplasmyandhtt_repeat_expansionare the only two modules whosecontent_signaturemoved across the whole batch. · from VCF_4_4_AUDIT § 1 · also in CHANGELOG, COMPILER, SCHEMAS - RM54 — a pointer at a multi-valued field cannot say which value. A closed vocabulary of selection rules, never an index. Shipped on the binning base's
source_fieldonly —callable_element/quality_elementare reserved, not built:callable_fromandquality_fromcan name a multi-valued field too and no module does, and an authored column onvariants.csvis full cost under the 0.6 amendment. Additive whenever a real case arrives (P3), the names held inRESERVED_NAMES_0_4so they survive the one-way door, and everything readingVCF_POINTER_COMPANIONSis generic over it. The proposal reads as though the rule reached all three columns; this is the built shape. The 2026-08-14 round carried the rule meanings onto the surface an author reads: they reached only the whole-schemareferenceand notdescribe <kind>, andlargest's sentence explained the rule as the longer of the sample's two alleles — a diploid claim, corrected against FMR1 in a male. · from VCF_4_4_AUDIT § 2 · also in CHANGELOG, COMPILER, SCHEMAS, DOGFOOD_0_6_FINDINGS §§ D1, D5 - RM55 (0.6 half) — copy number and repeat count are not whole numbers. 0.6 warns loudly and changes nothing. Fix in PROPOSAL_0_6_PT2 — taken back into 0.6 on 2026-08-16, so the fix and this warning now ship in the same line and the warning becomes conditional; removal in ROADMAP_1_0.
cyp2d6_structuralandfmr1_cgg_repeatare the corpus instances it fires on, each naming the field the spec does (CN,RUC). · from VCF_4_4_AUDIT §§ 3, 4 · also in COMPILER - RM56 (0.6 half) — a measurement can span several bins. 0.6 withholds and says loudly that no policy exists, once per table, and says that withholding is not the
unresolvedrow. Policy vocabulary in ROADMAP_0_8. · from VCF_4_4_AUDIT § 4 · also in COMPILER, SCHEMAS - RM57 — a quality floor inverts on reference records; callability evidence is a block, wanting interval containment and the block minimum. Docs + warning, and the warning names GQ and MIN_DP as the fix rather than leaving the author with the diagnosis. · from VCF_4_4_AUDIT § 5 · also in SCHEMAS
- RM58 —
alts="."splits identity. A diagnosis, not a grammar; stop filing the MISSING marker beside symbolic alleles. The only VCF finding reaching identity. The 2026-08-14 round guarded the minter against it too —.raised the same unhandledga4gh.vrserror a symbolic allele did. · from VCF_4_4_AUDIT § 6a · also in CHANGELOG, COMPILER, ENRICHER, SCHEMAS - RM59 —
*, the allele that could not be observed. Writable, and the contract states the withhold rule. Decided beside RM5, deliberately not inside it —*names no variant, it makes an observability claim. The 2026-08-14 round found the sharper half:*passesga4gh.vrs's sequence pattern, so an unobservable allele reaching the minter would have been handed a content-addressed id for a state that is not a sequence. Guarded on the enricher side. · from VCF_4_4_AUDIT § 6b · also in CHANGELOG, COMPILER, ENRICHER, SCHEMAS - RM60 —
chromrejectschrMwhile a normalizer in the same package accepts it. Widening only, and it did not blind RM48:chrM:16600is still refused against MT's 16,569 bp. · from VCF_4_4_AUDIT § 7 · also in CHANGELOG - RM61 — the pointer grammar rejects VCF-legal keys (
1000G, dotted). Widening only. · from VCF_4_4_AUDIT § 8a · also in COMPILER, SCHEMAS - RM62 — 32-bit values against 64-bit inclusive bounds. Consumer contract, no schema change — and the rule as shipped was one-sided. Narrow the authored bound to float32 rests on
float32(0.3)landing above0.3;float32(0.9)lands below0.9, so narrowing an authored0.9upper bound drops a row whose measurement never went through float32. The rule that survives is the one SCHEMAS.md's own heading always gave — compare in float32 — corrected on 2026-08-14 and put onmeasure_max's printed description, since the word "narrow" appeared zero times in what an author actually reads. · from VCF_4_4_AUDIT § 8b · also in CHANGELOG, SCHEMAS, DOGFOOD_0_6_FINDINGS § D6 - RM63 — a pipe-separated genotype names no homolog without a phase set. Shipped as a correction to a code comment, and carried onto the printed
genotypedescription on 2026-08-14 — the pipe form was not in the authoring contract at all, while the validator accepted it andphasedround-tripped. The 0.6 replacement wording overclaimed in its turn:C|Cloads, so "read a pipe as heterozygous" is false of a genotype the model accepts. The printed description carries only the true half ("phase recorded but unaddressable"); the code comment it was copied from is still wrong, filed as R2-14. · from VCF_4_4_AUDIT § 8c · also in CHANGELOG, SCHEMAS, DOGFOOD_0_6_FINDINGS §§ D5, Round 2 - RM64 — the VCF id column is a semicolon list. Documentation. · from VCF_4_4_AUDIT § 8e · also in SCHEMAS
- RM65 (0.6 half) — repeat and copy-number tables are positional and the code says they are not. 0.6 corrects the claim; the coordinates wait in ROADMAP_0_8. · from VCF_4_4_AUDIT § 10 · also in ROADMAP
✅ The 0.6 dogfooding fix round — Round 2's own findings, repaired¶
Round 2 of DOGFOOD_0_6_FINDINGS.md came from reading the code around each 0.6 repair rather than from building a module, and its thirteen actionable findings were grouped into RM74–RM79 on 2026-08-14. All six shipped, on 2026-08-15 — which cleared the sprouts before the ground: RM76's narrow repair is what landed here, and the root it grows from, RM73, closed a day later. Outcomes in ROADMAP_HISTORY § 0.6 dogfooding.
- RM74 — ✅ shipped: ClinPGx's
geneis;-multi-valued and both readers treated the cell as one symbol — 396 of 16,087 snapshot rows, and--gene VKORC1silently dropped the 3 rows ofrs17886199(PRSS53;VKORC1). The filter matches per member now. What a plural cell writes was the real choice and two candidates are decisively refuted: one row per gene is illegal, becausegenesits outsidePharmVariantRow's dedup key and the copies collide wheredrugs' copies do not; and picking from the cell has no rule to pick by, since the pharmacogene is first inCYP3A5;ZSCAN25and second inPRSS53;VKORC1. What shipped is the CPICgene.chrmove — write the member the request selects, and otherwise withhold and name the genes the cell held. Also:skipped_unidentifiedwas counted before the--genefilter, inflating "records the source could not identify" by the rest of the database (R2-11); and a location fixture keyed"location"wherecpic.defining_variantsreads"sequence_location", so the file's claim to cover a coordinate-carrying defining variant was hollow and green either way (R2-3), now fixed with the key and an assertion that the coordinate reacheshaplotypes.csv. · from DOGFOOD_0_6_FINDINGS § Round 2 (R2-1, R2-11, R2-3) · also in CHANGELOG - RM75 — ✅ shipped: three instances of work that has already succeeded being thrown away.
CpicClient._getwrapped only shape failures, so an exhausted retry ladder left a rawhttpx.HTTPStatusErrorthat walked through both ofenrich_pgx's per-leg handlers and took PharmVar's answer with it (R2-13) — the retrying half is_requestnow and the translation sits outside it, since wrapping inside would makeretry_if_exception_typea no-op, with a test that the ladder survived the split. The ledger named only CPIC and PharmVar had the identical hole; repairing one leg would make "one source failing must not sink the pass" true in one direction only.knows_drugis caught (R2-4), so an optional message-enrichment call can no longer discard a finished draft, and thebool | Nonetri-state that was designed and never delivered from the live client is finally reachable — with a third wording, because "the snapshot cannot answer" and "the request failed" have different remedies. Andspec_genome_build's deliberate raise no longer tracebacks out ofdraft/draft-panel(R2-2):_DRAFT_PRECONDITION_ERRORSnames the shared cause, and the check moved above the snapshot provisioning it used to be paid for. · from DOGFOOD_0_6_FINDINGS § Round 2 (R2-13, R2-4, R2-2) · also in CHANGELOG - RM76 — ✅ the narrow repair shipped: a
<<REPLACE>>stub in the licence table compiled green under--strictand reachedmanifest.sourcesinside the block its own signature covers.SourceRowis not anAuthoredModel(deliberately, as a machine-produced reference fact) and S21 made it draftable (deliberately, as the one fact sidecar a human writes); both were right and nobody reconciled them. The guard lands on the model rather than through the base —ModuleSpecConfigis the precedent — so the other four sidecars stay out, since no template is generated for them. Two things worth carrying: a vocabulary column was catching the stub by accident, which is why the free-text half stayed open and why this item's first test came out green on the unfixed code; andstub_template's printed guarantee ("an unreplaced stub cannot compile") is now asserted over everyDRAFTABLEkind, having held only where a model happened to inherit the right base. The general question — what marks authoring as unfinished — is RM73, which closed on 2026-08-16. · from DOGFOOD_0_6_FINDINGS § Round 2 (R2-8) · also in CHANGELOG - RM77 — ✅ shipped: a genotype pasted from a VCF (
0/1) fell through to the nucleotide-grammar wall and was never told those are allele indices into the record's REF/ALT list — the single most likely mistake in this column, since pastingGTis the obvious first guess.0/1/1was worse because of 0.6: the ploidy fix gave it a confident, correct explanation of the two-allele ceiling, which is about the wrong thing, so the diagnosis runs ahead of the arity branch and a test pins that a base-spelled triploid still gets the ceiling message. Changes no verdict — every matched cell was already refused — and reachesPharmVariantRowfree, since the grammar has lived onAuthoredModelsince 0.5. Second half: RM63's own replacement wording was false, sinceVariantRow(genotype="C|C")loads and1|1is an ordinary phased homozygote; the printeddescribeoutput had already dropped the zygosity word, so only the comment it was copied from was wrong. A correction is where this happens — the reviewer checks the claim being removed, not the one going in. · from DOGFOOD_0_6_FINDINGS § Round 2 (R2-9, R2-14) · also in CHANGELOG - RM78 — ✅ shipped, all three parts.
*no longer lands in the compiler's indel bucket (R2-6 — filed as having no instantiation, upgraded when*turned out to passLiteralSequenceExpression's^[A-Z*\-]*$; note severity could not have caught it, since the indel branch it fell into is also tier-blame, so only the reason can).refget_supports_buildno longer answersTruefor the two inputsrefget_accessionraises on (R2-10 — the old reasoning imported a spec-layer default into the identity layer, and every other build gate invrsalready read it the other way). And the decision (R2-5): a stored VA against a symbolic allele is now the row's contradiction, an error in both modes, settled grammar-first —validate_vrs_allele_idmakes bothvrs_idcolumnsga4gh:VA.-only (no instantiation: 844 corpus ids, all VA) so a present id can only name a different allele, and only then does the escalation follow. The asymmetry is pinned: an absent id on the same row stays a warning, because absence is a limit and a claim is a claim. · from DOGFOOD_0_6_FINDINGS § Round 2 (R2-6, R2-10, R2-5) · also in CHANGELOG - RM79 — ✅ shipped:
manifest.literature.missing_countcounted the whole table while thecitation_existencerecord counted the module's current citations, so the two disagreed in a published manifest with nothing wrong in the module. The item's own framing was the wrong question — both blocks already publish their denominator, so the reconcilable-or-not choice was not the live one; what nobody had decided is why a row nothing joins to is in the artifact at all. The compiler discards it andliterature.csvkeeps it, so the counters agree by construction rather than by documentation. Four things pinned: the check sees every row and everything after it sees the kept ones (reporting needs the full list); an empty citation set discards nothing (a module citing nothing cannot tell a stale sidecar from unauthored citations); both citation sites count, and the stakes rose — blind to binpmids the compiler would now discard a threshold's evidence rather than warn about it; and the round trip narrows once and converges, which is what makes a derived-sidecar narrowing tolerable at all. No corpus movement, and no corpus coverage either — pinned by fixtures. · from DOGFOOD_0_6_FINDINGS § Round 2 (R2-16) · also in CHANGELOG
✅ The 0.6 PT2 round — the items that fell in while 0.6 was open¶
Sorted in PROPOSAL_0_6_PT2.md on 2026-08-16: five taken back into 0.6, sixteen left deferred with the reason restated per item.
- RM55 (the fix) — ✅ shipped in 0.6.
measure_tiling({quantised, continuous}, optional, on the binning base so it reaches all four kinds) is what the shared-endpoint and gap rules now read, through an effective tiling resolved per bin group: the declared value, elsecontinuouswhere aquantised-defaulting kind carries a value no grid can hold, else the kind's default (DEFAULT_MEASURE_TILING,activity_score→ neither). Absent means the kind's default, never a value, so every published module keeps its meaning and no corpuscontent_signaturemoved._INTEGER_KINDS/_DENSE_KINDS/_CONTINUOUS_GAP_KINDSbecame inputs to that default table and stopped deciding a rule;_DENSE_KINDShad been literally the same object as_CONTINUOUS_GAP_KINDS, which made "spelled separately" a comment rather than a fact, and it is spelled out now.modifier_copy_number: float | Nonesits besidemodifier_cn, the one genuineint, read througheffective_modifier_copy_number(is not None, notor— SMN2 = 0 copies is a real dosage), both-set an error,_KEY_FIELDSkeying on the effective value so the key never holds two spellings.modifier_cnis deprecated warn-only, once per table, naming its replacement, so 1.0 inherits a removal and not a retype. The 0.6 RM55 warning is now conditional — a kind VCF 4.4 types as fractional and still reading as a grid — withFRACTIONAL_MEASURE_PHRASEbyte-identical. One deviation from the proposal, taken deliberately: the fractional inference fires only against aquantiseddefault, not "whatever its kind's default says".activity_scoreis fractional by nature (cyp2d6_structuralbins at 0.25/0.5/1.25/2.25) and asserts nothing about the grid, so the broad reading produced three false coverage gaps on a shipped module — the rule is the data contradicts the reading, and onlyquantisedstates a grid for a fraction to contradict. · also in CHANGELOG, SCHEMAS, COMPILER, create-module skill, history/ROADMAP_0_7 (stale in its suggested fix, marked so), ROADMAP_1_0 (removal half)
✅ The S36 round — what one consumer note about weight closed¶
Filed and closed 2026-08-17 from S36. The report is about authored weights; two of the three items are about the machinery that has to exist before a weight can be grounded in anything, and the third is the declaration the report actually asked for.
- RM90 — ✅ shipped in all three packages 0.6.0 on 2026-08-17. The report asked for the enricher to fill
weightwhere the authored cell is null; that is barred twice over (MODULE_LIFECYCLE names the cell, and checks report rather than repair) and carries a sign trap —weightis positive=protective while a GWAS beta is positive on the effect allele. So the effect getsgwas_effects.csv→.parquet, the seventh derived-fact table, andweights.parquet.weightstays 100% authored. Modelled from the real REST payload, which the download TSV would have got wrong:orPerCopyNum/betaNumare separate mutually exclusive keys, not the TSV's one ambiguous column;betaUnitis free text and is the reason the table exists;betaDirectionis about the measured trait and is kept offdirection(P5 — increasing HDL and LDL are bothincrease);riskAlleleNameisrs4149056-?when no allele was established, which parses to null and is counted, not dropped. No coordinates on the row — the payload has none.rsidis inside the fact set, invertingCLINICAL_ASSERTION_FACT_FIELDSbecause here the Catalog is queried by it. The live run broke the pass twice, neither reachable from a fixture: a 404 is the empty answer (the pass died on the first rare variant of the first module it met), and apvalue: 0.0underflow was dropping whole associations (189 → 195 rows once withheld instead). A prediction the measurement refuted: link-caching was expected to collapse the1+2Nbudget and saved nothing — 382 requests, zero hits — hence--no-study-facts. First source with no named licence;commercial_usestaysNoneand warns rather than gating. Corpus: adding the table moved nothing;hfe_hemochromatosisthen adopted 195 real rows — 62 traits, 12 distinct units including three spellings of one and two case-variants, 42 of 195 with no effect allele — and itscontent_signaturedid not move. · from CONSUMER_SUGGESTIONS § S36 · also in SCHEMAS, COMPILER, ENRICHER, MODULE_LIFECYCLE, CHANGELOG - RM91 — ✅ shipped in
just-dna-format+just-dna-compiler0.6.0 on 2026-08-17.StudyRowhas carriedeffect_size+effect_measuresince 0.3 with noeffect_allele, so every study row in the format stated a magnitude relative to nothing — whileVariantRowhas had the column since the same release precisely becauseref/altsplus the sign cannot recover which allele the claim is about, and the existing check's own message says a wrong one inverts the conclusion rather than breaking it. That check iteratesvariantsonly, and there was no field on a study row for it to read. One optional column plus_check_study_effect_alleles, on the same mode ladder and registered in bothvalidate_specandcompile_module(@parity-by-check). It reads resolved evidence only and withholds on everything else — aStudyRowhasrefwithoutalts, so{ref}alone would flag every study of a non-reference allele, which is most of them; unresolvable is unknown, not wrong.StudyRow.ALLELE_COLUMNSis("effect_allele",)and the omission ofrefis the design:AuthoredModel's rule is sequence columns that are the claim, never a column that points at a variant, and it namesStudyRow.refas its own example of the second kind._allele_verdict's resolved half was factored into_resolved_allele_verdict, not copied. Measured, prediction exact:artifact.digestmoved on 10 of 16 examples — the ten carrying astudies.parquet— andcontent_signatureon none. Round-trip test watched failing with only the reversefieldnamesentry removed. · from CONSUMER_SUGGESTIONS § S36 · also in SCHEMAS, COMPILER, CHANGELOG - RM92 — ✅ shipped in
just-dna-format+just-dna-compiler0.6.0 on 2026-08-17.effect_sizehaseffect_measurebeside it;VariantRow.weightis a barefloat | Nonereading "Score (positive=protective)" with no unit column, no range and nothing saying whether two modules' weights are on one scale — so consumers combined across modules anyway, and the reporter's summary of the result is that the weights "construct nonsense".Weighting(scale/method/note, three optional free-text strings,extra="forbid") onModuleSpecConfig, copied toModuleManifest, advisory exactly likelicense: out of both identity halves and dropped byreverse_module. The field it deliberately lacks is the design — no precedence rule, nothing saying "use the GWAS effect whereweightis null", because a per-row precedence rule puts two methodologies in one summable column, which is the reported defect, and leaves no single scale to declare. Measured while triaging and it reframed the item:weightis authored zero times in this repo — four of ninevariants.csv-carrying examples have the column, 42 rows, every cell blank.measure_tilingis the nearest precedent and is a column, not a yaml key; what transferred is its declared→inferred→default resolution shape, not its placement. No corpus movement (nothing adopted it in that commit); adopting it stales a module'sverification.json, which is pinned. Closed a gap in passing:license/panel/authorshipare all documented as reverse-dropped and none was asserted anywhere. · from CONSUMER_SUGGESTIONS § S36 · also in SCHEMAS, CHANGELOG, create-module skill
✅ The 0.6.1 round — what reading the code against the documents found¶
Filed and shipped 2026-08-18. A pass regenerated SCHEMAS/COMPILER/ENRICHER from the source alone, read the result against the shipped documents, and asked which of the two was wrong; eight times it was the code. Every one broke a rule this repo had already written down, and in four the file carrying the violation also carried the rule — so the durable half of each is a test, and in six of the nine that test walks a registry rather than a list. Five of the filings understated what was there and the entries in ROADMAP_HISTORY say so. No schema surface moved; all sixteen reference examples recompile byte-identical. See ROADMAP_HISTORY § 0.6.1.
- RM88 — ✅ shipped in
just-dna-enricher0.6.1 on 2026-08-18. The versioned publish path RM84 added could not notice that the version has not moved, so a recompile republished without aversion:bump overwritesdata/<name>/v<version>/with different bytes and the path names a version whose contents are not that version's. Not a defect in RM84 — the flat path always overwrote, and the versioned one is no worse than its own absence. Refuse unless--force, decided 2026-08-18 over warn-and-proceed and refuse-outright: the flag's existence is itself the claim that overwriting is sometimes right. Comparesartifact.digestoff the published manifest, so identical bytes are not a collision — a presence check would have refused the documented two-commit retry. Fails open on an unreadable remote: nothing established a collision, so nothing asserts one. The entry's own technical blocker was mispriced (the publish already costscreate_repo+ twoupload_folders), which left the policy as the only thing holding it for a release. The wider half shipped as an ask, not a fix:upload_foldernever removes, so a republish leaves a union of two releases on the flat path, and only a reader that starts frommanifest.artifact.filesis immune —delete_patternswas declined (one*.parquetwould delete every archived version's parquets, sincefnmatchcrosses path separators, and it cleans nothing nobody republishes). Asked in INTEGRATION_0_6 § 2.8. · from the 0.6 PT2 batch, lane D · also in ROADMAP_0_8 § RM84, INTEGRATION_0_6, ENRICHER, CHANGELOG - RM93 — ✅ shipped in
just-dna-compiler0.6.1 on 2026-08-18._check_study_effect_allelessits insideif variants:on the validate side and runs unconditionally on the compile side, so it never runs for the composition it was written for;_check_frequency_arithmeticis not called fromvalidate_specat all. Both reproduced:validate.valid=Truebesidecompile.success=False.@validate-refuses-all+@parity-by-check, and the same defect the 2026-08-07 audit fixed for two other checks —test_validate_agrees_with_compilepassed throughout because it lists the checks it knows. · from the code-first doc pass · also in COMPILER, CHANGELOG - RM94 — ✅ shipped in
just-dna-compiler0.6.1 on 2026-08-18. The compile-side_check_p_value_numre-run extendsall_warningswith noif w not in all_warningsfilter, which every neighbouring re-run has; reproduced as two byte-identical sentences inmanifest.compilation.warnings. Near neighbour of@no-rerun-with-countsrather than an instance — the message carries no count, so the copies agree, which is why it survived. · from the code-first doc pass · also in COMPILER, CHANGELOG - RM95 — ✅ shipped in
just-dna-format0.6.1 on 2026-08-18.MeasureBinRow._validate_measure_kindcallscheck_vocabfor its raising side effect and returns the uncanonicalized value, someasure_kind=copy-numberis stored ascopy-number(insidecontent_signature) and every subclass then rejects it against_EXPECTED_KIND. Violates@vocab-separator-slip, whose rule is store the declared member;_validate_measure_tilingone line above does it correctly. Two latent siblings inContribution/PgsRow. · from the code-first doc pass · also in SCHEMAS, CHANGELOG - RM96 — ✅ shipped in
just-dna-format0.6.1 on 2026-08-18.GeneMetricsRow.statusnames theResolutionRowvocabulary and enforces nothing (it is outsidereference._ALL_MODELS—@registry-completenessfrom the other side);GwasEffectRow._check_finiteguards two fields and blames both oneffect_size;startcarriesge=0on two of the five models with a position. · from the code-first doc pass · also in SCHEMAS, CHANGELOG - RM97 — ✅ shipped in
just-dna-enricher0.6.1 on 2026-08-18.gnomad._postandeutils._getcallraise_for_status()outside thetry/exceptwithHTTPStatusErrorin neither retry list, so a 5xx escapes raw past handlers written to catchGnomadError/EutilsError— the exact repaircpic.pyandpharmvar.pycarry with its R2-13 narrative. Beside it,CpicClient.row_countbypasses its own_get.@client-exception-contract. · from the code-first doc pass · also in ENRICHER, CHANGELOG - RM98 — ✅ shipped in
just-dna-enricher0.6.1 on 2026-08-18. With--offlineand no cache,enrichwritesstatus=not_found, source=cachenaming a cache never opened, between two adjacent branches whose comments spell out why that is forbidden;gene_metricsdoes the same against agnomad_v4.1_constraintlabel it never consulted, and its test pins the status rather than the claim.@unreachable-not-absent, in the mode where the fabricated negative is guaranteed. · from the code-first doc pass · also in ENRICHER, CHANGELOG - RM99 — ✅ shipped in
just-dna-enricher0.6.1 on 2026-08-18.gene_metrics,clingenandliteraturejoin filenames ontospec_dirby hand instead of callingsidecar_path, so on aderived/module they write to the root while six other passes write underderived/— inconsistent inside one family, sincegene_validityuses the resolver. Produces the both-copies-present collision RM49 made an error.@sidecar-name-and-place. · from the code-first doc pass · also in ENRICHER, CHANGELOG
✅ The 0.7 build round — PROPOSAL_0_7.md decided, then built¶
The 2026-09-01 source-adoption round (RM163–RM168) lands in the same uncut 0.7.0 and is a second round rather than an addendum to the first — PROPOSAL_0_7_PT2 is its record. Its shipped items are indexed here, beside the twelve; RM164 parked and is filed under Deferred to a later minor since 2026-09-11, and RM171 — the spin-off it filed — shipped on 2026-09-03.
- RM70 — ✅ shipped in 0.7.
requires_callablewasVariantRow-only, so a star-allele module could not record the assumption CPIC states only in prose: a position it did not call is reference, which is literallyrequires_callable=falseand is what a*1call rests on. The optional tri-state column now sits onHaplotypeRowandPharmVariantRow— the two PGx tables that name a locus, so the claim is about a position the row states — and not onDiplotypeRow, which names a star-allele pair and where the same column could only restatehaplotypes.csvone table over.callable_fromdeliberately did not travel: a proof is required and where the proof lives are different axes. No compiler change was needed (the parquet schema and the reverse writer both derive their columns from the model), andreference_examples/cyp2c9_warfarin_grch37now populates all three states across both tables, which answers the PGx half of a consumer's ask for the column populated somewhere real. Not gated on RM65/RM66's caller VCF: those wait on what a caller emits, this on what a curator asserts. · from DOGFOOD_0_6_FINDINGS § D2 (F11) · also in PROPOSAL_0_7, ROADMAP_0_8 (departure note), SCHEMAS, COMPILER, REFERENCE_EXAMPLES, USE_CASES, CHANGELOG, CONSUMER_SUGGESTIONS_HISTORY § S32
⏳ Open, no release decided — ROADMAP.md § Active items¶
Four items as of 2026-08-21 (RM103's manifest half, RM108 and RM110 here, plus RM117's observability half indexed under its own session below), and the heading was kept while it was empty. Three of the four — RM110, RM103's manifest half and RM108 — shipped on 2026-08-31 in the uncut 0.7.0; RM117 is the one still open, and the rows below carry their own status. The count in this sentence is dated on purpose: it says what the decision round left, not what is open now, and the ✅/⏳ on each row is what answers that. It held six until the 2026-08-21 decision round, whose whole content was that every one of them was a decision nobody had made: RM102 closed outright (→ ROADMAP_HISTORY), RM122 parked on demand (→ the deferral file), RM117 narrowed to its free half, and RM103 split, with the refusal moved to ROADMAP § The 1.0 cleanup. What is left is four minors whose shape is settled and whose release nobody has argued — a different thing from what this heading used to hold, and worth the distinction: two of the six were never design-blocked, one by a test that already pinned the answer and one by a record that held no incident. Items whose release nobody has argued yet belong
here rather than in a ROADMAP_0_8/ROADMAP_1_0 file. Nothing is open under this heading as of
2026-09-11 — RM164 was the last, and its section moved to the 0.8 file the day someone asked which
150+ items were open without a release; the heading stays because the allocator writes a new
reservation under it. And the section exists because there was nowhere to index one — every other heading names a release or a terminal state, so RM88 and RM89
would have been filed into a document this index could not point at, which is the exact failure this
file was written to make impossible. Both have now left it: RM89 the next day, closed by the
consumer answer it was waiting on, and RM88 in 0.6.1 once the policy it was really blocked on was
decided. Both stay indexed under their release below, because an item that shipped is exactly what
this index exists to still be able to find — and the heading stays for the next item filed before its
release is argued.
Five of the rows below arrived at once, out of a batch of six: RM163–RM168, the 2026-09-01 source-adoption round. RM168 shipped the same day and is indexed under the 0.7 build round above. They answer one question — what else should we adopt as enrichment sources, besides CIViC and PubMind — and they were unusual for this heading in that none of them had been probed when they were filed. Each stated its measured half (a table kind with no provider, a snapshot's actual contents, a number from a probe already run) separately from its candidate half, and none asserted a licence.
All six were probed the same day, and decided with the maintainer that evening — the round is PROPOSAL_0_7_PT2, which is a record rather than a plan and wins over the entries below. Five build inside the uncut 0.7.0 and RM164 parks on a measured negative, having spun off RM171, which shipped two days later. The keeper from the round: five of the six entries said something their own probe contradicted, and four of the six verdicts the proposal drafted were then overturned in the maintainer pass — so an unprobed entry is a question, and a probed one is still only a proposal.
- ✅ RM89 — SHIPPED in
just-dna-compiler+just-dna-enricher0.6.0 on 2026-08-17, the day after it was filed.upload._REQUIREDdemanded all three ofweights/annotations/studies.parquetwhile RM2 made the SNP core optional four releases ago, so a table-only module could not be published by this tier at all — seven of sixteen reference examples, measured.fmr1_cgg_repeatwas the instructive one: it hasstudies.parquetand lacks the other two, so the rule was "not all three", not "no SNP core", and the obvious repair (exempt a module with novariants.csv) would still have refused it. Same class as RM55's_INTEGER_KINDS. Its open question was the consumer's, asked with RM84's two and answered with them in S35:_find_lead_tableprobes one lead-family parquet and that singlefs.existsis their "is this a module" test, so manifest-plus-at-least-one-parquet is the consumable rule. Answering it found the larger half, which they reported and probing widened:_ALLOW_PATTERNScontained no 0.4 family and no derived-fact table either, so relaxing_REQUIREDalone would have publishedmanifest.json+ README with no data — and sincemanifest.artifact.filesattests each parquet by name, sha256 and size, eight more examples were publishing an artifact whose statedartifact.digestthe uploaded bytes could not reproduce. 15 of 16 wrong,sources.parquet— the licence table — dropped every time it existed. Built as: the allowlist derived from the now-publiccompiler.ARTIFACT_PARQUETS(@fieldnames-from-modelone tier out), plus three positive rules — the plan carries everything the manifest attests,weights.parquetnever travels alone (the consumer's_EXPECTED_WITH_WEIGHTS), at least oneLEAD_PARQUETSmember. An absent or unreadable manifest withholds, keeping RM84's four version reasons intact. Re-measured: 16 of 16 publish, all 16 digests verify. · from the 0.6 PT2 batch, lane D · motivating case S35 · also in CHANGELOG, ENRICHER, COMPILER, ROADMAP_0_8 § RM84
⏳ Deferred to a later minor — ROADMAP_0_8.md¶
- RM16 — authored PRS weights. Not derivable, so a full-cost authored table. Re-parked on 2026-09-13: the blocker is the shape, not the demand. Demand is answered — RM188's round-2 skim found 540 weights hand-transcribed out of a supplementary table (
dianguan0105), and an author with a corpus in a familiar shape is the demand that decides whether a format is adopted. What is unanswered is how weights combine, what reference distribution the score is stated against, and whether a percentile travels with it. Its unpark condition needs restating: read as "a consumer that reads authored weights", it gates on a tool that cannot exist until the table does — the one circular gate found by the parking-condition sweep. One axis at two operators with RM28: weighted-sum here, boolean there, enumerative already shipped indiplotypes.csvand covering the small-arity cases both would serve. · also in SCHEMAS, PROPOSAL_0_5, ROADMAP_0_8 § RM188, ROADMAP § trackers - RM23 — predictor scores (
predictions.csv). Both blockers unmoved: per-transcript grain, and the acquisition measurement. Licensing is not the blocker. · also in CLAUDE.md - RM28 — meta-conclusions, the predicate half only. Parked on a corpus. The general injected-cofactor mechanism was dropped on 2026-08-13 as never-earned; each class gets a plain column on demand. The corpus has four entries now: CIViC's 209 multi-variant profiles (RM174), ClawBio's warfarin branch, Kulminski's APOE ε4 subdivision by linked TOMM40/APOC1 markers (filed 2026-09-13 by the maintainer — the first entry where enumeration succeeds and the schema still complains: eight patterns fit
haplotypes.csv+diplotypes.csvlikeapoe_epsilon, but the haplotype spans three genes against a required single-valuedDiplotypeRow.gene, so it compiles only by choosing between a findable symbol and an honest locus label, and only under an unverified phase assumption — the pressure is on the subject, not the combiner, which argues a locus-keyed subject would settle it where a predicate would not), and — from RM188's round-2 roster — SNPedia's genosets, a boolean grammar over genotypes that nests and self-references, extracted intozhaofengli/snappy'sgenosets.json. Unlike the first two it was written for consumer genetics in general rather than falling out of one domain, which makes it the first entry where both the condition and the conclusion side are published at scale by one source. Still parked: the operator distribution and nesting depth are a count off a committed file and have not been run, andreference_examples/apoe_epsilonalready answers the two-variant case without a predicate, which is the boundary any count must beat. SNPedia's CC BY-NC-SA 3.0 US is not the obstacle a first reading made it — established terms, adoptable as an unsellable share-alike module (USE_CASES § 2e). One axis at two operators with RM16 — boolean here, weighted-sum there, enumerative already shipped indiplotypes.csv; decide where the combining rule lives once, but keep the items separate. · also in COMPILER, REFERENCE_EXAMPLES, PROPOSAL_0_5 § G3, ROADMAP_0_8 § RM188 - RM56 (the policy) — withhold / worst bin / point estimate, as a closed vocabulary. Gated on real caller output; grain undefined on purpose.
- RM65 (the coordinates) — gated on a real repeat-caller or CNV VCF, or a consumer report. Would take RM43's lane from three tables to five. The 2026-08-14 round supplied the corpus half of that evidence —
cyp2d6_structuralandfmr1_cgg_repeat, filed as evidence rather than as defects — and left the caller-output gate exactly where it was. - RM66 — one repeat locus, several motifs; the key cannot say which count the thresholds describe. Same prerequisite as RM65, and
fmr1_cgg_repeat's AGG interruptions against a(gene, repeat_unit)key are now the worked case. -
RM67 — polyploid / partially-phased genotypes. Not work — a documented divergence, numbered so it is findable and not re-probed. Unchanged by the 2026-08-14 round, which changed only the message: a polyploid call used to be refused with a bare restatement of the grammar, so a deliberate limit read as a syntax error; the refusal now says in-line that two alleles is a decision and that VCF 4.4 §7.2 permits more. The five 0.6 dogfooding findings the ledger classes surface rather than fix — the repair is itself a design decision, so each entry carries the candidates and why each one fails. Found by the probes of DOGFOOD_0_6.md on 2026-08-13 and filed on 2026-08-14 by the round that fixed the rest; the ledger is DOGFOOD_0_6_FINDINGS.md, whose closing table maps finding to unit to pull request.
-
RM73 — ✅ closed on 2026-08-16, both halves, the root item. The phase boundary. Authoring had no end, so nothing could say a module was finished. RM45 had already built almost all of it for another purpose —
verification.jsonbinds the authored bytes and the compiler drops the block on any mismatch — so what shipped is one optionalClosureblock on that document, ajust-dna-compiler closecommand, and a warning when a compile publishes none. No new file, no new binding, no new proof-of-work: the closure sits outsidepow_digest's payload, so closing re-mines nothing and every attestation written before it still verifies. Deliberate by design (validatestays read-only — a mark left by whatever ran says only that something ran), signable with the existing Ed25519 key, refusing an invalid spec but never a warning. Measured: all sixteen reference examples compile byte-identically before and after being closed, and all sixteen now ship a closure with a test that fails loudly when an authored edit outdates one. The enricher's merge had to learn to carry it — the never-clobber trap a third time, afterSourceRow.datasetanddraft_digest— and it drops rather than re-binds a closure whose bytes have moved, since only the author may make that claim again. What is left is the promotion, not a half: requiring a closure to compile is major-only (P8) and blocked — ROADMAP_1_0 § RM73 (gate half), because reverse cannot re-emit the document, so under a gatecompile → reverse → compilerefuses on step 3. The probe that found it is the reusable half: warnings feed no digest and no signature, which is why the identical asymmetry has been free since RM45 and why the gate is what gives it a price.
The provenance half, shipped the same day and the one the sprouts were actually asking for. A flat CSV row records nothing about how it came to be, so every check needing that had guessed: a drafting provider hashes the table it wrote, projected onto the column its own cross-check later reads, and stamps SourceRow.draft_digest; the check recomputes it and skips only on a conjunction of this release and nothing moved. Scoped to the checked column, not the row — a drafted module always has edited rows, since genotype is a stub the human must fill, so a row hash would never match. Closed two tautologies nobody had filed (CPIC/allele_function, ClinPGx/pgx_evidence_level, the latter already stamping the marker nothing read), made the skip per-leg in enrich_pgx so PharmVar still runs, and deleted RM4's strict per-row audit along with the mode ladder under it. The classification is derived, never typed. · from the RM72 read-through, 2026-08-14 · also in CHANGELOG, CLAUDE.md, COMPILER, ENRICHER, SCHEMAS, ROADMAP_1_0, the create-module skill
- RM80 — ✅ shipped in 0.6.0, retro-filed from a downstream consumer report: annotations.parquet is not unique on variant_key and never could be (poly-effect is real), and the authored column that decides which call an annotation applies to was in no column. genotype is now carried and keyed on — carrying it without keying would let two genotypes sharing a conclusion collapse onto a row naming one of them, turning a missing answer into a wrong one. Reverse learned to read which of three keyings an artifact carries. · from CONSUMER_SUGGESTIONS § S29 · also in CHANGELOG
- RM68 — a drafting provider on a non-GRCh38 module: refuse, or strip to the rsID. The warning shipped in 0.6 (enrich.source_build_mismatch); the behaviour is open. Refusal makes a GRCh37 module undraftable; stripping drops the 36 CPIC defining variants that have a position and no rsID. Probably dissolved by RM15. · from DOGFOOD_0_6_FINDINGS § D2 (F1)
- ✅ RM70 — shipped in 0.7; the entry moved to ROADMAP_HISTORY and this line is the pointer left behind. Its row is in § The 0.7 build round above.
- RM71 — ✅ SHIPPED in 0.7 (2026-08-28; it sits under the 0.7 deferrals below because that is where its entry lives, not because it is open) — a drafted genotype stub must be written from alleles the file does not carry, emitted once to stdout and not re-requestable. Every legal home is also the wrong home; the real question is where an author does the work. · from DOGFOOD_0_6_FINDINGS § D4 (D4-3)
- ✅ RM72 — SHIPPED in 0.6 PT2 (2026-08-17); the entry stays here, where the reasoning is, rather than being copied into the shipped list. The remainder of D4-1 after six members were wired: four blocked on the printed "Writes nothing" contract of check-identifiers/check-acmg, two deliberately reserved (gene_disease_validity, dosage_sensitivity), one open question about read-only surfaces, and one about the merge rule — merge_records is newest wins, per check, so an offline re-run downgraded a real subjects=2 findings=1 verdict to skipped=offline. Taken into 0.6 PT2 on 2026-08-16: the four are wired unconditionally (a --attest flag makes the record optional, and an optional record is ambiguous between not run and ran without the flag); merge_records stops letting a skipped replace a ran, on the function's own docstring argument one step further out; and the reword is three sites, not the printed-contract surface the entry feared — 37 sites carry a form of the promise but the other 34 are a different promise (hint/lookup write no authored cell, validate stamps no closure), and the create-module skill annotates neither command being changed (verified before shipping: its rows for both commands carry no such annotation, so it needed no edit). The two reserved members did not move; each gained a line saying it is reserved, and so did every wired one. Built with one thing the proposal did not anticipate: the skip-does-not-displace rule needed a condition, existing_still_binds, because an answer over authored bytes the author has since edited is not an answer the document may keep asserting — without it, literature's deliberate skip-on-changed-citations became a stale finding again, undoing an earlier round. · from DOGFOOD_0_6_FINDINGS § D4 (D4-1) · also in ENRICHER, PROPOSAL_0_6_PT2
The five filed on 2026-08-16 out of MODULE_LIFECYCLE.md, which mapped the second
pass and found that nothing had ever described it. They were that document's closing "open questions"
section until they were numbered — the shape this repo has twice found to be a backlog nobody reads, so
the section is gone and these are the whole of it. Of its seven questions, one dissolved into a
documentation fix (the trust rule's reader is a catalog, S34 — corrected in SCHEMAS.md and in
manifest.py's own comment) and one was decided: a review stamp is an attestation of zero changes,
so un-closing the module is correct. That decision is what produced RM86 — settling the format side
sent someone to read what the catalog does with the result, which turned out to be the sharper half.
- RM82 — ✅ shipped in 0.6 (2026-08-17), as
integrity.newline_normalized_file_entrybehindcompiler.authored_input_entries; measured: 7 of the 16 reference examples re-bound and 9 did not (a binding moves only where an authored file really carries\r\n— and it is the machine-written half of the corpus that does, sincecsv.writerterminates with\r\n), two of them dropping four attested check records each, and noartifact.digest/content_signature/source_signature/resolution_signaturemoved anywhere. The attestation binds raw bytes, so normalizing line endings un-closed a module without a cell changing. Decided 2026-08-16: normalize\r\n→\nbefore hashing and stop there — no loader, no parse, which is what separates it from the content-aware binding RM45 refused. Costs a one-time re-attest of everymodule_hashin existence (soft: a stale attestation warns and is dropped);manifest.inputs[]deliberately does not follow. Sighted once before from the round-trip side in DOGFOOD_0_6's lane plan. Taken into 0.6 PT2 on 2026-08-16, with the fact that decides the implementation:module_bindingisartifact_digestandsize=stat().st_sizeis inside the hashed listing (integrity.py:80-83,:106-112), so normalizing the digest input while reporting the on-disk size still moves the binding on exactly the CRLF files — the naive fix is a no-op that looks like one. A separate normalized entry builder, reporting the normalized length, used by the binding and nothing else; not anormalize=flag onfile_entries. · from MODULE_LIFECYCLE § 6.2 · also in MODULE_LIFECYCLE - RM83 — ✖ CLOSED, not shipped, on 2026-08-28, in the commit that landed RM124 and not before. Dissolved rather than argued down: both halves stopped existing once derived tables became pure build products. The refresh half's problem was that re-deriving a sidecar meant deleting it and losing the curator's rows — now there is nothing inside a sidecar to preserve, so
rmcosts nothing. The drift half's problem was that detecting an upstream revision was that same delete — now it is an ordinary operation and §5.1's canary fires from it. The blocking sub-question is answered rather than deferred: the tier never has to tell a curator's edit from the source's last answer, because the edit is recorded by construction. Nothing named in the entry is built — no--refresh, no proposed table, no diffs file. The residue is a flag on the command that already derives,enrich --rederive, shipped in 0.7 under RM128 and composing with its transaction so a baseline exists for the diff;rmplus a re-run stays silent and correct because nothing holds both sides. · from MODULE_LIFECYCLE §§ 5.1, 6.3 · also in MODULE_LIFECYCLE, CONSTITUTION (the amendment) - RM84 — the HuggingFace discovery path carries no version, no digest and no manifest fetch, so the identity used to detect "the module changed" is a property of the reader (the consumer app's own package version), not of the module. Half of it is ours:
upload.upload_modulewrites the flatdata/<name>/layout. Joint, and the consumer's half is already agreed in writing — S34 §4 says they will follow a version segment if the publisher grows one. Had noSnand noRMnbefore this entry. Our half taken into 0.6 PT2 on 2026-08-16: it is one line (upload.py:139,path_in_repo=f"data/{name}"), and the decision is to write both —data/<name>/v<version>/beside the flat path, which keeps meaning latest, so neither side waits for the other and nothing already published has to move.v<version>verbatim rather than a barevN, since a bare major segment collides two patch releases at one path. The one open thing is theirs: whether their fsspec scan matchesv0.6.0. Answered in S35 on 2026-08-17 — onlyv-plus-integer, and the HuggingFace branch has no version fallback at all, so no spelling is read on this path today andv<version>verbatim stays. A nested subdirectory does not disturb their scan, by construction (fs.lsat one level, neverfs.findor a**glob). Both fixes are theirs and unscheduled; the segment spelling is settled. ✅ Our half shipped in the 0.6 PT2 batch (lane D):plan_uploadreadsidentity.versionout ofmanifest.jsonand plans both paths (the versioned one is a subdirectory of the flat path, not a sibling),upload_modulewrites both, and a version that is absent/unreadable/unstated/not SemVer falls back to the flat path alone and says which of the four (UploadPlan.version_unknown_reason) rather than constructingvNone;--dry-runprints both. The one field is read from the JSON and gated withis_valid_versionrather than validated throughread_manifest, so an unrelated manifest defect cannot withhold a version that is legible. Twoupload_foldercalls, so two HuggingFace commits, not one — recorded rather than papered over, flat first because it is the path anything reads today. It refuses nothing new:manifest.jsonis in the allow-patterns and not in the required set, so a directory without one is still publishable. Two consequences documented rather than fixed: re-publishing without bumpingversion:overwrites the versioned copy — filed 2026-08-17 as RM88, a policy question and not RM84 — and the nesting is the second half of the ask. Building it also surfaced RM89: this publisher refused a table-only module outright, so seven of the sixteen examples could not be published at all — shipped 2026-08-17, unblocked by the same S35 that answered the two questions above. The row stays here because the consumer's discovery half is still open; the segment spelling is not. · from MODULE_LIFECYCLE § 6.8 · also in CONSUMER_SUGGESTIONS § S34, ENRICHER, PROPOSAL_0_6_PT2 - RM85 — ✅ SHIPPED in 0.7 (2026-08-29:
currency.check_dataset_currency, a sixthenrich()check attested asdataset_currency, with--verify-datasetsas its switch). A source-drafted module needs a refresh pass when the source moves and a paper-grounded one needs an evidence pass when the literature does;SourceRow.datasetrecorded the release and nothing acted on it. The tempting repair — a column stating the origin — is refused by RM71's argument one table over (it restatesdatasetand rots wheredatasetis maintained), so what shipped reads rather than writes. Three things the entry did not settle were decided in the build: only ClinVar has a live release label this tier can read in the namespace it records, so one probe ships in a derived registry and every other source is honestlyunsupported; comparability is its own withhold, sinceclinvar_dataset_label's digest form and its stated-date form name one release space in two spellings; andstrictrefuses over the superseded set alone, never over an unchecked one, or--offline --strictwould be impossible forever over something no author can edit. It is--rederive's cheap neighbour and ENRICHER says so where an author reads it. Had noSnand noRMnbefore its entry. · from MODULE_LIFECYCLE §§ 0, 7 · also in CHANGELOG, ENRICHER, AGENT_NOTES - RM86 — ✅ CLOSED 2026-08-20, the downstream half of the review-pass decision, read out of the registry tree rather than assumed. Filed as an ask, RM27's shape — delivered into the registry's own inbox on 2026-08-16 as their S10, S11 and S12, and all three came back. The publish succeeds and the same-module carve-out is real code (so §6.6's long-standing claim is confirmed, not merely believed) — that half never moved. The pre-flight, which answered
would_publish: falsefor that same publish, is fixed in their 0.16.0: a newpublished_elsewherecarries the hits under a different(namespace, name)and the verdict quantifies over it, so it now agrees with the gate. The closure reaches downstream as of their 0.16.0 + 0.17 —verification.jsonis inRECOGNIZED_SPEC_FILESso rebuilds carry it, inDERIVED_FILES/manifest.derivedsodownload(include_inputs=True, layout="split")returns it, andmanifest.verificationis projected onto the module-detail response withclosedre-bound by their own compile; still out ofSIGNATURE_INPUTS, which is what made recognising an unread file safe.authorshipreaching no projected field is answered as policy, not repaired — payload, deliberately, so their card never renders an author's claim beside the server's own. The question that was ours is decided by their S12 reply and is now §6.6's advice: areviewsrow by default; anauthorshipentry when the record must travel inside the module or be signed; both when both matter — the version-bump path being legal and costing a version number and nothing else. Closed by re-reading their tree at 0.18.3, prompted by S46 fromjust-module-creator, who measured the recognition half from outside and reported §6.6 as stale — the composite sentence had gone stale as a unit, which is why §6.6 now states the findings separately with a release on each. · from MODULE_LIFECYCLE § 6.6 · also in MODULE_LIFECYCLE §§ 6.6, stages 7–8, CONSUMER_SUGGESTIONS_HISTORY § S46, and../just-dna-registry(reachable asjust-dna-marketplace, a symlink) CONSUMER_SUGGESTIONS_HISTORY §§ S10–S12 - RM87 — ✅ shipped in 0.6 PT2 (lane B). A one-to-many expansion pairs K authored genotypes with N loci, and only the member whose alleles can carry a genotype can match it; the others were well-formed rows asserting a pair the module never wrote, and nothing in the artifact marked them (
locus_indexwasresolution.csv-only). Cost a consumer 3,762 false pathogenic findings, caught before rendering. 0.6 shipped the artifact-level half (expanded_keys/expanded_rows+ the read-side contract); PT2 shipped the row-level half. Filed to correct a premise, not to defer one: S33 ruled the parquet column out as a 1.0 conversation because it movesartifact.digest, and P3 plus the 0.6 cost amendment say the opposite — a stamped compiler-managed column is minor-legal and the cheapest class of change there is. Two columns, not one:locus_indexalone is0on both a non-expanded row and an expansion's first member,locus_countalone cannot line a weights row up with itsresolution.csvrow, and aboolforecloses the ordinal under P5. What landed (0.6 PT2 is the design record): both declared throughstamped_identity_field, which gained a keyword-onlydefault=for it (exclude=True, so nocontent_signaturemoved on any module — a plain field would have repeatedVariantRow's grandfathered defect);locus_countdefaults to 1, not 0, or the predicate is not a predicate; stamped at the expansion loop inresolution.pyand at its twin in the deprecatedresolver.resolve_variants, since digest parity between the two paths is a guarantee;_build_weightsmaterializes both asUInt32in its hand-listed record dict and polars schema;_freeze_identityoverwrites an authored cell of either name; reverse prefers the stored column over its encounter-order recompute and keeps the recompute for a pre-column artifact. The round-trip test nobody had written now exists — a multi-member0..N-1sequence survivingcompile → reverse → compile, plus stored-vs-recompute agreement across the corpus. Measured:artifact.digestmoved on the nine reference examples carrying avariants.csv(the proposal predicted twelve; seven of the sixteen are table-only) and nothing else moved anywhere. · from CONSUMER_SUGGESTIONS § S33 · also in SCHEMAS (the consumer join contract), COMPILER § Resolution
🔒 Deferred to 1.0 — ROADMAP_1_0.md¶
- RM15 — build-agnostic identity & multi-build support. A major because it changes the semantics of
variant_keyand of every coordinate — not for digest reasons. The build-naming half shipped as RM19. Not RM48, which is one-way and authoring-time. · also in USE_CASES, SCHEMAS, COMPILER, PROPOSAL_0_5 - RM52 — the upgrade procedure. Release-blocking by charter. Decided 2026-08-13: the 0.6 batch owes no per-item ledger rows — that is premature decision-making, and the obligation belongs at 1.0.
- RM55 (the removal) — the integer columns and the integer tiling semantics. The only genuinely major part of the three-release route.
- RM69 —
resolution_signaturemoves across the round trip on a non-GRCh38 module carrying a positional table. Not a Principle 7 breach —resolution.csvis a derived sidecar, and P7's own next sentence ("the artifact is missing a field, not the spec") is the diagnosis. Moved from the 0.7 deferral file on 2026-08-27: the repair is minor-legal, but RM15 is the only route to it, so the deciding release is 1.0 — and the 0.7 file promises nothing in it waits on a version. It is the third membership class that file's header now names, and RM15 lists it as something building RM15 closes. · from DOGFOOD_0_6_FINDINGS § D2 (F8), measured in § D6 · also in ROADMAP_0_8 (departure note), MODULE_LIFECYCLE § 6, PROPOSAL_0_6_PT2, CHANGELOG, ROADMAP_HISTORY -
RM81 — one artifact spells a genotype two ways:
weights.parquetsplits it intoList(Utf8), the 0.4-family tables keep the authored string, and a consumer joining both to one VCF meets two representations of one concept. A retype of a published column, so major-only; the parallel-column workaround is refused as two spellings in one table (thevrs_iddesync shape). The reader half already shipped in 0.6 asalleles.split_genotype, the one public leaf every tier calls. Open question for the major: unify up (split everywhere) or down (verbatim everywhere). · from CONSUMER_SUGGESTIONS_HISTORY § S30 · also in SCHEMAS, CHANGELOG -
Plus the unnumbered items in ROADMAP § The 1.0 cleanup, which stays where it is.
✖ Closed as an item¶
- RM10 — declarative inheritance expectation. Folded into RM28 on 2026-08-13: it is an injected cofactor (family structure arrives at query time, exactly like ancestry), so designing it separately would fix a shape for one class before the axis exists. Reasoning lives in ROADMAP_0_8 § RM28. · also in USE_CASES, PROPOSAL_0_5
— Not format scope¶
- RM7 — evaluation / report-card schema. Per-sample results are a measurement, so this is a consumer contract (
just-dna-lite). Listed only so it is not mistaken for format scope. · also in USE_CASES, COMPILER, PROPOSAL_0_5