Skip to content

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.csv optional, 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 as just-dna-compiler reference. · also in ROADMAP, SCHEMAS, COMPILER, CHANGELOG
  • RM9 — recommended colour / icon palette (RECOMMENDED_COLORS / RECOMMENDED_ICONS). · also in ROADMAP, COMPILER, CHANGELOG
  • RM11 — doi provenance column on StudyRow. · 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-derived variant_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>C and Ensembl's X:634690 AGAG>AG are the same 2 bp deletion, and string comparison called it not_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: source named a link in resolution.csv and a licensed source in sources.csv, compared by string equality. Closed by ResolutionRow.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 by draft --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 → compile moved content_signature for a module authoring curator/method per row, because reverse re-emits the value under defaults: and the hash read the CSVs before defaults applied. Closed by resolving defaults: 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 in defaults.curator hashed 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_key gave a GRCh37 module's locus a GRCh38 VA while variants.csv gave it a coordinate key. Closed by injection — the loader tells each row the build via a PrivateAttr, so the declaration stays in module_spec.yaml alone and reaches no CSV, parquet or digest. Per-row and per-CSV ("service row") declaration were both rejected, with reasons. Carried the correction that content_signature was not build-independent: it now hashes a non-default genome_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 a 0.5.1 label 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_quality on VariantRow, clinical_context on DiplotypeRow. Dissolved the draft --population refusal. · 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-twin keeps both), per locus because XG and SPRY3 straddle a boundary. Carried a false-absence fix in frequencies.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 --offline on pgx/draft. PharmVar is build-only — its key is personal and non-transferable, so no publish and no ensure_*. Two prerequisite defects fixed on the way (LICENSE.txt never published; the layout constants imported from a [dev] builder) and two integration defects found by probing (PharmVar's GRCh37-first coordinates; CPIC's gene.chr). · also in CLAUDE.md, ENRICHER, CHANGELOG
  • RM39 — ✅ shipped in 0.5.1: enrich_dosage_sensitivity was the only pass with no offline parameter, 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, --offline on dosage. An injected curation_text still wins — that is not egress. · also in ENRICHER, CHANGELOG
  • RM40 — ✅ shipped in 0.5.1: enrich() computed the MintResult the 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 by EnrichmentResult.vrs; None when the pass did not run, never a coverage of zero. · also in ENRICHER, CHANGELOG
  • RM41 — ✅ shipped in 0.5.1: compiler._load_csv_rows was 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_rows is public (old name kept as an alias), compiler.load_spec_variants does the build injection and re-stamp, and verify_acmg_sf/check_identifiers accept spec_dir= beside variants=. · 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 reassign policy.stop. Closed by net.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_resolved is all() over variants.csv, hence vacuously true for a table-only module, and a catalog following the documented trust rule served trusted: true for 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_PHRASE pins it meanwhile). The fix is one additive integer — resolution_subjects — beside the flag, the same parts-not-conveniences pattern as vrs_alleles. Do not make the flag None-able, and it does not retire UNJOINABLE_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 as Stats.weights_rows — publishing it beside the flag is still right, because that equality is a property of the materializer rather than a contract and Stats is 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 one compile refuses; their layout stays transport-only (flatten on upload, re-split on download). The byte-attestation half of S26 shipped as manifest.derived in 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 — enrich on 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), make derived/ canonical (two supported layouts, and reverse emitting a tree older compilers in the same major cannot read), extend it to authored tables (two legal homes for variants.csv, so the ignored copy is invisible). Shipped as just_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_tables had to be extended into the subdirectory or a single fixed name blinds it just as a tree walk would, and manifest.derived carries 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.csv as a second spelling of sources.csv in 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_signature is rows, source_signature is facts, manifest.derived is transport-only. What cannot come along is sources.parquet (inside artifact.digest, read by name) and the manifest.sources key — both removals, both major — so the 0.x tail reads licensing.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, so record_source_terms/merge_sources_file take 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 release clinvar_draft stamps into the licence row, both sides calling one shared label function) and re-keys that check on a mode ladder — strict audits 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 is Number=A, so a scalar column cannot describe alts=<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 under strict, 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: enrich crashed 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 --offline limitation, 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-tainting gene_validity source layer. Probing moved the stated key twice — mode of inheritance joins it (59 ClinGen gene/disease pairs differ only there) and so does submitter, 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_panel was 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 same clin_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_spec as well as compile_module, each model gaining stamped parquet-only variant_key and authored_ident plus alts on PharmVariantRow/HaplotypeRow as data, not identity. No resolution.parquet; reverse rebuilds the lookup table from the positional parquets, which P7 forces. pgx_slco1b1_simvastatin went from nine all-null rows to 12 / 21178615 / T / A,C. One deviation kept: the stamped fields are Field(exclude=True), or content_signature moves on all five positional modules — which leaves VariantRow'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 into manifest.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 from literature, one each from pgx and vrs mint, and rsid↔coordinate inside enrich, a check that turned out to be unreachable from enrich() 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_TERMS constant: 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 a studies.csv row may name no variant at all. The bin cites, the citation table describes, which is what stops StudyRow'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 a heteroplasmy.csv module stating four thresholds and citing nothing was silent while the same thresholds on repeat_alleles.csv were 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 fills pmid, because filling it would make the existence check compare NCBI with itself. The live hazard was the accepted spelling, not the refused one: PMC 3110566 used 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 why mt_heteroplasmy and htt_repeat_expansion are the only two modules whose content_signature moved 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_field only — callable_element/quality_element are reserved, not built: callable_from and quality_from can name a multi-valued field too and no module does, and an authored column on variants.csv is full cost under the 0.6 amendment. Additive whenever a real case arrives (P3), the names held in RESERVED_NAMES_0_4 so they survive the one-way door, and everything reading VCF_POINTER_COMPANIONS is 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-schema reference and not describe <kind>, and largest'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_structural and fmr1_cgg_repeat are 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 unresolved row. 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 unhandled ga4gh.vrs error 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: * passes ga4gh.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 — chrom rejects chrM while a normalizer in the same package accepts it. Widening only, and it did not blind RM48: chrM:16600 is 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 above 0.3; float32(0.9) lands below 0.9, so narrowing an authored 0.9 upper 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 on measure_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 genotype description on 2026-08-14 — the pipe form was not in the authoring contract at all, while the validator accepted it and phased round-tripped. The 0.6 replacement wording overclaimed in its turn: C|C loads, 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 gene is ;-multi-valued and both readers treated the cell as one symbol — 396 of 16,087 snapshot rows, and --gene VKORC1 silently dropped the 3 rows of rs17886199 (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, because gene sits outside PharmVariantRow's dedup key and the copies collide where drugs' copies do not; and picking from the cell has no rule to pick by, since the pharmacogene is first in CYP3A5;ZSCAN25 and second in PRSS53;VKORC1. What shipped is the CPIC gene.chr move — write the member the request selects, and otherwise withhold and name the genes the cell held. Also: skipped_unidentified was counted before the --gene filter, inflating "records the source could not identify" by the rest of the database (R2-11); and a location fixture keyed "location" where cpic.defining_variants reads "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 reaches haplotypes.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._get wrapped only shape failures, so an exhausted retry ladder left a raw httpx.HTTPStatusError that walked through both of enrich_pgx's per-leg handlers and took PharmVar's answer with it (R2-13) — the retrying half is _request now and the translation sits outside it, since wrapping inside would make retry_if_exception_type a 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_drug is caught (R2-4), so an optional message-enrichment call can no longer discard a finished draft, and the bool | None tri-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. And spec_genome_build's deliberate raise no longer tracebacks out of draft/draft-panel (R2-2): _DRAFT_PRECONDITION_ERRORS names 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 --strict and reached manifest.sources inside the block its own signature covers. SourceRow is not an AuthoredModel (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 — ModuleSpecConfig is 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; and stub_template's printed guarantee ("an unreplaced stub cannot compile") is now asserted over every DRAFTABLE kind, 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 pasting GT is the obvious first guess. 0/1/1 was 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 reaches PharmVariantRow free, since the grammar has lived on AuthoredModel since 0.5. Second half: RM63's own replacement wording was false, since VariantRow(genotype="C|C") loads and 1|1 is an ordinary phased homozygote; the printed describe output 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 pass LiteralSequenceExpression'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_build no longer answers True for the two inputs refget_accession raises on (R2-10 — the old reasoning imported a spec-layer default into the identity layer, and every other build gate in vrs already 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_id makes both vrs_id columns ga4gh: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_count counted the whole table while the citation_existence record 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 and literature.csv keeps 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 bin pmids 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, else continuous where a quantised-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 corpus content_signature moved. _INTEGER_KINDS/_DENSE_KINDS/_CONTINUOUS_GAP_KINDS became inputs to that default table and stopped deciding a rule; _DENSE_KINDS had 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 | None sits beside modifier_cn, the one genuine int, read through effective_modifier_copy_number (is not None, not or — SMN2 = 0 copies is a real dosage), both-set an error, _KEY_FIELDS keying on the effective value so the key never holds two spellings. modifier_cn is 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 — with FRACTIONAL_MEASURE_PHRASE byte-identical. One deviation from the proposal, taken deliberately: the fractional inference fires only against a quantised default, not "whatever its kind's default says". activity_score is fractional by nature (cyp2d6_structural bins 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 only quantised states 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 weight where 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 — weight is positive=protective while a GWAS beta is positive on the effect allele. So the effect gets gwas_effects.csv → .parquet, the seventh derived-fact table, and weights.parquet.weight stays 100% authored. Modelled from the real REST payload, which the download TSV would have got wrong: orPerCopyNum/betaNum are separate mutually exclusive keys, not the TSV's one ambiguous column; betaUnit is free text and is the reason the table exists; betaDirection is about the measured trait and is kept off direction (P5 — increasing HDL and LDL are both increase); riskAlleleName is rs4149056-? when no allele was established, which parses to null and is counted, not dropped. No coordinates on the row — the payload has none. rsid is inside the fact set, inverting CLINICAL_ASSERTION_FACT_FIELDS because 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 a pvalue: 0.0 underflow was dropping whole associations (189 → 195 rows once withheld instead). A prediction the measurement refuted: link-caching was expected to collapse the 1+2N budget and saved nothing — 382 requests, zero hits — hence --no-study-facts. First source with no named licence; commercial_use stays None and warns rather than gating. Corpus: adding the table moved nothing; hfe_hemochromatosis then 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 its content_signature did not move. · from CONSUMER_SUGGESTIONS § S36 · also in SCHEMAS, COMPILER, ENRICHER, MODULE_LIFECYCLE, CHANGELOG
  • RM91 — ✅ shipped in just-dna-format + just-dna-compiler 0.6.0 on 2026-08-17. StudyRow has carried effect_size + effect_measure since 0.3 with no effect_allele, so every study row in the format stated a magnitude relative to nothing — while VariantRow has had the column since the same release precisely because ref/alts plus 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 iterates variants only, 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 both validate_spec and compile_module (@parity-by-check). It reads resolved evidence only and withholds on everything else — a StudyRow has ref without alts, so {ref} alone would flag every study of a non-reference allele, which is most of them; unresolvable is unknown, not wrong. StudyRow.ALLELE_COLUMNS is ("effect_allele",) and the omission of ref is the design: AuthoredModel's rule is sequence columns that are the claim, never a column that points at a variant, and it names StudyRow.ref as its own example of the second kind. _allele_verdict's resolved half was factored into _resolved_allele_verdict, not copied. Measured, prediction exact: artifact.digest moved on 10 of 16 examples — the ten carrying a studies.parquet — and content_signature on none. Round-trip test watched failing with only the reverse fieldnames entry removed. · from CONSUMER_SUGGESTIONS § S36 · also in SCHEMAS, COMPILER, CHANGELOG
  • RM92 — ✅ shipped in just-dna-format + just-dna-compiler 0.6.0 on 2026-08-17. effect_size has effect_measure beside it; VariantRow.weight is a bare float | None reading "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") on ModuleSpecConfig, copied to ModuleManifest, advisory exactly like license: out of both identity halves and dropped by reverse_module. The field it deliberately lacks is the design — no precedence rule, nothing saying "use the GWAS effect where weight is 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: weight is authored zero times in this repo — four of nine variants.csv-carrying examples have the column, 42 rows, every cell blank. measure_tiling is 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's verification.json, which is pinned. Closed a gap in passing: license/panel/authorship are 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-enricher 0.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 a version: bump overwrites data/<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. Compares artifact.digest off 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 costs create_repo + two upload_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_folder never removes, so a republish leaves a union of two releases on the flat path, and only a reader that starts from manifest.artifact.files is immune — delete_patterns was declined (one *.parquet would delete every archived version's parquets, since fnmatch crosses 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-compiler 0.6.1 on 2026-08-18. _check_study_effect_alleles sits inside if 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_arithmetic is not called from validate_spec at all. Both reproduced: validate.valid=True beside compile.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_compile passed throughout because it lists the checks it knows. · from the code-first doc pass · also in COMPILER, CHANGELOG
  • RM94 — ✅ shipped in just-dna-compiler 0.6.1 on 2026-08-18. The compile-side _check_p_value_num re-run extends all_warnings with no if w not in all_warnings filter, which every neighbouring re-run has; reproduced as two byte-identical sentences in manifest.compilation.warnings. Near neighbour of @no-rerun-with-counts rather 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-format 0.6.1 on 2026-08-18. MeasureBinRow._validate_measure_kind calls check_vocab for its raising side effect and returns the uncanonicalized value, so measure_kind=copy-number is stored as copy-number (inside content_signature) and every subclass then rejects it against _EXPECTED_KIND. Violates @vocab-separator-slip, whose rule is store the declared member; _validate_measure_tiling one line above does it correctly. Two latent siblings in Contribution/PgsRow. · from the code-first doc pass · also in SCHEMAS, CHANGELOG
  • RM96 — ✅ shipped in just-dna-format 0.6.1 on 2026-08-18. GeneMetricsRow.status names the ResolutionRow vocabulary and enforces nothing (it is outside reference._ALL_MODELS — @registry-completeness from the other side); GwasEffectRow._check_finite guards two fields and blames both on effect_size; start carries ge=0 on two of the five models with a position. · from the code-first doc pass · also in SCHEMAS, CHANGELOG
  • RM97 — ✅ shipped in just-dna-enricher 0.6.1 on 2026-08-18. gnomad._post and eutils._get call raise_for_status() outside the try/except with HTTPStatusError in neither retry list, so a 5xx escapes raw past handlers written to catch GnomadError/EutilsError — the exact repair cpic.py and pharmvar.py carry with its R2-13 narrative. Beside it, CpicClient.row_count bypasses its own _get. @client-exception-contract. · from the code-first doc pass · also in ENRICHER, CHANGELOG
  • RM98 — ✅ shipped in just-dna-enricher 0.6.1 on 2026-08-18. With --offline and no cache, enrich writes status=not_found, source=cache naming a cache never opened, between two adjacent branches whose comments spell out why that is forbidden; gene_metrics does the same against a gnomad_v4.1_constraint label 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-enricher 0.6.1 on 2026-08-18. gene_metrics, clingen and literature join filenames onto spec_dir by hand instead of calling sidecar_path, so on a derived/ module they write to the root while six other passes write under derived/ — inconsistent inside one family, since gene_validity uses 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_callable was VariantRow-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 literally requires_callable=false and is what a *1 call rests on. The optional tri-state column now sits on HaplotypeRow and PharmVariantRow — the two PGx tables that name a locus, so the claim is about a position the row states — and not on DiplotypeRow, which names a star-allele pair and where the same column could only restate haplotypes.csv one table over. callable_from deliberately 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), and reference_examples/cyp2c9_warfarin_grch37 now 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-enricher 0.6.0 on 2026-08-17, the day after it was filed. upload._REQUIRED demanded all three of weights/annotations/studies.parquet while 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_repeat was the instructive one: it has studies.parquet and lacks the other two, so the rule was "not all three", not "no SNP core", and the obvious repair (exempt a module with no variants.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_table probes one lead-family parquet and that single fs.exists is 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_PATTERNS contained no 0.4 family and no derived-fact table either, so relaxing _REQUIRED alone would have published manifest.json + README with no data — and since manifest.artifact.files attests each parquet by name, sha256 and size, eight more examples were publishing an artifact whose stated artifact.digest the 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-public compiler.ARTIFACT_PARQUETS (@fieldnames-from-model one tier out), plus three positive rules — the plan carries everything the manifest attests, weights.parquet never travels alone (the consumer's _EXPECTED_WITH_WEIGHTS), at least one LEAD_PARQUETS member. 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 in diplotypes.csv and 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.csv like apoe_epsilon, but the haplotype spans three genes against a required single-valued DiplotypeRow.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 into zhaofengli/snappy's genosets.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, and reference_examples/apoe_epsilon already 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 in diplotypes.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_structural and fmr1_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.json binds the authored bytes and the compiler drops the block on any mismatch — so what shipped is one optional Closure block on that document, a just-dna-compiler close command, and a warning when a compile publishes none. No new file, no new binding, no new proof-of-work: the closure sits outside pow_digest's payload, so closing re-mines nothing and every attestation written before it still verifies. Deliberate by design (validate stays 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, after SourceRow.dataset and draft_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 gate compile → reverse → compile refuses 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_entry behind compiler.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, since csv.writer terminates with \r\n), two of them dropping four attested check records each, and no artifact.digest/content_signature/source_signature/resolution_signature moved 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 → \n before 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 every module_hash in 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_binding is artifact_digest and size=stat().st_size is 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 a normalize= flag on file_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 rm costs 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; rm plus 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_module writes the flat data/<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 no Sn and no RMn before 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 bare vN, since a bare major segment collides two patch releases at one path. The one open thing is theirs: whether their fsspec scan matches v0.6.0. Answered in S35 on 2026-08-17 — only v-plus-integer, and the HuggingFace branch has no version fallback at all, so no spelling is read on this path today and v<version> verbatim stays. A nested subdirectory does not disturb their scan, by construction (fs.ls at one level, never fs.find or 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_upload reads identity.version out of manifest.json and plans both paths (the versioned one is a subdirectory of the flat path, not a sibling), upload_module writes 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 constructing vNone; --dry-run prints both. The one field is read from the JSON and gated with is_valid_version rather than validated through read_manifest, so an unrelated manifest defect cannot withhold a version that is legible. Two upload_folder calls, 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.json is 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 bumping version: 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 sixth enrich() check attested as dataset_currency, with --verify-datasets as 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.dataset recorded 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 restates dataset and rots where dataset is 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 honestly unsupported; comparability is its own withhold, since clinvar_dataset_label's digest form and its stated-date form name one release space in two spellings; and strict refuses over the superseded set alone, never over an unchecked one, or --offline --strict would 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 no Sn and no RMn before 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: false for that same publish, is fixed in their 0.16.0: a new published_elsewhere carries 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.json is in RECOGNIZED_SPEC_FILES so rebuilds carry it, in DERIVED_FILES/manifest.derived so download(include_inputs=True, layout="split") returns it, and manifest.verification is projected onto the module-detail response with closed re-bound by their own compile; still out of SIGNATURE_INPUTS, which is what made recognising an unread file safe. authorship reaching 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: a reviews row by default; an authorship entry 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 from just-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 as just-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_index was resolution.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 moves artifact.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_index alone is 0 on both a non-expanded row and an expansion's first member, locus_count alone cannot line a weights row up with its resolution.csv row, and a bool forecloses the ordinal under P5. What landed (0.6 PT2 is the design record): both declared through stamped_identity_field, which gained a keyword-only default= for it (exclude=True, so no content_signature moved on any module — a plain field would have repeated VariantRow's grandfathered defect); locus_count defaults to 1, not 0, or the predicate is not a predicate; stamped at the expansion loop in resolution.py and at its twin in the deprecated resolver.resolve_variants, since digest parity between the two paths is a guarantee; _build_weights materializes both as UInt32 in its hand-listed record dict and polars schema; _freeze_identity overwrites 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-member 0..N-1 sequence surviving compile → reverse → compile, plus stored-vs-recompute agreement across the corpus. Measured: artifact.digest moved on the nine reference examples carrying a variants.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_key and 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_signature moves across the round trip on a non-GRCh38 module carrying a positional table. Not a Principle 7 breach — resolution.csv is 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.parquet splits it into List(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 (the vrs_id desync shape). The reader half already shipped in 0.6 as alleles.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