2026-07-04 — v26 manual assembly controls: strand override + overlap/match tuning
Until now the contig assembler was a one-shot black box: load two reads, click Assemble, and hope the auto-orientation logic picks the right strand and a 20 bp minimum overlap works for your amplicon. That is fine for a classic F+R Sanger pair — but the moment you have an unusual run, a very short amplicon, or a re-sequenced read that was stored reversed, you had no lever to pull. Today that changed.
What I shipped
- Strand A / Strand B override selects. Each read can now be set to Auto (existing behaviour), Force Forward (pass the sequence as-is regardless of what auto-detection would choose), or Force Reverse (pre-apply reverse complement before the assembler sees the read). This is the fix for the "I know read B came off the reverse primer but the assembler keeps mis-orienting it" case.
- Min overlap (bp) control. A numeric input (range 5–200, default 20) lets you tighten the minimum overlap length. Short amplicons now assemble cleanly at 10–15 bp instead of silently failing at the 20 bp hard-code; long, repeat-heavy amplicons can be tightened to 50+ bp to avoid spurious matches.
- Min match % control. A percentage input (range 0–100, default 0 = accept any positive-scoring overlap) adds a score-quality floor. Setting it to 70 % means at least 70 % of the overlap positions must contribute a positive match score — useful for rejecting chimeric overlaps that only pass because the overlap region happens to be short.
- Live re-assembly on control change. Once a contig has been assembled, any change to a control immediately triggers a fresh assembly pass, so you can scrub the overlap-length slider and watch the consensus update in real time without pressing Assemble again.
- Informative error messages. When no qualifying overlap is found the status line now shows the exact min-overlap and min-match values that were active, so there is no ambiguity about why the assembly failed.
Architecture
-
src/consensus/assemblyControls.ts— pure TypeScript, no DOM. DefinesAssemblyControlState,DEFAULT_ASSEMBLY_CONTROLS,applyStrandOverride()(reverse-complements seq + qual when'reverse'), andassembleWithControls()which orchestrates the full pipeline: strand pre-processing → minMatchFraction gate →buildPairedContig. Everything is client-side; no data leaves the browser. -
src/components/ContigPanel.ts— extended with a.contig-panel__controlssection above the action buttons, containing four labelled widgets (data-testidanchors for tests). AddedgetAssemblyControls()to read the current widget state as anAssemblyControlStateobject. -
src/components/TraceViewer.ts—runContigAssembly()now callsassembleWithControls()instead ofbuildPairedContig()directly, passing the controls fromgetAssemblyControls(). Change listeners on all four controls firerunContigAssembly()when a contig is already resident.
Tests
-
tests/core/assemblyControls.test.ts— exact-value unit tests:applyStrandOverride— exact RC sequences and reversed quality arrays for the'reverse'case; identity for'auto'and'forward'.assembleWithControls— storing a read as RC of the correct sequence, then settingstrandA='reverse', recovers the exact consensusAAAAAACCCCCGGGGGwith contigLength=16, mismatchCount=0, and coverage=2 at overlap positions 6–10.minMatchFraction— overlap score 2/4 = 0.5 is accepted at threshold 0.5 and rejected at 0.6; exact IUPAC mismatch base K at position 10 is verified.minOverlap— assembly fails with minOverlap=10 on a 5-base overlap pair and succeeds at minOverlap=5.
-
tests/e2e/assembly-controls.e2e.test.ts— Playwright tests: default values, option sets, range attributes, label wiring, keyboard focus, assembly round-trips with min-overlap=5 and min-overlap=200, live re-assembly on control change.