Found during the generalization audit (#125). Not tRNA-specific, but the same class of baked-in default.
Problem
The chunk edge guard hardcodes 5 bases rather than using the configured kmer_context:
src/leech/chunking/extractor.py:350 — base_idx = int(np.clip(base_idx, 5, leech_read.num_bases - 6))
src/leech/chunking/extractor.py:360 — focus_bases = list(range(5, leech_read.num_bases - 5))
src/leech/preparation/parallel.py:142-144 — return list(range(5, max(5, num_bases - 5)))
5 is DEFAULT_KMER_CONTEXT, but ChunkConfig.kmer_context is configurable. A run with kmer_context=10 still guards only 5 bases, so edge chunks get N-padded k-mers; a run with kmer_context=2 needlessly discards usable focus bases.
Same pattern, lower stakes
src/leech/chunking/serialization.py:80-81 — chunk.get("feature_start", -5)
src/leech/preparation/parallel.py:275-276 — config.chunk.feature_start or -5
The second one has an additional bug: or treats a legitimate feature_start=0 as falsy and silently substitutes -5. Should be an explicit is None check.
Suggested fix
Use chunk_config.kmer_context at all three guard sites (np.clip(base_idx, k, num_bases - k - 1), range(k, num_bases - k)), thread it into _find_motif_positions, and derive the feature_start/feature_end fallbacks from it as well.
Found during the generalization audit (#125). Not tRNA-specific, but the same class of baked-in default.
Problem
The chunk edge guard hardcodes 5 bases rather than using the configured
kmer_context:src/leech/chunking/extractor.py:350—base_idx = int(np.clip(base_idx, 5, leech_read.num_bases - 6))src/leech/chunking/extractor.py:360—focus_bases = list(range(5, leech_read.num_bases - 5))src/leech/preparation/parallel.py:142-144—return list(range(5, max(5, num_bases - 5)))5isDEFAULT_KMER_CONTEXT, butChunkConfig.kmer_contextis configurable. A run withkmer_context=10still guards only 5 bases, so edge chunks getN-padded k-mers; a run withkmer_context=2needlessly discards usable focus bases.Same pattern, lower stakes
src/leech/chunking/serialization.py:80-81—chunk.get("feature_start", -5)src/leech/preparation/parallel.py:275-276—config.chunk.feature_start or -5The second one has an additional bug:
ortreats a legitimatefeature_start=0as falsy and silently substitutes-5. Should be an explicitis Nonecheck.Suggested fix
Use
chunk_config.kmer_contextat all three guard sites (np.clip(base_idx, k, num_bases - k - 1),range(k, num_bases - k)), thread it into_find_motif_positions, and derive thefeature_start/feature_endfallbacks from it as well.