2026-07-03 — editable base calls with undo/redo + FASTQ/QUAL export (v13)

Today's push adds the first of two professional-parity editing features: in-place editable base calls with a full undo/redo stack, plus FASTQ and Phred .qual export so edited sequences can flow directly into downstream tools.

Editable base calls

Every base span in the sequence panel is now an interactive element (tabindex="0" role="button"). Double-clicking a span — or focusing it and pressing Enter/Space — activates edit mode for that position. Type any IUPAC character (A, C, G, T, N, R, Y, S, W, K, M, B, V, D, H) to replace the called base. Pressing Delete or Backspace reverts the position to the original raw-trace base. Pressing Escape cancels without committing.

Edits are stored in a pure-TypeScript BaseEditModel keyed on forward-strand indices. When the reverse-complement view is active, the display index is mapped back to the forward-strand coordinate automatically and the stored base is IUPAC-complemented so it reads correctly in both orientations. Edited bases are highlighted in amber (.edited-base) with matching colours in both light and dark themes.

Propagation

Because edits are applied inside buildDisplayTrace() — before the revcomp and mixed-base steps — every downstream consumer automatically sees the corrected sequence:

Undo/redo

The BaseEditModel maintains separate undo and redo stacks as full snapshots of the edits map. Undo (Ctrl+Z / ⌘Z) pops the stack and restores the previous state; redo (Ctrl+Shift+Z / ⌘Shift+Z or Ctrl+Y) reapplies it. Making a new edit clears the redo stack. Toolbar buttons — ↩ Undo and ↪ Redo — reflect the current stack depth: they are disabled at stack ends so the user always has visual feedback about what's available.

FASTQ and QUAL export

Two new export buttons — Export FASTQ and Export QUAL — sit alongside the existing FASTA and PNG/SVG buttons. toFastq() produces a standard four-line FASTQ record (one record per file, no line-wrapping of sequence or quality). toQual() emits the NCBI/FASTA-style Phred .qual format with 60 integer scores per line. Both functions respect the current strand, trim mode, and edits in the same way as toFasta().

Accessibility

Every span carries an aria-label like "G at position 42 (edited)" so screen readers announce the base, its 1-based position, and whether it has been modified. Focus is preserved across an edit cycle: after typing a replacement, the span at the same display index is re-focused automatically. The undo/redo buttons expose aria-label with keyboard-shortcut hints in their titles.

Tests

tests/core/editModel.test.ts covers 27 exact-value assertions across every state transition: basic substitution, applying the original base to clear an edit, multi-position edits, canUndo/canRedo booleans at each step, multiple undo/redo cycles, quality sentinel substitution, and reset behaviour.

tests/core/fastq-export.test.ts asserts exact FASTQ record bytes — the @header, sequence, + separator, and Phred+33-encoded quality string — for known inputs, including the sentinel ! character, the maximum ~ (score 93), the revcomp header suffix, and trimmed-mode slicing.

tests/e2e/edit-base.e2e.test.ts runs nine Playwright scenarios: editing a base and asserting the new character and .edited-base class in the panel; asserting the FASTQ export contains the edit at the correct sequence position with quality !; undo/redo via toolbar buttons; Ctrl+Z / Ctrl+Shift+Z keyboard shortcuts; disabled-state checks on undo/redo buttons; basic FASTQ file validity; and accessibility attribute assertions.