Skip to content

Open issues, by the harm they do

290 open, sorted into six tiers by the kind of harm each one does rather than by age or label. Most carry no label at all, so this ordering is the triage rather than a view onto one that already existed.

Derived 2026-10-14 by make issues, which reads the live issue list; titles and statuses are as of that date. Whether every open issue still has a tier is checked daily against the live list (make issues-check, in .github/workflows/issues.yml). The tier assignments below are committed in issue-tiers.toml and reviewed like code.

Tier What it means Open
0 Breaks for a user 23
1 A gate that does not gate 52
2 A claim nothing measures 63
3 Measured cost 24
4 Cannot be reached 43
5 Convergence and hygiene 85

12 of them have a pull request open against them; the Status column says which.

Tier 0 — Breaks for a user

Reproducible through an interface someone actually uses — a crash, a race, a link failure, or a stub documenting a signature the extension does not have.

Issue Summary Status
#982 Carrier lock, not acquisition, fails on ~1/3 of draws — and the coarse residual that kills it is asymmetric about zero open
#1060 settle_floor()'s 5/Bn budget does not cover slewing out a clock offset — measured 12.7x too short, and it makes a working receiver read as chance open
#1284 dll: the full-epoch and partial-correlation loops apply the loop filter with different gains behind the one steer open
#1289 async_dsss_receiver: the carrier slips cycles at 40 dB-Hz in both flavours, and decodes at 1% between them open
#1443 Stub and extension disagree on a call signature in 10 sacred fragments (jm apply has been saying so) open
#1654 Array parameters without a str_hint still let numpy parse a str (279 calls); the size-guard half is done open
#1680 track.Dll: at segments=1 the code loop's realised Bn is 56-79x the configured bn, with zeta ~0.05 (the integral path is scaled by SF, the proportional path is not) open
#1958 psd: adjacent bands both count the bin they share, so a partition overstates the whole (+3.0 dB on a DC tone) open
#1992 detector/detector2d/acq push silently drop the rest of the input once results fill (Python defaults lose 488 of 1000 samples) open
#2011 stream: producers ignore send failures (wfmgen exits 0 after dropping blocks; StreamSink.send returns an int) and close() loses the tail in review (#2300)
#2014 buffer: F32Buffer.consume(0) releases the outstanding borrow instead of nothing (jm releases codegen treats 0 as omitted) open
#2029 specan PullSource: one seq_account in the library, redeliveries keyed on num_delivered, and the fail-open holes #2020 left open
#2038 burst_capture: a full detection queue drops hits uncounted, and set_state writes before its checks open
#2040 wfm: StreamSink.send should raise on a refused block, not return an int (blocked on jm) open
#2057 adopt just-makeit#2187: a buffer's destroy() must not unmap under its live views (#2016 item 4) open
#2063 stream: Pull.close() during a GIL-free recv() tears down the context under the fetch (#2016's class, receive path) open
#2095 _SynthEngine.set_wtype(PN|BPSK|QPSK) on an engine created otherwise segfaults on the next step open
#2110 clib: dp_fmod_pos can return m (outside [0,m)), so dll_replica reads code[sf], one past the copy in review (#2305)
#2111 resamp: set_state trusts a forged delay_head, and the next output reads past delay_buf in review (#2301)
#2112 float-domain holes from #2109's review: loop embedders without the bn/zeta predicate, det_verify_count int overflow, Dll lock geometry open
#2142 set_state trusts index fields from the blob: MovingAverage writes out of bounds; delay, wfm_synth read out of bounds open
#2234 BurstCapture: a tiled capture of a repeated chirp reports the wrong Doppler tile 13-78% of the time, start up to 7 periods off (pre-existing, D = 1 too) open
#2291 wfm_json.c converts JSON numbers to integer fields with bare casts: num_samples=1.5, -1, 232 and seed=-1, 232 are accepted (jm's hardened reader never reaches Composer.from_json) open

Tier 1 — A gate that does not gate

This repo's own doctrine turned on itself: a claim nothing runs is prose. Each is a check that reports green because it cannot see the thing it names — several confirmed by sabotage.

Issue Summary Status
#682 test: §12's blob-determinism check compares in float at 1e-9, so it asserts float-equality not bit-identity open
#692 characterization: the category has no envelope gate and no figure-freshness gate open
#696 docs-check and docs-drift-check keep two copies of the generator --check list, and CI only runs one open
#716 Validation figures and CSVs are gated by nothing — validate-check only compares rendered markdown open
#736 check_doc_face_parity compares Examples/Raises only, so the divergence that shipped was invisible — and lock-detection.md is stale on CarrierNda open
#744 check_lifecycle: verify the phase-9 example too, by having each report cite it open
#847 Phase 4's sabotage rule is stated on three pages and executed by none open
#871 check_stimulus_sources: a hand-computed Es/N0 sigma is an invented level convention, and no marker catches it open
#919 libdoppler.a's declared link line is only checked where pthread is a separate library open
#936 check_stimulus_sources: the pulse marker's C branch cannot fire — it is matched per line against a signature clang-format always splits open
#967 check_doc_paths does not check build/ paths, so documented invocations can rot silently open
#1000 46 header @code examples reach no stub, so no gate executes them — and one of them was wrong open
#1010 19 Python benchmarks take the benchmark fixture and never call it in review (#1972)
#1028 Nothing enforces the UBSan alignment ratchet — it grew 821 → 853 unnoticed open
#1118 StreamSink cannot be certified through its Python face: validate-check runs after nats-down, and a report must render identically either way open
#1129 wfm_plan: nothing can observe whether a restore took the cached fast path, so a silent fallback to full rebuild would pass every test open
#1201 Parallel make targets re-sync one shared venv against each other: a plain uv run removes the docs group under a running docs-check, and a make pyext sync broke a commit hook's mkdocs build open
#1306 make gallery keeps two hand-maintained lists that must agree, and a script in only one orphans its PNG open
#1328 A spot check's budget is wall-clock; gate its WORK COUNT instead open
#1350 tests/install/rust-test.sh has no execution home — nothing runs it, which is why its broken make goal survived open
#1366 bench: acc_f32's madd/madd2d/get/dump benchmarks measure a no-op in review (#1980)
#1377 tests-ssot's private-RNG check is blind to libc generators (rand_r, random, drand48) open
#1388 Sanitizer jobs skip all 23 validators — a heap overflow in validate_receiver_pullin shipped because of it open
#1566 validate_capture_dwell_pd fails make validate: its full sweep asserts nothing open
#1637 wfm: the Field corpus cannot see a constant field (why it missed #1624) open
#1657 build: -Wswitch is never an error, so an unhandled enum value warns and ships open
#1663 DP_NODISCARD: an ignored refusal is invisible to every compiler flag open
#1671 gallery-scripts-check cannot see a plot whose file name the script derives rather than quotes open
#1770 A mypy gate: doppler's own code type-checked against its stubs, ratcheted open
#1772 release-freshness-check: one changed asset passes every changed gallery script open
#1900 make test-python ends with SIGTERM (Error 143) at ~50% on a different test each run open
#1915 Two manifests restate acq_result_t's fields by hand, and drifted the first time the struct grew open
#1920 tests-ssot: the macro-stamped framer is outside the serializable/streaming gates open
#1977 make bench exits 0 when its Python half fails to collect (upstream: just-makeit#2180) open
#1982 Release and CI-image container builds pull stock FROMs inside BuildKit, so #1979's pre-pull cannot reach them open
#1994 ratchets: check_warnings and check_alloc_helpers switch off when their list is absent at the base; move both onto _gitbase.added_since_base open
#1997 docs sh gate: the holes an executed fence still has (exit-status-only refusals, substitutions, pipefail 141, shadowing, the wfmgen/cat trigger) open
#1999 release: the pre-publish smoke-wheel installs only cp312, so a per-Python wheel defect is found after PyPI is written open
#2004 build: a parent compiler change drops make build's and make pyext's -D options; pyext then exits 0 having built no extensions (likely #1996) open
#2012 stream: core NATS subscribers lose frames across disconnect/reconnect with no signal; no error/disconnect callbacks, and the docs describe a slow-consumer drop that cannot happen open
#2013 stream: the 'durable' JetStream tier deletes backlog older than 1 h (MaxAge) for a lagging consumer, while stream.h and stream.pyi say it cannot / keeps frames forever open
#2059 validation reports: _self_check resolves §N.M but never F -- a renumbered finding silently re-points every citation in review (#2147)
#2062 adopt just-makeit#2188 (jm_bench.h drops entries past 32 silently); restore U1's hop nfft/2 bench rows; guard the cap meanwhile open
#2077 state: verify #2022's C-only setters with a C-side twin of the mutator gate open
#2078 state: 11 serializable classes have no test_state_serialization CASES row, so #2022's gate cannot probe their mutators open
#2093 state gate (#2022): what #2085's review leaves -- refused-restore probe, NONDETERMINISTIC masking, C-only discovery open
#2182 Validation reports restate header claims by hand; nothing ties a claim to its header sentence or its verdicts (deferred design) open
#2205 A changelog fragment without its leading "- " passes every PR gate and fails only at release assembly open
#2218 acq: a burst engine's measured per-dwell Pfa is 2x its target (1.97e-3 against 1e-3, ZC 127 x 16, D = 5) open
#2224 acq: a tiled burst engine's pd_predicted/pd_burst price W·D·cb samples, not D·cb -- it reports ~1.000 (0.62-0.94 measured) and underpowered stays clear where it should warn open
#2235 acq: since #2230, a tiled burst search at D > 1 reports raw hits a whole tile off, off the ridge, for band-limited repeated chirps (9-12% of hits; D = 1: none) open
#2256 ci: ECR Public's anonymous DATA quota ('toomanyrequests: Data limit exceeded') outlasts stock-pull.sh's 75 s retry window open

Tier 2 — A claim nothing measures

A header, report or design doc asserts a number or a behaviour that no test and no validator establishes. Not wrong — unestablished, which is a quieter problem.

Issue Summary Status
#645 MpskReceiver timing loop: two measured default changes not taken — DTTL for BPSK/QPSK, and bn_timing's knee open
#646 The resamp double-emit fix is pinned at RateSync level only — MpskReceiver, where it was observed, has no regression test open
#684 test(symsync): the embedded timing NCO never states its rate, and the gate that would catch it never landed open
#689 DSSS test captures inject 3.01 dB less noise than their cn0_dbhz label, and correcting it exposes non-monotonic acquisition open
#711 agc: the header promises level-independent settling, and §6 measured otherwise open
#732 carrier_nda: the acquisition contract needs the seeding number (|df| \<= bn/M), and the arm's absolute wall it does not name open
#733 carrier_nda: the half-symbol arm's 1/2 + 1/(M+1) coherent gain does not reproduce open
#734 carrier_nda: the lock statistic's H0 spread is M-independent per look, and is not through the arm open
#751 The DTTL's "degrades faster at low SNR" claim is unmeasured — the RateSync validator adds no noise open
#754 MpskReceiver: false lock (negative lock, correct frequency and timing) at any m_out mpsk.md §8 would not derive — the cost of #644 open
#814 MpskReceiver: six header claims are covered by nothing in either language (F9) open
#830 The MpskReceiver validation report characterises the complex face only — the real face has no Python evidence open
#831 MpskReceiver: state the link and the requirement, derive the loops (mpsk-refactor 4.3) open
#855 The timing rate residual doubles with a carrier offset present, and nothing characterises the coupling open
#932 symsync_lock's published false-alarm rate moves 1.5x with -ffast-math, and its header states a conclusion neither value supports open
#962 Streaming: CI8/CI16 have no round-trip test, and the format names are unprefixed in a public header open
#975 The 100 ms interrupt bound is published as a guarantee and measured only at idle (io-termination §5) open
#997 acq: the non-coherent Pd model is NOT unreliable past a few hundred looks — measured monotone to 1024, \<1 sigma to 512 open
#1064 acq: realized Pfa is ~1.65x the requested target — the threshold's N omits the Doppler interpolation the gate's maximum runs over open
#1128 wfm.Plan: a ranged-gap scene draws a different length per seed, and render()'s documented Returns says it does not open
#1133 gold: the CCSDS constants are certified against the published vector, not against the document open
#1191 acq peak list: a strong emitter's same-code-phase sidelobes pass the two-epoch rule under long non-coherent integration open
#1275 async_dsss_pool: a neighbour within a kilohertz crossing a departed receiver's code phase at a chip or two a second is, to that receiver, a return — the pool's zone is where it can be told apart open
#1307 The burst-demod test codes have 0.78 autocorrelation sidelobes, so the tests tolerate timing error no real waveform would open
#1311 burst_capture k_lo is 3*reps+2 by assertion, not derivation, and it inflates the merge radius and min_gap by 1.7x open
#1475 30 serializable objects are outside the shared state round trip: blob determinism unchecked open
#1530 burst capture: min_gap is conservative once emission follows stream time -- re-derive or re-measure it open
#1677 CarrierNda: the loop gains ignore the discriminator's slope of 2, so the realised noise bandwidth is ~1.67x the configured bn open
#1775 wfm_frame: decide bounded vs unbounded field list and contiguous vs bitmask cover open
#1777 Certify wfm_data and dp_hash64 in the Validation Log open
#1814 bench_wfm_synth::test_bench_step can calibrate to 1 iteration and time the clock, not step() open
#1867 DopplerChannel is not certified: no validation report (adding-algorithms phases 7-8) open
#1874 Apply the signed-count refusal (DP_ERR_INVALID) to the other count-returning calls that collide with a valid 0 open
#1896 Chunk-invariance: burn down the ratchet (49 stateful streaming objects have no test) open
#1921 docs: assert the printed-output text fences the snippet gate does not check open
#1928 Audit: SIMD kernels whose scalar tail rounds differently from the vector body (the #1893 pattern) open
#1967 bench(carrier_acq): the C benchmark credits 65536 samples to a search that stops after one block open
#1969 bench(interp_table): the C benchmark names its rows nearest/linear/cubic; the methods are floor/nearest/linear open
#1970 bench(ber_meter): the C stimulus maps symbol indices through a Gray-label constellation open
#1971 bench(pn): the C benchmark's polynomials are not maximal-length in dp_pn's convention open
#1991 bench: stamp the measured TREE in doppler_meta, so bench-commits-check verifies provenance offline, not just reachability open
#2001 Stubs: none_on_empty readouts lack | None until just-makeit#2183 ships open
#2039 stream: an end-of-stream names no stream, so any publisher's EOS on a base ends every subscriber there open
#2053 psd: windows are symmetric (N-1), not the periodic form spectral estimation uses -- Hann n=2 is zero, -82 dBc leakage, BH ENBW 2.036 in review (#2140)
#2071 burst_despreader: create() and set_bn_* pass an unvalidated bn to dp_loop_filter_init, which trusts its embedders to validate in review (#2306)
#2079 state (#2022 family 1): LO/NCO norm_freq is not in the blob, and every tuned composition inherits it open
#2080 state (#2022 family 2): a rate is state and a reject key -- RateConverter, Resampler, CIC restore into another rate open
#2081 state (#2022 family 3): correlator and detector set_ref / set_threshold values are not serialized open
#2082 state (#2022 family 4): wfm_synth's setters are not serialized open
#2083 state (#2022 family 5): receivers' and meters' setters -- RateSync bn and lock, BerMeter truth/align, acq carrier, DSSS lock_raw open
#2087 burst_capture: configure_search_raw() mid-stream resets acq position but not samples_fed, so every later epoch is early open
#2104 state: composite set_state restores children in sequence, so a refused later child leaves the parent half-restored open
#2114 specan PullSource: a read returned 10 of 1200 frames and timed out (intermittent, CI Python 3.10) open
#2143 bench(psd): power_onesided is timed one call per round, so its 1,024 cell moves in 7% clock steps in review (#2146)
#2159 specan: the source/engine handshake is written three times and the copies disagree open
#2187 PSD kernel extraction is byte-identical on x86 only; run the before/after dump on aarch64 open
#2188 docs/specan/chirp_frames.json is stale and no test reads it open
#2200 Published Python benchmarks under ~300 ns carry the timer's overhead whenever pytest-benchmark calibrates one iteration per round open
#2211 PSD kernel follow-ups from #2209's review: ENBW off the kernel, meters carry an unused ring, the identity dump's gaps open
#2219 rate_hypotheses follow-ups: tiled Monte-Carlo, per-event rate, DsssBurstReceiver, a deterministic guard for refine open
#2229 acq: a dwell straddling a burst's start with under one epoch of signal reports its Doppler up to ~D/2 bins off (first hit only; tiled and narrowband alike) open
#2236 acq: resolve a tiled burst's tile alias over a delay window and re-estimate the code phase at the resolved hypothesis (ridge-aware; the fix for the chirp raw-hit errors) open
#2289 nogil: ten methods now really release the GIL (jm 0.105.0) and none has a thread test for a shared object open

Tier 3 — Measured cost

Performance findings with a number attached. Filed, not fixed; each names the measurement that produced it.

Issue Summary Status
#502 Performance: prepare() scales O(n) with users instead of sharing RRC filters open
#845 make coverage's -O0 tree costs 6 minutes, and -O2 takes two bit-exactness tests red under CI's clang 18 open
#890 snr: both _db_series forms are O(nwindow) — they re-scan the window at every sample open
#896 Multi-config C benchmarks charge the clock ramp to whichever config runs first open
#905 arith: the Q8 shift kernels are slower than their Q15 twins, not faster open
#1006 DsssBurstReceiver: non-overlapping frames cost a band of burst offsets NEAR the knee (77% for a good code) open
#1173 BurstCapture: the per-burst window copy is measured only at a 20 kB window, and it scales with burst_len open
#1247 acq: bound the block depth D to a smooth slow-time length -- 308 = 4·7·11 at the operating point, and the transforms are now the searcher's cost open
#1269 AsyncDsssReceiver builds its refine and track chains on every seed and hand-over — the pool's "sized once at create" holds for the pool, not its receivers open
#1309 acq interpolates Doppler but not code phase: nx_out is 0, so the burst start is quantised to one sample open
#1313 The two long sweeps over BOUND objects sit in native/validation/, not characterization/ — 60% of every PR's C suite open
#1320 wfm_writer raw cf32 write is ~7% slower than v0.47.0 with byte-identical source open
#1342 wfm_writer integer writes are ~3x slower since #1117: every component goes through the single-sample converter step open
#1370 coverage: the sweep validators are excluded from instrumented ctest, then run again through pytest — 28 of the job's 42 minutes open
#1381 perf: three benchmarks flat for three releases moved in v0.51.0 (wfm_synth step 2.3x, acc_trace 1.5x, wfm_writer ci16 1.26x) open
#1697 DSSS burst receiver: TX/RX usability and speed findings (frame_syms, naming, refine_span, error drift, events padding, 4 MSa/s) open
#1816 ci-changes: a release's waiver file counts as source, so the release commit runs the full matrix open
#1856 resamp: the ctrl step truncates to 32 bits, a constant ~8e-11 rate bias (0.2 Hz at 2.5 GHz) — may not matter open
#1937 bench: wfm Reader Python cells moved +11% / +21% in v0.65.0, one cell per build; not the binding, cause unmeasured open
#1978 acc_f32/acc_cf64: add2d and madd2d are private copies of steps and madd, and miss the SIMD path (4.4x) open
#2006 acc_f32/acc_cf64: madd (and so madd2d) is a serial scalar reduction; give it steps' SIMD path open
#2074 PSD's dB conversion is 70-83% of a frame: decide on a cheaper conversion or a power-first default (Spectrogram U3) in review (#2117)
#2094 PSD must blaze: the per-frame fold on the SIMD accumulate path, measured against the FFT open
#2287 acq: per-dwell Pfa at rate_hypotheses n = 3 and n = 4 reads above the target (1.20e-3, 1.07e-3 at 1e6 dwells), with #2218 open

Tier 4 — Cannot be reached

The capability exists in C and no caller can get to it, or it exists and nothing tells anyone it does.

Issue Summary Status
#545 Reading a capture is undiscoverable and undocumented — enriched view over wfm_reader + a guide open
#658 AGC: a seed that cannot fire on silence — buy back the acquisition spread open
#661 RateSync reports over-drive but is silent about under-drive open
#668 RateSync.clipped conflates transmitter over-drive with noise-crest clipping open
#735 carrier_nda_get_nco_freq is unreachable from Python and telemetry — both published frequency views are the same view open
#750 AGC has no signal-presence notion: on a noise floor it applies 59.9 dB and the next burst arrives hot open
#813 fec: virtual fill (4.4.2 shortened codeblock) is not implemented, so a frame off the 223*I grid has no path through the outer code open
#844 stream: ten public send entry points have ZERO execution — the CI8/CI16/CF32 slice of PUSH/REQ/REP, including the durable JetStream tier open
#865 doppler reads 131.0-B-3; B-6 is current — and it changed the randomiser default open
#959 Streaming API shape: role typing, ack ergonomics, control-plane parity, and an undocumented size ceiling open
#966 Pull workers have no subscription drain, so leaving a queue group drops in-flight work open
#981 Composer cannot SET seed_advance from Python — the object face and the JSON face disagree open
#998 acq: no property reports the SEARCHED Doppler reach, and doppler_span_hz reads like it does open
#999 acq: a push shorter than one dwell returns nothing, and nothing says how long a dwell is open
#1035 The stream carries complex only; a real sample type is refused at the sink open
#1057 Three public classes are reachable only from the generated API reference — and two are the odd ones out in a 13-member family open
#1073 A Bits type with methods, rather than six free conversions threading out-parameters open
#1202 EventLog: the standalone finalize has no Python face — a crashed run's sidecar can only be rendered from C open
#1206 wfm compose: sources in a segment cannot be shifted independently — add a per-source start offset open
#1229 AsyncDsssReceiver: one telemetry attach should forward to the embedded Acquisition open
#1294 wfm: the compose Synth and the Plan's DSSS source have no per-frame code-only window; only _SynthEngine.set_dsss_window has it open
#1364 Windows (clang-cl): what remains after #1360 — the C library compiles, the link and the benchmarks wait on jm open
#1372 Push.send_eos reports no transport detail, so a full store and a deleted stream are indistinguishable (send distinguishes them) open
#1405 vcpkg: a static triplet needs a single-linkage build open
#1431 stream.Push.send_eos() is bound at runtime but absent from stream.pyi open
#1481 acq burst path: no code-Doppler (time compression) compensation, and it bites wideband preambles hardest open
#1571 ddc: the plain DDC's CIC is uncompensated and cannot be asked to compensate (flat only to ~0.1 fs_out) open
#1692 wfm: FrameDesc has no from_json constructor (a description is built from JSON only as a scene's "frame" key) open
#1722 wfm: Plan's refusals carry no reason (const char **why, #1686) open
#1776 wfm: the composer has no state triplet open
#1780 wfm: no Python face serializes a synth pulling from a data source open
#1803 Python face for dp_syncword_search, plus M-ary (QPSK 4-fold) ambiguity resolution open
#1828 Install the benchmark/test harness headers so downstream projects can use them open
#1829 Stream subscriber: expose frame-gap and duplicate accounting from the wire header open
#1865 Plan: a background=True source with Doppler is refused (fold sums it before any channel can run) open
#1894 Streaming spectrogram: a Spectrogram object over the ring's framed face (PSD per frame, no averaging) open
#1966 Spectrogram: separate the frame length from the transform length (non-power-of-two nfft) open
#1983 MpskReceiver(agc=0) refuses a prefix every probe it registers fits, on its disabled AGC's names, and leaves dead slots open
#1987 AccTrace.alpha: the setter refuses silently in Python until just-makeit#2182 ships open
#2024 framer: no Python face, so the framed face shipped without the Python example and bench that phase 9 owes open
#2031 stream: reassemble more than one chunked frame at a time, so two publishers on a subject do not abandon each other's frames open
#2089 stream: the wire header gains a sender/epoch id (owner decision on #2017) open
#2183 PSD reads back hop, window, beta, pad and alpha, and PSD.mode by name open

Tier 5 — Convergence and hygiene

Duplication, stale pins, harness drift, and the long tail. Real, none of it urgent — and the tier that grows when the ones above it are held.

Issue Summary Status
#535 DsssReceiver: derive segments, adopt async's squaring carrier combine open
#630 GitHub Actions: every pin is stale (up to 5 majors), and the Node 20 forcing we rely on is temporary open
#639 CI is make-SSOT for every gate — the drift is all in the plumbing layer open
#651 Makefile diverges from the shared convention: no PYTEST command variable, and make test runs only ctest open
#655 UBSan alignment ratchet: 821 misaligned member accesses open
#678 util: no C test harness, and square_clip.c duplicates its own body open
#685 feat(telemetry): attaching a pipeline takes one call per object; the one-call form was written then lost to a redesign open
#694 make gallery: GALLERY_CHARACTERIZATIONS is plural but the recipe only works at n=1 open
#712 make docs-check gives a wall of false broken links when site/ is absent open
#720 clang-tidy: 172 findings block gating at zero — triage, judgement, and config, in that order open
#721 Three helpers are byte-identical across modules; zeropad_1d is the one that will drift open
#730 jm_test.h is deliberately not vendored: a jm 0.58.0+ test scaffold needs converting to dp_test.h open
#756 Retire wfm_synth_mls_poly() in favour of pn_mls_poly() open
#802 Cleanup plan for the test/measurement layer: a convergence plan, not a deletion plan (measured) open
#856 design/bpsk-receiver is superseded by the collapse and the view — triage its design doc, then close it out open
#893 bench: six benchmarks are declared at a level jm was never told about (three below an object, three inside c_deps) open
#894 Certify viterbi as its own object, rather than inside conv open
#900 Audit: what is left to declare, and the capabilities with no Python path open
#906 The function-only modules are benchmarked in C but not in Python open
#933 Migrate the four inline LCG streams off scripts/.private-rng-ratchet open
#937 Four validation harnesses hand-roll AWGN instead of calling the library's awgn, and nothing says they shouldn't open
#974 The dp_stream_* interrupt aliases were meant to be removed, and nothing tracks it — our own binding still uses all of them open
#1009 Certification reports open with caveats, not orientation — a caller arriving cold has no entry point open
#1114 noise_steps matches steps()'s AWGN chunking to defend against a path that no longer exists, and nothing would catch its return open
#1123 wfm_reader_header_tag neither bounds-checks nor documents that it must not be — the only one of four enumerators that does neither open
#1186 changelog.d fragments using reference-style links break mdformat once assembled next to another entry open
#1188 native/validation: move every validator's --check onto dp_test.h open
#1228 docs(gallery): a page for acq_surface_demo — the searcher's surface and probes open
#1242 just-makeit.toml carries a stale "NOT adopting c_style" block eleven lines below c_style = "clang-format" open
#1299 The "slot by both coordinates" phrasing repeats in six more places, including a generated results.md open
#1302 Burn down docs/.design-page-baseline: 24 design-page record sections across 15 pages open
#1305 form_partials: the last partial runs long when est_segments does not divide acq_sf open
#1380 cvt: two of twelve converters abort on OOM, the other ten raise MemoryError open
#1396 test-snippets: the PAGE= usage example names a page that no longer exists open
#1398 validation: 28 private _csv helpers in 8 variants -- one Report.csv() that owns the write flag open
#1425 ring buffer: does burst_capture's position-addressed history belong in the ring? (at / pos / restore) open
#1463 stream: _ready_queue timed out after 10s on a server-acked probe (test_push_pull_header_all_fields, py3.13 CI) open
#1465 Windows: POSIX-only test carve-outs in the Python suite open
#1489 test_compose: live three-block chain can miss its 10 s recv budget under a parallel suite open
#1495 Acquisition (continuous): take the samples model the burst engines now use open
#1496 Two library copies of the chip → ±1 rule: wfm.bpsk_map and cvt.bin_to_nrz open
#1547 Packaging: the relocatable .pc defeats pkg-config's system-dir filtering, and jm can now own the install section (dry run attached) open
#1550 carrier_acq's pfa is per-test while acq's is per-search: same name, two meanings open
#1570 docs: types.md and cvt/iq.py name RTL-SDR as a CF32 / int16 source (it streams cu8) open
#1577 Vendored symbols: extend the dp__v_ respell to macOS, Windows and the shared libraries' export tables open
#1608 Docker image re-resolves the jm pin against PyPI instead of installing the locked wheel open
#1638 check_wfmgen_flag_docs: the checker cannot see short flags, so -o is waived open
#1651 Header @code backlog: 79 C examples do not compile or run (ratchet from #1635) open
#1665 A failure message can name a make target that no longer exists open
#1667 Patch-coverage gate has no way to name an unreachable enum case, so a -Wswitch fix alone is always red open
#1676 package-linux sends the builder's dnf output to /dev/null, so a failed rpm-build install cannot be diagnosed open
#1694 wfm: Source.frame's getter returns JSON that its setter refuses; drop it when just-makeit#1753 lands open
#1698 wfm_compose: 105 source/segment field docs are declared twice (header comment + manifest doc), gated equal; derive from the header only (jm#1703) open
#1723 wfm: one copy/free pair for wfm_source_t's arrays (wfm_plan.c duplicates wfm_compose.c's) open
#1728 ci: two jobs upload an artifact named coverage-report in the same run open
#1740 curl without --fail outside the image: install-deps pipes get-jb.sh into bash (Makefile, standard.mk), release-watch.sh open
#1774 ber.FrameMeter takes Frame.check()'s result, not a bare CRC outcome open
#1800 rx: object constructors lose dp_wfm_frame_desc_rx's reason; needs an object-level create_why in jm open
#1815 Adopt Keep a Changelog 2.0.0: Breaking marker within its type, an optional version summary, and a gate for six types open
#1826 ci: a docs-only diff should run the docs-reading tests, not the full Python job open
#1850 check_warnings.py docstring still says '99 hand-owned fragments' after #1446 adoptions open
#1853 PN(length=1) builds a no-feedback register that wfm_synth and wfm_frame refuse open
#1886 Adopt fft, wfm_synth, dp_tlm and dp_tlm_capture to jm: held on extra_methods and just-makeit#2059 open
#1887 scripts/.warnings-exempt floors at 2: stream_ext.c and resample_ext_extra.c are not jm-adoptable open
#1897 Composite set_telemetry leaves dead probe slots when a child refuses after the parent registered open
#1906 Refresh prose that still says the interrupt flag is volatile sig_atomic_t (follow-up to #1027) open
#1912 Validation: migrate conv, rs and ccsds_tm onto _validation_common.harness_blocks (three private copies of the harness CSV parser) open
#1957 psd: scalar readouts return 0.0 for 'no measurement', a value a real measurement also returns open
#1984 scripts: seven gates strip C comments with a /*.*?*/ regex that does not know about string literals open
#1990 examples/downstream-jm's two sacred capture fragments miss jm's binding fixes (the last jm-apply binding warnings) open
#1993 docs gate: the sh fence's src/ -> /src/ rewrite also rewrites redirect targets, so a fence writing to src/ writes into the real checkout open
#2005 build: the vendored nats.c custom command has no DEPENDS (a vendor bump never rebuilds) and does not forward the ccache launcher open
#2023 dp_chunk_inv.h: a stop-and-resume mode, so the detectors' ci_*_resume twins (and acq's) are one harness open
#2027 stock-pull.sh --dockerfile pulls every stock FROM, whatever stage the build targets open
#2030 lint: a make target a uv-less CI job runs may not call uv (nats-vendor-fresh-check failed train #2026) open
#2032 stock-images gate: a shell build-arg value is never resolved, and a workflow pre-pull's scope spans jobs open
#2037 dp_tlm: read the telemetry ring through its API, not head/tail/mask (#1426 baseline) open
#2045 Makefile:1674 says gen-c-api-check runs via docs-invariants; it runs only as its own pre-commit hook open
#2054 ring gate blind spots, burst_capture's plain resets, and one acq drain helper (#2042 leftovers) open
#2066 package-linux: the builder image's dnf failure is discarded (docker build -q >/dev/null), and dnf has no retry open
#2108 One dB conversion: every remaining log10 site switches to dp_power_to_db_f32 or says why it keeps double in review (#2126)
#2189 specan nits from the #2180 review: dBm import direction, step() naming, fastapi skip open
#2254 examples/: 33 print calls in 16 scripts hold characters cp1252 cannot encode, so they crash on a redirected stdout on Windows open
#2279 hand-owned fragments: six uint64_t / size_t parses use the masking K (dp_tlm x4, wfm_synth pn_poly and span), so a negative or over-wide int wraps open
#2286 wfm_synth .prod(): ~60 lines of hand-written glue and a hand-edited sacred fragment, and no public Synth.prod, until jm 0.105.0 in review (#2297)

How an issue gets its tier

By asking what goes wrong if it is never fixed, and nothing else. Age does not raise a tier and neither does effort — a one-line fix that stops a crash outranks a week of hygiene. The tiers are deliberately about harm rather than cost, so that the order to work in falls out of the table instead of being argued each time.

The daily make issues-check run goes red if an open issue has no tier or a tier names an issue that is closed — so this page cannot rot in either direction without saying so. make issues refuses while an issue is untiered, and drops a closed issue's row itself.