Skip to content

Read an .exar1 out, classify every sequence on a scanner, and name CMRR's spectroscopy suite - #17

Merged
bbfrederick merged 29 commits into
mainfrom
exar1-driver
Sep 9, 2026
Merged

bbfrederick merged 29 commits into
mainfrom
exar1-driver

Conversation

@bbfrederick

@bbfrederick bbfrederick commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Everything on exar1-driver since #16 merged: 29 commits, mostly .exar1
work, plus the sequence catalog growing to cover CMRR's spectroscopy suite.

Reading an archive out

siemens-protocol-tool archive <file.exar1> is the reading half of the
.exar1 support, where exar is the writing half. exar/inspect.py composes
archive, patch and geometry into hierarchical JSON: the console's
Preview summary under the labels a printout uses, the whole ASCCONV block
nested by the structure its key names describe, the slice geometry, and the
prescription links between scans — which a printout does not record at all,
since a linked scan prints exactly like an unlinked one. list, sequences
and check now take an archive wherever they take a PDF.

Format corrections, and three of them were silent

  • The live set is the head changeset's element map, not the instances that
    changeset touched. Right on a file written in one save and catastrophically
    wrong otherwise: a 97 MB whole-scanner export read as 21 instances of
    31164
    , with no error anywhere. Every other corpus archive gains the same
    four scaffolding nodes under the fix, which is what had made the folder tree
    look flat.
  • A step's ObjectId is not unique. A copied protocol keeps the source's,
    so resolving the running order through an archive-wide object index hands two
    programs the same instance — 75 step elements never walked, 27 protocol
    documents never read, and 39 of 67 pairs held different protocols, one
    being eja_svs_laser beside eja_svs_press. The check that should have
    caught it was comparing object ids, 435 against 435, and so was passing
    vacuously. A GUID-space error cannot be checked in the space it occurs in.
  • The folder tree is on the root node, keyed in two GUID spaces at once,
    and the structure document states it in both directions — so the two can now
    be checked against each other.

What a scanner said

Six rounds of import-and-export classify all 117 corpus sequences: 68
consistent, 46 imported and greyed out, 3 that refuse to import
(blade, ciss, medic, all licensed product options). The counts are
exhaustive and disjoint, and the final round rebuilt them into one 53-scan
program that all printed — so the split predicts behaviour in a build it was
not derived from.

sProtConsistencyInfo.tBaselineString == "ConversionNeeded" is the first
thing found that anticipates a greyed-out protocol offline: 43 of 43
scans carrying it were greyed out, 0 of 53 consistent scans carry it. It is
sufficient, not necessary — three greyed-out scans lack it — and inverting
that is the expensive error.

The catalog

CMRR's spectroscopy suite is now eleven sequences over six kernels. The two
semi-LASERs are split (Deelchand's from Auerbach's, one character apart in the
kernel); single voxel is told from CSI by the phase-encoding matrix it does
not print; MEGA-PRESS no longer claims MEGA-semi-LASER; and the three
diffusion-weighted builds separate from their parents on one Special-card
label, Diffusion weighting, which is on 6 of 1487 corpus scans and nothing
else. Every attribution here came from the protocols' owner — two were derived
from the card-and-kernel pairing, put to him to check, and confirmed.

Corpus

The scanner returns ship as examples, and so does
allcustomer_20260909.{exar1,pdf} — one scan per customer sequence installed
on the scanners, 35 protocols, every one current. Twelve sequences get their
first console-authored copy in examples/.

Test design

The unrecognized rate is retired. It measured the corpus rather than the
catalog: per export the legitimate figures run 4.2% to 50%, and the aggregate
cleared 5% only because large fully-named protocols diluted the rest. What
replaces it sweeps the whole corpus and subtracts what each pin claims, so an
export excluded from both pins leaves a scan standing — falsified three ways
rather than assumed to bite.

Checks

Full suite green: 3103 passed, 26 skipped. black, isort and codespell
clean.

A note on history

The branch was rewritten to drop outbound/ — six generated .exar1 archives
plus a manifest, 6.3 MB, committed before .gitignore covered the directory.
They are evidence for the scanner round trips rather than source, and are kept
outside the repository. One commit, Ship two archives to load on the scanner and re-export, held nothing else and so no longer exists; nothing else
changed, and the tree is otherwise identical to what was pushed before.

🤖 Generated with Claude Code

bbfrederick and others added 29 commits September 4, 2026 21:00
An archive read as 1/1800th of itself and reported no error. archive/P1/
Investigators.exar1 is a 97 MB whole-scanner export written by twelve
successive CopyProgramsPipeline saves; reading it yielded 21 instances of
31164, one program of 499, and 317 KB of JSON. Nothing raised, and the result
looks exactly like a small archive.

_live_instances resolved the live set by filtering InstanceChangeSet to the
head changeset. That table records what each changeset *touched*, so on a file
written in one changeset it is the whole tree and on any other it is the last
save's delta. The live set is the head's element map instead: a ChangeSet
names a BaseElementMapId holding the tree as of an earlier point and a
DeltaElementMapId holding this save's changes, each a flat run of 32-byte
element/instance GUID pairs, the delta superseding the base element by
element. 28109 plus 3056 is every Element row: 499 programs, 61 directories,
8217 scans, 1953 pauses. generate._head_map_id already wrote into that map;
nothing read from it.

Every other corpus archive gains the same four nodes -- two EdfDirectory and
their two EdfString labels, created in an earlier changeset and never touched
again -- which is precisely what made the folder tree look flat. One gains 99:
NAV_optionscan_P1_loadtest holds its program twice, both named
NAV_optionscan_P1 (2), under Investigators/Frederick and Investigators (2)/
Frederick, so the console disambiguates a repeated directory name as it does a
program name and that file really was imported twice.

With the versions right the hierarchy is recoverable, and it is not where the
node structure suggests: an EdfDirectory carries no Children in any archive
and an EdfProgram no ParentElementId. It is in the root EdfStructure's own
content document under ParentDirectoryId, keyed in two GUID spaces at once --
a directory under its ObjectId, a program under its Element_id. Resolving
every key in one space finds all 61 folders, misses all 499 protocols, and
reads as a tree of empty folders rather than as a lookup in the wrong space.
directory_parents, parent_of and path_of read it; the recovered path agrees
with the printed one component for component, differing only at the root.

Surfacing the duplicate broke the driver in a way worth keeping: apply_protocol
paired against archive.steps, which flattens every program, so each scan name
appeared twice against a printout naming it once and the guard against pairing
a repeated name to the wrong copy refused all 31 -- a driver that writes
nothing, reported as a clean run. build.target_steps now picks one program, a
lone one or the one program_name reads out of the printout's header.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
siemens-protocol-tool archive <file.exar1> is the reading half, where exar is
the writing half. exar/inspect.py composes archive, patch and geometry and
establishes nothing new about the format beyond the observations below; the
document is not a parsed printout and does not pretend to be one.

Three things in it have no counterpart on the PDF side. The whole ASCCONV
block, nested by the structure its key names describe. The prescription links,
which a printout cannot record at all -- a linked scan prints byte-identically
to an unlinked one. And who supplied the sequence: the protocol names its
binary under %SiemensSeq% or %CustomerSeq%, which is Siemens stating the
owner rather than this tool inferring it, and it carries the same standing as
VB17A's printed SIEMENS:/USER:. Verified over 1031 scans in 31 archives with
no contradiction -- no binary under both prefixes, every %SiemensSeq% binary
the catalog knows is one of its kernels, every %CustomerSeq% one it knows
matches a third-party signature. It is carried into the catalog under the
archive's own spelling rather than translated, so an evidence line quotes what
the file says. On Potpourri_P1 that resolves all 18 scans where the PDF, which
prints only the kernel, leaves four unaccounted.

Indices nest as decimal string keys rather than JSON list positions, for two
reasons that both come from the file: an array node also carries an
__attribute__ member, so it is not a pure sequence, and the arrays are sparse.
Literals are kept as spelled, since the console writes 0x1 for some flags and
1 for others. ASCCONV also spells an index two ways -- alTE[0] and a bare
sComment.0, 2214 assignments over one key family -- and a tokenizer built on
the bracketed form alone declines the rest silently, which is why the nesting
test counts leaves against the flat table.

list, sequences and check now take an archive wherever they take a PDF, and
--program picks one protocol out of a file holding several. What those
commands see of an archive is the console's Preview summary, roughly forty
parameters a scan rather than the several hundred a page prints, so a policy
written against a printout mostly misses; the complete set is the ascconv tree.

Two claims elsewhere in CLAUDE.md did not survive the corpus sweep this makes
cheap. The empty-Kind relation is not one export's quirk but 1248 of 1440
relations across 18 of 51 programs, and it is not the running order mirrored
into the relations map: only 2 of K23EB's 19 distinct pairs are adjacent in
the chain. And CMRR is not the only sequence that stamps a build --
rslh_ep3d_vaso writes vx_ep3d 7b674ae rslh6.0, with no semicolon, so build_id
returns it whole and it can never match a gate.

The navigator .prot rule is settled in the direction its own note left open.
On console-authored scans it is exception-free: all 53 pair alFree[15] = 2
with an _ABCD_* name and = 1 with the bare one. T09/T19 are not
console-authored, which was the proposed explanation -- NAV_optionscan_P1
holds them at 2, so the move to 1 is the driver's, exactly as in the
driver_loadtest scan. Two returns therefore disagree on identical input, which
puts the counterexample on the import side rather than the authoring side.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cmrr_mbep2d_se is CMRR's multiband EPI spin echo, supplied by the protocols'
owner. It is the third member of a family whose other two the catalog already
names, and the largest unnamed third-party binary in the shipped corpus at 282
scans across 89 protocols in the whole-scanner export.

Which detector can name it depends on which file you have. A Numaris/X page
prints the kernel, so cmrr_mbep2d_se and cmrr_mbep2d_diff both read as epse
there and only the Special card can separate them; an .exar1 prints the
sequence file name and settles it outright. The entry carries both routes --
binaries for the archive, base_binaries plus special_all for the page -- and
they agree on every corpus scan that has both.

Deriving the card route needed the archive to label the page. Joining the 18
archive/PDF pairs on scan name gives each printed Special card the binary that
actually wrote it, and the fingerprints then separate cleanly: Triggering
scheme is on all 17 SE scans and on none of the 23 diffusion ones, nor
anywhere in their 22-label union, while Disable B1 control loop and PF omits
higher k-space are on every diffusion card and no SE one. That is a method
worth reusing -- the printout says what a card holds and the archive says
whose card it is, and neither file answers both questions alone.

54 shipped scans match, all epse; an archive confirms 30 of them as
cmrr_mbep2d_se and none as anything else. 52 move off cmrr-epi, whose "EPI
package, multiband off or not printed" was the vague but correct answer for
the CMRR field maps. The other two are literally named cmrr_mbep2d_se and
cmrr_mbep2d_se_3echo and were reported as diffusion, because with multiband on
they print the generic MB card on the spin-echo kernel. Priority 30 rather
than 20 is what corrects those; condition count says the opposite, as it did
for the package entry.

The residual risk is stated in the note: Triggering scheme is an option rather
than a property of the binary, so a diffusion protocol with it enabled would
read as SE from a printout alone. Unobserved across the corpus, and the
archive names the binary when there is one -- which is what makes "prefer the
archive where both exist" a rule with teeth rather than a preference.

Regenerating the snapshots surfaced a gap this change did not cause:
examples/XA60/driver_loadtest.pdf shipped without a golden snapshot, so it was
covered by neither the golden test nor the accounting one, and that test had
been skipping for want of it. Its snapshot is added and its five MGH scans
join the pinned unaccounted product, which now reads over four Potpourri
exports rather than three.

Also carried in this commit, and not the author's work: spice-epsi gains the
binaries ZPL_RG_EPSI_FID_v1h and ZPL_RG_EPSI_SE_v1b. Those were authored in a
parallel session and were sitting in the working tree when catalog.json was
staged whole. They name 20 scans in the whole-scanner export that the entry's
four earlier spellings missed. Recorded here rather than split out because the
commit is already published; the lesson is to stage by hunk when two sessions
share a tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Several parameters exist only on diffusion scans -- the number of directions,
the diffusion scheme, the b values -- and the console prints them on a card of
their own. That makes the card a structural property of the sequence where
every Special-card label is a checkbox someone can clear, which is a better
thing to identify a diffusion scan by than the multiband card it shares with
BOLD and spin echo.

cards_all is the clause. It requires a scan to print a named card, matched on
the group at the *head* of the printed title rather than the page at its tail:
a title is "<group> - <page>", so Special is a page of the Sequence card while
Diff is a group with pages. VE11C splits diffusion into Diff - Body,
Diff - Neuro and Diff - Composing against Numaris/X's single Diff, so matching
the tail finds Body and Neuro and misses all 26 VE11C diffusion scans -- which
is the first thing this got wrong, and it reported them as printing no card at
all rather than failing.

Like base_binaries it gates the Special-card route only, never binaries, for a
sharper reason than the kernel gate has: a scan read from an .exar1 prints no
cards at all, so gating the binary route would make every archive stop
matching. Both routes are exercised -- a page identifies cmrr_mbep2d_diff by
"prints the Diff card", an archive by the binary with cards=['Preview'].

cmrr-mb-epi-diffusion gains cards_all: ["Diff"]. All 96 corpus scans it
matched before print one and nothing that is not diffusion prints one, so
nothing is reclassified: the snapshot diff is 96 pure insertions of one
evidence line and no deletions.

Two corrections to the entry added in the previous commit. Its priority of 30
was unnecessary and the reason given for it was false -- cmrr-mb-epi-se names
three Special labels against diffusion's two, so it already outranked it on
weight at equal priority, and "condition count says the opposite" was simply
not true. It is back at 20, and CLAUDE.md now says to read rank() before
reaching for a priority, because a priority added on a wrong reading is one
nothing will ever question. Diffusion instead moves to 25, deliberately above
it: with the card clause the two tie on weight, so the winner would otherwise
fall to file order, and if a diffusion protocol ever enables the Triggering
scheme option the SE entry keys on, the card it cannot help printing is the
better evidence. That closes the residual risk the SE note recorded.

Not folded in: the twelve cmrr-epi scans that print a Diff card --
ABCD_dMRI_DistortionMap, DWI_98Dir, one named cmrr_mbep2d_diff -- stay where
they are, because claiming them means loosening special_all, which is a
separate judgement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The two files name a sequence differently: a Numaris/X page prints the kernel
mpres, an .exar1 prints the sequence file name eja_svs_mpress. cmrr-megapress
knew only the kernel, so it matched every printout and no archive at all --
427 scans in the whole-scanner export were reported third-party on the owner
statement alone, with nothing saying which sequence they run.

They are the same sequence rather than two, joined archive-to-printout on the
five scans in Frederick_P2 where both spellings are visible: same scan names,
kernel mpres, and both Special-card labels on every one. So this lists the
second spelling beside the first, as cmrr-slaser already does for sead and
slaser, rather than adding an entry.

No golden snapshot moves, because the kernel route already covered every PDF
in the corpus. The whole gain is on the archive side.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CMRR ships two of them, by different authors, and the catalog held one entry
covering the pair. Both attributions come from the protocols' owner:
Deelchand's is now dkd-semilaser and Auerbach's is cmrr-semilaser.

They are easy to confuse and hard to confuse, in that order. The kernels are
one character apart -- a page prints slaser for Deelchand's and slasr for
Auerbach's -- but the cards share exactly one label out of 9 and 39:
Deelchand's prints GOIA/FOCI and FA AutoCalib, Auerbach's the OVS and VAPOR
blocks. The three labels this keys Auerbach's on appear on every one of his
scans and on none of Deelchand's. Nothing was mis-attributed before, because
slasr matched no entry at all; the eja scans were simply unidentified.

dkd-semilaser also gains the archive spelling svs_slaser_dkd beside the two
kernels, so one sequence is now named by all three of the ways the files spell
it -- sead on a VE11C page, slaser on a Numaris/X one, svs_slaser_dkd in an
.exar1. That is what makes its 421 scans in the whole-scanner export resolve,
against 7 for Auerbach's.

The pair also shows the two files disagreeing about what they can resolve. An
archive names eja_svs_slaser and eja_csi_slaser apart; a page prints slasr for
both and their cards share 39 of 40 labels, the one difference being an option
that may simply be off. So the archive declines the CSI variant and the page
claims it. Rather than assert a split the corpus cannot support on one scan of
each, the family is worded without "single-voxel" and the note says so.

INVESTIGATOR_UNACCOUNTED drops from 73 to 70 and loses slasr from its kernel
list -- the pin behaving as its comment says it should, coming down when an
attribution arrives from the owner rather than because anything was written to
make it fall.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Twelve minutes serially, five at -n 8, with identical results -- 2558 passed
and 18 skipped either way, verified at -n 8 and -n auto before this landed.

pytest-xdist joins the dev extra, which is what CI installs, and -n auto goes
on the whole-suite step alone. Not on the targeted steps above it: those tee
their output and grep it for "skipped", because a skip in the OCR, front-end
or .exar1 suites means the fixtures were missing rather than that the tests
passed. Parallel workers interleave that output, so the guard would be reading
scrambled logs to answer the one question it exists to ask.

It stays out of addopts for the same reason -- a developer running one of
those files by hand should get the serial output the greps expect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
eja_svs_slaser and eja_csi_slaser share the kernel slasr and 39 of the 40
labels on their Special cards, the one difference being an option that may
simply be off. So an .exar1 named them apart and a page did not, and
cmrr-semilaser claimed both -- which the entry's note recorded as a cost
rather than a defect, for want of anything better.

There is something better, and it is what single voxel means: whether the scan
phase encodes. Scan Res. A >> P and R >> L are absent on all 27 single-voxel
spectroscopy scans in the corpus and 8 or 16 on all 6 CSI ones, with nothing
against, and they are printed only on Resolution - Common.

parameters_at_most is the clause, and it is the first that reads a printed
value rather than the presence of a label. It is satisfied by absence as well
as by a value within the bound, because a sequence with no such setting prints
none; the bound is 1 rather than 0 on the owner's reading that a 1 x 1 matrix
would mean the same thing, which the corpus does not show. An unparsable value
is refused rather than assumed small. A label printed on several cards must
satisfy the bound on every one -- the same flattening trap the Position note
describes, met in the matching rules this time rather than in a reader.

Exactly one scan moves: eja_csi_slaser drops out of cmrr-semilaser, so the two
routes stop disagreeing and the entry earns "single-voxel" back in its family.
INVESTIGATOR_UNACCOUNTED goes 70 to 71 and keeps slasr with one scan under it
rather than losing it with three, because that CSI variant is still
unattributed and the pin should say so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
MEGA-PRESS and MEGA-semi-LASER are different sequences, per the protocols'
owner. cmrr-megapress matched on MEGA flip angle and Editing pulse BW, which
are what any MEGA-edited sequence prints rather than anything about this one,
so its card route also claimed three mslsr scans -- eja_svs_mslaser twice and
eja_csi_mslaser once.

base_binaries: ["mpres"] gates the card route to its own kernel. It costs
nothing: mpres is the kernel on both VE11C and XA60, and the binary route is
never gated, so an archive still resolves the sequence by its file name. The
three scans are unrecognized now, which is the right answer until someone
names them, and no mpres scan moves.

The shape generalises. Labels that describe a technique -- editing,
multiband, navigation -- are printed by every sequence using it, where labels
naming a sequence's own implementation are not. The CMRR multiband card had
this problem and is why base_binaries exists; this is the second instance, so
a two-label fingerprint of common parameters should be read as needing a gate
rather than as a signature.

INVESTIGATOR_UNACCOUNTED goes 71 to 74 and gains mslsr. That pin has now moved
in both directions in three commits -- down when Auerbach's semi-LASER was
named, up when its CSI variant was declined, up again here -- which is what it
is for. A count that only ever falls would be a target, and writing signatures
to make it fall is the one thing the attribution rule forbids.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two more attributions from the protocols' owner, and between them the eja
spectroscopy suite is now told apart three different ways.

cmrr-semilaser-csi is the chemical-shift-imaging variant of cmrr-semilaser and
the same author's. It shares that entry's kernel and all 39 of its
Special-card labels, so only the Resolution card separates them, and it needs
the exact complement of the bound that entry uses.

parameters_at_least is that complement, and deliberately not a negation:
absence fails there where it satisfies parameters_at_most. So "at most 1" and
"at least 2" partition -- a scan printing a 1 x 1 matrix goes to the
single-voxel entry alone. Two negations would have left a gap at 1 that both
entries claimed, on a value neither the corpus nor the owner rules out.

cmrr-mega-semilaser is the MEGA-edited semi-LASER that cmrr-megapress was
claiming until the previous commit gated it off. Its kernel mslsr is unique to
it, and its card is exactly the pair of techniques its name says: the MEGA
editing labels MEGA-PRESS also prints, over the semi-LASER refocusing block --
GOIA refoc. pulses, HS refoc. pulse N and R -- that MEGA-PRESS does not. One
label from each is what names the sequence rather than either technique, which
is the lesson the previous commit recorded, applied. The single-voxel and CSI
spellings share the entry rather than being split, because the owner named
them together.

Four golden scans move, all from unrecognized: three MEGA-semi-LASER and one
CSI semi-LASER. INVESTIGATOR_UNACCOUNTED returns to 70 and loses both slasr
and mslsr, having gone 73, 70, 71, 74 and back over five commits -- which is
what a pin is for, as against a bound that would only ever have been allowed
to fall.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three more from the protocols' owner. With them the eja spectroscopy suite
runs to eight sequences over six kernels, and it is where the catalog's
clauses divide the work cleanly: the card names the author, the kernel names
the technique, and neither is sufficient alone.

22 labels -- the VAPOR water-suppression delays, the spoiler and timing
controls -- are printed by every eja sequence, so a card fingerprint says only
whose implementation a scan runs. PRESS, LASER and STEAM are techniques anyone
may implement, so a kernel says only which technique. Each entry pairs three
of the shared labels with its own kernel.

Keying on a technique name would be reckless if Siemens shipped a sequence
using one, so a test asserts that every scan printing press, laser, steam,
slasr or mslsr anywhere in the corpus is an eja_ scan -- and the archives put
all of those under %CustomerSeq%, which is the scanner saying the same thing.

Eight golden scans move, all out of unrecognized: four PRESS, two LASER, two
STEAM. INVESTIGATOR_UNACCOUNTED goes 70 to 62 and loses those three kernels.

Auerbach's diffusion-weighted semi-LASER was named too and is deliberately not
here. eja_svs_slaser_diff appears 22 times in the whole-scanner export and
never in examples/, so an entry would be one nothing shipped could exercise
and test_every_shipped_signature_matches_something_in_the_examples would fail
on it, correctly. Widening the examples is the fix that rule names -- shipping
one of the seven DWS protocols that run it -- rather than relaxing the test or
letting the entry sit unverified. The attribution is recorded in CLAUDE.md so
it is not lost while the example is missing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The scanner rejected both archives from the previous commit. Each opened and
each navigated to Investigators/Frederick, where nothing appeared -- and in
scanner terms a Program is a protocol, so that is the program failing to
build rather than a program opening empty.

Two real defects turned up, and this is honest about what they explain,
which is: not necessarily this.

Content is addressed by hash, so rewriting a document re-addresses it and
strands the old row -- and appending is a loop, so a 96-scan program left 95
dead copies of its own document beside one live program instance. Every
console archive carries exactly one orphan, the placeholder branch's
structure content, and nothing else in 21 files. Archive.prune collects the
rest at write, taking what this library created *or displaced*: origin alone
keeps the seed's own program document forever, since that arrived with the
file and was stranded by editing it. A read and write with no edit between
still drops nothing, on all 20 corpus archives.

The five step-keyed maps were left in append order where every archive the
scanner has accepted keys them lexically -- which this file already said,
under "do not sort on re-encode", about the lists inside them. Newtonsoft
reads these into dictionaries and so probably does not care; matching costs
nothing and removes a difference from every known-good file.

Both now fail loudly: validate refuses either, three tests cover them, and
reintroducing each defect at runtime makes the checks fire. A test helper
that staged a multi-program backup was building its maps in running order
too, so it was staging a shape no scanner has been handed.

Neither defect is established as the cause. The 40-scan assembly that loaded
33 scans back went through this same code and carried both. Everything else
checks out against a console export -- folder tree, all five maps, ranks,
element types, changeset states, the element map, link field sets, Children
resolution, content hashing, and no $ref preceding its $id. What is left is
size, since the largest program any corpus archive holds is 74 and these are
96 and 117, or something about these particular protocols, which are by
construction the rarest sequences we have. A scanner is the only way to tell.

So the deliverable is now six files rather than two. gaps_1of4..4of4 carry
the same 96 sequences in programs of 25, well inside the range the console
is known to handle, and each opens with a control scan the scanner has
exported before -- so a chunk that appears holding only the control says the
other protocols were refused one by one, while a chunk that does not appear
says the program could not be built and rules size out. The two whole
archives are rebuilt with both fixes and kept, since if they load the
chunking was unnecessary.

All six validate clean with zero orphans and sorted maps, and every protocol
in them is byte-identical to the corpus scan it was copied from -- 117, 96
and 25/25/25/24, checked against every protocol in the corpus rather than
against the donor the manifest names.

Also noted while sweeping: tSequenceFileName can carry a subdirectory under
the owner prefix, and one scan spells it with a doubled separator. Four
binaries appear under both a bare and a subdirectory spelling, so counting
distinct values overcounts the sequences by four. Nothing is broken by it,
because sequence_owner splits on the first separator and header_of takes the
binary with rsplit -- correct by luck rather than design, and worth keeping
deliberately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 96 gap sequences went to the scanner as four chunks of 25. Chunks 2 and
4 imported; 1 and 3 were refused outright, same size, same build path, same
seed. So the size hypothesis this file was carrying is dead, and what is
left is which protocols are in them.

That is a harder failure than the greying-out rule describes. A scan the
console dislikes normally arrives and is greyed out, and scans whose
binaries are missing were simply dropped from the 40-scan assembly while the
program still built. Here nothing arrives: the folder is there and the
program is not.

The two that imported settle something else. All 49 protocols came back
byte-identical with the running order preserved and no scan missing --
including the 26 the console greyed out. So "inconsistent" is a verdict
recorded against a protocol stored faithfully rather than an edit to it, and
the write path is sound: what fails is the console's judgement of these
protocols, not our construction of them.

26 of 49 greyed out is itself worth recording. Each is a byte-exact copy of
a protocol some console authored, so consistency really is a property of the
whole parameter set in its context, and a protocol lifted out of the export
it was written in has lost that context. For the corpus's rarest sequences
that is the common case rather than the exception. The 23 that survived have
printouts now.

The retry is nine groups of six rather than two of twenty-four, so one bad
scan costs five others. The three hcp_mbep2d_* are grouped together on
purpose: they are already known to be refused whatever we write, so a known
failure is confined instead of taking six good scans with it.

The archives and the returned files are not committed -- inbound/ and
outbound/ are gitignored as of a26c78c, alongside loadtest/ and archive/.
The outbound files from the two commits before that are still tracked; say
the word and they come out of the index.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 48 stranded sequences went back as nine groups of six; six imported.
Groups 3, 4 and 8 were refused, so the blocker is confined to eighteen scans
and is not what it looked like.

It is not the exotic protocols. Group 4 is six small ordinary ones -- ciss,
three csi_*, two can_neuromelanin -- at 16 coils and one slice, while group
1's three hcp_mbep2d_* at 130-172 KB imported without complaint. csi_st
imported and csi_fid, csi_se and csi_slaser did not; se_mc imported and se
did not. Sweeping every ASCCONV key and XProtocol tag across the 38 accepted
scans and the 18 refused ones finds no key present in even two of the three
refused groups and absent from every accepted one, so there is nothing
offline to write a check against and bisection is the only instrument left.

Two things this file said need correcting.

"A protocol from an older CMRR build can be rejected on import, whatever we
write" was too strong. Sent on their own, all three hcp_mbep2d_* imported,
returned byte-identical, kept the running order -- and were greyed out. The
earlier assembly showed them not arriving; this shows the same protocols
arriving and being inconsistent. So the outcome is not a property of the
protocol alone, and the old-build reconciliation account no longer explains
both observations.

And the churn list was ASCCONV-only. fl3d_vibe and se_mc came back with
their parametric-mapping functor removed -- <Connection."c1"> losing its
T1mapFunctor/T2mapFunctor, EXECUTE emptied, sParametricMapping.* changed --
while BEAT and space had sCommonIterRecon.*, sPat.* and the derived scan
times recomputed. A diff reading only the ASCCONV block reports all four as
unchanged. 45 of 49 did return byte-identical, which is what makes the four
legible rather than lost in noise.

The archives are not committed; inbound/ and outbound/ are gitignored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The eighteen candidates went back as nine pairs. Six imported, and the three
refused are exactly one pair from each of the three refused groups:
{ZPL_RG_EPSI_FID_v2f, blade}, {ciss, csi_fid}, {jn_svs_special_ve11c,
medic}. So there is one offending scan per group of six, and six candidates
left. All eighteen returned protocols were byte-identical, with no repairs.

The pairs rule out two things on their own. csi_se and csi_slaser import
while one of ciss/csi_fid does not, and resolve, se and petra import while
one of medic/jn_svs_special_ve11c does not -- so it is neither stock versus
third-party nor the sequence family.

Repeating the key sweep against every scan now known to import, a 1067-key
vocabulary over three rounds, leaves blade as the only candidate carrying
anything unseen: sBladePara.*. That is weak. It is the corpus's only BLADE
sequence, so a unique parameter family is what it would have whether or not
it is the offender, and the other two pairs show nothing at all.

Eight more sequences came back consistent -- can_neuromelanin and its _pk
variant, csi_se, csi_slaser, resolve, se, petra and ZPL_RG_EPSI_FID_v2e --
which puts the corpus at 51 sequences with printouts that had none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bisection ran to singles. blade, ciss and medic are refused alone, in a
two-scan archive holding nothing but the control, so the cause is inside
those protocols rather than an interaction between scans -- a single-scan
program being the smallest possible test of that. ZPL_RG_EPSI_FID_v2f,
csi_fid and jn_svs_special_ve11c imported alone and clear their pairs.

What the search excludes is worth more than what it found. Against the 93
scans now observed to import, a 1067-key vocabulary, there is no ASCCONV key
or XProtocol tag the three blockers share and the accepted scans lack: ciss
and medic have none at all, and blade has only sBladePara.*, which is what
the corpus's one BLADE sequence carries whether or not it is the offender.
Sweeping values rather than keys turns up seven keys where all three hold
something unseen, and all seven are per-scan unique by nature -- alTR,
dRefSNR, lScanTimeSec, tProtocolName.

It is not size, coils, slices, sequence family, or stock versus third party.
csi_se and csi_slaser import while ciss does not; resolve, se and petra
import while medic does not; all three blockers are %SiemensSeq%. Nor is it
provenance -- petra and se appear only in the same unshipped whole-scanner
export and import fine.

All three are licensed Siemens product options, which is the leading
explanation and is not established, since petra is one too and imported.
Either way the protocol is the wrong place to keep looking: nothing in it
distinguishes them, so the next question is for the console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three sources describe .exar1: Tobias Rautenkranz's exar1-read
(gitlab.com/tobiasrautenkranz/exar1-read, GPL-3.0), the NeuroStars thread
"Parsing EXAR files", and a Stack Overflow answer. They independently
confirm the container, raw DEFLATE at wbits=-15, the EDF V1 header line, the
JSON beneath it, XProtocol in Data, SHA-1 content addressing, .NET
Guid.ToByteArray ordering, the seven tables, the FirstStepId/LinksFrom chain,
and that the printed Card grouping is absent from the archive. Nothing
already established had to change, which is worth stating plainly: the
reverse engineering holds up against independent descriptions.

Four additions, three adopted and one recorded.

The structure document states the folder tree twice. Beside
ParentDirectoryId it carries RootDirectoryId, SubdirectoryIds and
SubprogramElementIds -- the tree downwards, with the top named outright.
directory_children and declared_root read them and validate compares the two
directions. This is the one place a source would have saved real work:
reading the tree wrongly turned a 97 MB export into 61 empty folders and 499
orphan protocols and presented as a small file rather than an error, where
two independent statements of one tree make it a single failing line. They
agree on all 20 corpus archives and RootDirectoryId is the unique zero-parent
directory in each, so it is pure redundancy -- which is what makes it worth
checking. SubprogramElementIds is in none of the three sources; it turned up
on dumping the document once the others said where to look.

EdfDecisionStep is a seventh step kind and is now in STEP_KINDS. The corpus
has none, but the errors are lopsided: a kind that never appears costs
nothing, while omitting one drops its step from the running order and reports
the file as corrupt rather than as unknown.

Content.Format is the literal "DS" -- confirmed on all 20 archives rather
than adopted. InstanceChangeSet.State is 0 current, 1 change, 2 delete; the
corpus holds only 0 and 1, so delete is taken on their word and nothing
depends on it, the live set coming from the element map.

One correction to my own reading while doing this. I wrote that every archive
carries two EdfStructure nodes and that picking the first was luck. That was
a raw-table count read as a live-set count: the second belongs to the
placeholder branch and is not live, so the live set has exactly one. tree_root
now prefers the node declaring ParentDirectoryId anyway, since a reader
reaching the other would report a flat archive rather than an error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reading the Stack Overflow answer sent me back through the corpus, and the
sweep turned up a defect that has nothing to do with the sources: a step's
ObjectId is not unique, and we were reading it as though it were.

This file claimed copying a protocol inside a directory reuses the source's
step node -- "one element id per shared object id". It is the other way
round. The copy gets its own element and its own live instance and keeps the
source's ObjectId, so Frederick_P2 has 510 live step instances over 510
elements but only 435 distinct object ids, 67 objects carrying two apiece.

The running order is a chain of object ids, so resolving it through an
archive-wide object index hands both programs the same instance. 75 step
elements were never walked and 27 protocol documents never read, and 39 of
the 67 pairs hold different protocols -- one being eja_svs_laser beside
eja_svs_press, different sequences, with the wrong one returned. steps_of
now resolves each chain id against the program's own Children, which are
element ids, keeping the global index as a fallback no corpus archive needs.

_step_coverage exists to catch exactly this and was passing vacuously, for
the same reason: it compared object ids, 435 against 435, while 75 elements
sat in no running order at all. It counts elements now. The general lesson is
that a GUID-space error cannot be checked in the space it occurs in, and the
old claim had all three of its supporting checks phrased in that space.

No pinned count moved, which is worth stating: the twins mostly run the same
sequence, so the corpus totals were right by luck while individual scans were
not. Two tests cover it -- every live step walked exactly once by element,
and the laser/press pair each reading its own protocol.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Stack Overflow question links a shoulder protocol Siemens distributes
from magnetomworld, shoulder_4ch_flex.exar1. Every archive in the corpus came
from one site's two scanners, so this is the first independent file the
reader has met -- and it is not the same Numaris generation. Its baseline is
N4_VE11S_LATEST_20170215: .exar1 is not an XA format, and Numaris 4 spells
the baseline as one underscored token with no keyed fields at all.

Nothing had to change to read it. 33 steps in one program, the folder tree
resolving to Root/New Tree/Shouolder/Flex_4Ch/routine (the typo is the
file's), validate clean, and all 76 content blobs re-encoding to their stored
hash -- so the Newtonsoft serializer derived from XA60 reproduces a 2017
Numaris 4 file byte for byte. Read and write with no edit returns an archive
identical in every table, every content row, the running order and all 28
protocols. sequences names all 28 scans as stock Siemens, and one step is an
EdfPauseStep used as a section divider.

The slice-geometry model holds as well: 24 groups read, worst deviation of
the stored array from the recomputed one 7.1e-15 mm. That formula came
entirely from XA60 option scans, and a release eight years older agrees with
it.

Two differences. major_version returned empty, because the release is a token
rather than a field; it now reads both spellings, keyed field first, with a
narrow anchored fallback rather than a general search for a version-looking
token -- a loose pattern would give a confident wrong answer where the empty
string was merely unhelpful. And a VE11S protocol names its first XProtocol
block "MultiStep Controller" where an XA60 one leaves it unnamed; both carry
two blocks with the ASCCONV in the second, so it is a labelling difference
rather than a structural one. That block is what the Stack Overflow answer
printed, and reading it as a protocol document without parameters would be
wrong.

The file is not added to examples/. It is Siemens' to distribute and that is
not this layer's decision; CLAUDE.md names it so it can be fetched again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six rounds of import and export have now given every one of the corpus's 117
sequences a scanner verdict. 68 are consistent -- 53 of them gap sequences
that had no printout at all before, now covered by a single 53-scan export --
46 import and are greyed out, and 3 refuse to import: blade, ciss, medic. The
three counts are exhaustive and disjoint, which is what says the
classification is complete rather than merely large.

This round is what makes it trustworthy rather than circular. The verdicts
came from four rounds of differently-shaped archives; the fifth rebuilt them
into one 53-scan CORPUS_CONSISTENT and all 53 printed, while
CORPUS_INCONSISTENT returned all 41 protocols byte-identical with only its
anchor printable. The split therefore predicts behaviour in a build it was
not derived from. 53 scans is also the largest program this library has had a
scanner accept.

Six of the 21 catalogued sequences were greyed out: ZPL_RG_EPSI_FID_v1h,
ep2d_DE_pcasl_iPAT, ep2d_bold_MGH_tb, ep2d_se_VASO, mjd_mclean_flipback and
svs_slaser_dkd. Every one carries a signature because shipped examples
exercise it, and svs_slaser_dkd runs 421 corpus scans. So a signature, a
printout and hundreds of examples say nothing about whether a protocol lifted
out of its own export will load elsewhere -- the context rule, in its
sharpest form yet, on the sequences we know best.

And the console's repairs reproduce. Importing CORPUS_CONSISTENT changed
exactly four protocols -- BEAT, fl3d_vibe, se_mc, space -- the same four,
with the same field sets, it changed when those protocols arrived inside
differently-shaped archives a round earlier. Two independent imports agreeing
field for field makes the repairs a property of the protocol meeting this
console rather than an artefact of one import.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Chasing the owner's note about the six greyed-out catalogued sequences turned
up sProtConsistencyInfo.tBaselineString, which reads "ConversionNeeded" on a
protocol the console will grey out and is absent from every one that loads.

Across the 96 scans with a scanner verdict: 43 of 43 carrying it were greyed
out, 0 of 53 consistent scans carry it. That makes it a sufficient predictor,
checkable offline, and the first thing found that anticipates the greying-out
rule rather than restating that only a scanner can answer it. It is not
necessary -- ep2d_asl, svs_edit and BEAT_FQ_nav were greyed out without it --
so absence means "not predicted to fail", never "will load". Inverting that
asymmetry is the expensive error.

The neighbouring tMeasuredBaselineString says where a protocol came from:
"N4_VE11C_LATEST_20160120" on ZPL_RG_EPSI_FID_v1h. That spelling is only
recognisable because a Siemens-published VE11S archive was read a day
earlier. ulVersion is no help -- all six read 66010002, the XA60 value,
because an XA60 console wrote the archive. Origin release lives in
sProtConsistencyInfo, not in the protocol version.

It also separates the two failure modes: blade, ciss and medic, which stop a
program building outright, carry no tBaselineString at all, so whatever
refuses them is not conversion.

The owner reports ep2d_DE_pcasl_iPAT, ep2d_bold_MGH_tb and mjd_mclean_flipback
as VE11C/VB17-era sequences with no XA60 build here, which is why they cannot
load; svs_slaser_dkd and ZPL_RG_EPSI_FID_v1h he reports as installed and
working and could not explain, and he did not address ep2d_se_VASO. Recorded
as supplied. ConversionNeeded covers all six and resolves the puzzle without
contradicting him: the protocol is stale even where the sequence is current.
svs_slaser_dkd runs 421 corpus scans on an installed sequence -- what fails is
this protocol, saved under an older baseline and never converted. So a
greyed-out scan is not evidence that its sequence is missing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Where a sequence has several copies, the one to keep is the one needing no
conversion -- sProtConsistencyInfo.tBaselineString absent rather than
"ConversionNeeded" -- and among stale copies the later measured baseline.
The later-release-wins rule is the protocols' owner's; that field is what
implements it, since tBaselineString never holds a release string, only the
flag.

Over the whole corpus it moves exactly one exemplar of 117.
ZPL_RG_EPSI_FID_v1h has 9 copies, 4 of them current, and all 4 sit in the
unshipped whole-scanner export -- so the old prefer-a-shipped-donor rule
picked a stale one, and that scan came back greyed out. outbound/zpl_retry.exar1
carries the current copy for a scanner check.

The sweep also settles that most of the greyed-out set cannot be rescued this
way. 42 sequences have no current copy anywhere, svs_slaser_dkd at 421 of 421
copies needing conversion on a sequence its owner confirms is installed and
working -- so every protocol this centre holds for it predates XA60 and none
was re-saved. Where no better copy exists the fix is a fresh save on the
scanner, not a better search.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eight archives and seven printouts from six rounds of import and export now
ship under examples/XA60/scanner_returns/, with their golden snapshots. The
corpus goes from 20 archives to 28 and from 73 protocols to 80, and it gains
what it most lacked: printouts for 53 sequences that had none, and the first
examples of a great deal of spectroscopy.

Wider data corrected six readings, each widened to what is true rather than
excused.

A repeated scan name is ordinary, not a hazard. An option scan runs thirty
copies of one sequence and Keto MRS prints fastestmap five times. Earlier
notes here said to drop non-unique names before joining a printout to an
archive; that was a workaround that silently discarded real scans. They are
paired instead -- grouped by name and zipped in running order, which both
sides preserve -- and build.pair_scans is that rule in one place.
apply_protocol already worked this way; the tests were the half still
dropping duplicates, which is how a printed Coronal came to be compared
against a different scan's stored normal. A group whose sides differ in
length is still skipped, since the returns were printed after their
inconsistent scans were deleted and choosing which copy a printed one refers
to would write one scan's values into another.

The Sequence card belongs to the binary. Keto MRS's spectroscopy scans print
Measurements on Sequence - Common and Sequence - Special reading 9, counting
transients, while lRepetitions is absent -- a different parameter from the
Measurements a Contrast or BOLD card prints, and the driver was writing the
first into the second. build.sequence_card_only refuses a general mapping for
a label printed only there. One label is affected, on 76 scans. Sequence -
Special is a page of the Sequence card, so this and the Special-card rule are
one rule: the flattening trap the Position note describes, met a third time.

An empty Preview means the protocol awaits conversion -- 24 of 24 empty ones
carry ConversionNeeded and none of 928 current protocols is empty -- so the
test asserts the implication rather than tolerating the emptiness.

Three printout readings: a sequence with several repetition times prints TR 1
and no bare TR, as a multi-echo scan prints TE 1..TE 4; an unlocalized FID
prints neither voxel nor VoI, and is the only kernel that may; and an
acquisition time can run to hours, 1:42:33 h, which the clock pattern had
anticipated as 1:02:03 while allowing only min after it.

alFree[15] is an ABCD-generation field: every _ABCD navigator carries it over
226 scans and the older ones never do. The rule was written as "must be the
setter", true of a narrower corpus.

And a single-voxel spectroscopy scan's printed orientation describes its VoI.
Of 21 in the corpus, 10 print Coronal against a stored transversal normal and
11 print Transversal, matching only because that is what an unused slice
normal holds -- so none is evidence for the normal formula. The tolerance now
follows printed precision, radians(0.05) per tilt; extravals X08 still
separates the two composition orders at 7.1e-3 while tgse_asl, at 1.0e-4,
never could.

dkd_svs_sLASER joins dkd-semilaser as a fourth spelling: it is the XA60 build
where svs_slaser_dkd is the VE11C one, and they split cleanly -- all 422 of
the latter need conversion, all 10 of the former are current. That is why
every svs_slaser_dkd scan greys out on a console whose sequence is installed
and working, and the catalog had been naming the superseded spelling while
reporting the current one as unrecognized. From the protocols' owner, via a
Keto MRS export whose scans are named svs_slaser_dkd* and run dkd_svs_sLASER.

UNACCOUNTED gains 24 entries, all sequences already unaccounted: the returns
are built to carry one scan per sequence the catalog cannot name, so shipping
them changes what the corpus exercises, not what the catalog knows. None of
the pinned scans resolved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A binary can be renamed between releases, and svs_slaser_dkd is. The owner
confirms it: an XA60 save of Deelchand's semi-LASER is named dkd_svs_sLASER,
where svs_slaser_dkd is the VE11C build.

That falsifies something this file asserted two commits ago. The exemplar
sweep reported 42 sequences with no current copy anywhere, svs_slaser_dkd
among them at 422 of 422 needing conversion, and concluded that none of this
centre's protocols for it had ever been re-saved. They had been -- under the
other spelling, which the sweep was not looking for because it keyed on the
binary. Grouping by sequence identity instead gives 41, and dkd-semilaser is
the one signature in the corpus whose binaries split that way: 14 current
under the new name, 0 under the old, nothing on either side against.

So an exemplar search must ask the catalog which binaries are one sequence
before concluding none is current. "No current copy of this binary" is not
that finding on its own. For the remaining 41 there really is none, and a
fresh save on the scanner is still the only fix.

The split is pinned two-sidedly rather than as a count, because a current
protocol appearing under the old name -- or a stale one under the new -- is
what would break the rename account rather than merely move a number.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
examples/XA60/allcustomer_20260909.{exar1,pdf} is one scan per customer
sequence installed on the scanners: 35 protocols, every one current, with
a printout whose names and running order agree exactly. Twelve of them get
their first console-authored copy in examples/ -- until now they appeared
only inside archives this library assembled and a scanner handed back.

It weights sequences rather than scans, so its 8 unnamed sequences state
the catalog's gap list once instead of in proportion to anything, and
folding it into the scan-weighted unrecognized rate took that from 4.96%
to 5.46% for reasons that have nothing to do with the catalog.
ROSTER_EXPORTS excludes it there, the way the bulk import already is, and
UNACCOUNTED_ROSTER pins its scans by name instead -- the stricter check.

Two things the file settled:

An absent sparse assignment has two readings, not one. The navigator
setter prints Protocol filename: Generic with no sWipMemBlock.alFree[1] at
all, while all 46 corpus setters that store a value store 1 for Generic --
corroborated by tFree, which names Prisma_epi_moco_navigator.prot there.
So the sequence supplies its own default for an element nobody set, and
that default need not be the choice stored as zero. Mapping.absent_choice
records it, and both readings have to stand together: dropping "absent is
zero" turns MTC, Prio Recon and three others red at once. The writer now
leaves such a protocol byte-identical rather than refusing it for want of
a sibling element to insert beside.

And the three diffusion-weighted eja builds can now be told from their
parents. Joining archive to printout on scan name over 12 pairs, 6 each
way in three archives, shows each diff card is its parent's card plus
exactly "Diffusion weighting" -- 38 to 39, 40 to 41, 36 to 37 -- and that
label is on 6 of 1487 corpus scans and nothing else. The obvious reach is
wrong here: unlike CMRR's multiband EPI, these print no Diff card at all,
so cards_all matches nothing. The label alone names a technique, the
cmrr-megapress trap, so each entry carries it over its parent's
implementation labels and behind the same kernel gate; naming one more
condition outranks the parent on weight, so no priority is needed.

Attributions for eja_svs_press_diff and eja_svs_steam_diff were derived
from the card-and-kernel pairing, put to the protocols' owner as a
derivation to check, and confirmed by him.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The floor was unrecognized scans over curated scans, asserted under 5%. It
had already been raised from 2% and had two tiers excluded from it, and it
sat at 4.96% -- one curated example running three unnamed sequences short
of tripping for no reason to do with the catalog.

Per export the legitimate figures run 4.2% to 50%: GAPS_ONE_4 is one scan
of two, CORPUS_CONSISTENT is 43% because it was built to carry what
nothing names, the roster export is 23% because it states the gap list
once. No bound separates a healthy export from an unhealthy one, and the
aggregate sat under 5% only because many large fully-named protocols
diluted them. The bound was measuring dilution.

Everything it stood proxy for is already exact. The named pin catches a
signature that stops matching and one that starts over-claiming,
immediately and by scan name; the bulk import has its own counted pin.
What neither covers is that each looks at its own tier, so an export
excluded from both would be answered by neither -- which is how a future
failure would get "fixed". test_no_unrecognized_scan_escapes_every_pin
sweeps the whole corpus and subtracts what each pin claims. Falsified
three ways: dropping the roster from the named pin leaves 8 scans
standing, dropping the scanner returns 24, emptying the bulk binary set
62. It carries the usual two-halves guard, so a sweep that found nothing
cannot pass by finding nothing loose either.

third_party > stock stays, now over the whole corpus with no exclusions --
947 against 410, a margin nothing has to tune. ROSTER_EXPORTS is deleted:
it existed only for the rate, and being the one constant no other check
wanted was the clearest sign the bound rather than the file was wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
outbound/ holds archives this library built to send to a scanner. They are
evidence for a round trip rather than examples of what the tool parses, so
they do not belong in the repository -- .gitignore has covered the
directory for a while, which has no effect on files already tracked. The
branch is rewritten so they were never added; the note that cites two of
them by name now says where they came from, so a reader is not sent
looking for a file that is deliberately absent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bbfrederick
bbfrederick merged commit e788dd9 into main Sep 9, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant