Project Retrospective Β· 2026-09

Two Years,
One Full Retrospective

From the first commit in October 2024 to V6.0.2 in September 2026: six phases of evolution, five classes of recurring problems, the methods that proved themselves, the evolution of verification, and a look forward. Every claim is written from git history and version records β€” no recollection, no polish, only evidence.

400+Total Commits
35Released Versions
6Evolution Phases
7Meta Lessons

By the Numbers

This repo (UHRR_mac, from 2026-03-06): 206 commits. Parent project UHRR (from 2024-10): ~208 commits. 400+ commits and 35 versions combined.

Monthly Cadence

Mar 48 / Apr 4 / May 35 / Jun 32 / Jul 1 / Aug 55 (the most intense month) / Sep 31. The quiet months were "usage-driven" β€” the product ran in real QSOs while problems accumulated.

Peak Release Day

2026-08-09: five versions in one day (V5.7.1 β†’ V5.8.2) β€” RagChew fixes, ATR SWR guard, IOLoop de-blocking, thread-misplacement fix. A concentrated overhaul burst.

Platform Evolution

Raspberry Pi/Linux (parent) β†’ macOS (this repo's origin, 2026-03) β†’ Windows installer (V6.0.0, 2026-09). One codebase, three platforms.

Six Phases

Every phase is written directly from the commit chain.

Phase 0 Β· 2024-10 β†’ 2026-02

From Zero to Usable (parent project)

  • V1.0 β†’ V4.3: core architecture settled (Tornado + WebSocket + PyAudio + Hamlib + Opus)
  • Dual desktop/mobile interfaces, basic recording
  • FDE mode established: the author (BG1SB) was the first heavy user β€” daily QSOs as the test field
Phase 1 Β· 2026-03 Β· 48 commits

The Mac Port Sprint

  • ATR-1000 tuner saga: SYNC throttling, anti-disconnect, intelligent learning (V4.5.11β†’V4.5.18)
  • First threading battles: TX AudioWorklet refactor β†’ decisive rollback (d4a40c2)
  • High-fidelity voice edition, WDSP, multi-instance deployment, remote tunnel, bilingual UI
Phase 2 Β· 2026-04 Β· 4 commits

The Quiet Month

  • Only a mobile fix + WDSP NF; V5.0.0 mobile UI modernization at month's end
  • Low commit count β‰  stagnation: real usage was accumulating real problems
Phase 3 Β· 2026-05 β†’ 06 Β· 67 commits

Audio Arms Race + Methodology Crystallizes

  • RagChew TX audio chain (V5.1), RX engine rewrite (V5.2), stall fix then rollback again (V5.3.1)
  • First noise-reduction war: NR2 Gaussian rewrite killing the "digital artifacts"
  • ATR learning saga, four fixes in a row: false-SWR pollution β†’ stability buffer β†’ relay state β†’ dedup
  • FDE practice guide (05-10) β†’ Aladdin V2 (06-06) β†’ SDD surfaces as the vibe-coding core
Phase 4 Β· 2026-08 Β· 55 commits

The V5.7/V5.8 Overhaul

  • High-fidelity audio: 48 kHz full bandwidth / 64 kbps CBR / soft-knee limiter / watermark buffer
  • Entire FT8/CW decoder removed (models, frontend, automation dir) β€” subtraction as architecture
  • Comprehensive code audit (8b741b1) + IOLoop de-blocking series (F3 / MAIN_IOLOOP)
  • iOS background-audio fix, mono conversation recording timeline (specβ†’planβ†’impl, four-commit chain)
Phase 5 Β· 2026-09 Β· ongoing

Cross-Platform + Deep DSP + RC-001

  • V6.0.0 Windows installer: from personal tool to distributable software
  • NR2 SSB voice protection (V6.0.1): C-level patch + red-green acceptance + Latin-square A/B listening
  • RC-001 (09-14): IOLoop wedge freezing the web port + Bluetooth DAC churn silencing TX β€” first root cause found outside the code boundary

Five Recurring Problem Classes

Each has a full "fixed repeatedly until truly solved" story.

Threading & Event-Loop Blocking β€” the #1 Theme

DateBattleWhat Was Fixed
2026-03-06ba66892 / 1a072b3TX main-thread blocking, ATR broadcast thread safety
2026-03-07d4a40c2New-architecture rollback (the cost of over-engineering)
2026-08-09V5.8.1 / V5.8.2rigctld I/O into an executor (F3), pinned MAIN_IOLOOP
2026-08-28F2stream.write() moved off the IOLoop
2026-09-14RC-001 F4/F4bConstructor p.open() β€” the last blocking call standing
The first four times we "fixed wherever it hung". RC-001 finally turned it into a discipline β€” zero blocking on the IOLoop thread β€” backed by a watchdog that makes the discipline observable. From fixing points to fixing the surface: six months.

Audio Quality: Ears and Metrics on Two Tracks

RNNoise β†’ WDSP β†’ EMNR Gaussian rewrite (digital artifacts) β†’ sample-rate wars (watery sound) β†’ NR2 SSB voice protection (voice suppression, C patch). From "sounds wrong" to four testable assertions: voiceΞ” / noiseΞ” / LSD / jitter.

Device Fragility: Designing Around Unreliable Peripherals

ATR-1000 SYNC throttling, anti-disconnect, learning pollution, SWR guard, plus the Bluetooth DAC β€” the pattern is always the same: proxy isolation + cached answers + pressure control + anomaly observability. Assume every protocol peer can stall.

Safety: PTT Is the Only Physical Surface

PTT Safety Monitor (release-failure retry + TOT hard cap), 5-second no-frame auto-release, direction-aware state machine (R3), SWR>2 auto-retune guard, RC-001 forced release on the discard path. Software state can lie to you; the radio cannot β€” the verdict ultimately sinks to physical quantities.

Environment Boundary: The World Outside the Code

RC-001 pinned the root cause outside the system for the first time: a generic Bluetooth firmware never acknowledging the jitter-buffer config (error 312) β†’ CoreAudio stalls globally β†’ unrelated USB sound card dragged down. Probes moved into the system layer accordingly (unified log / bluetoothd / power-meter A/B).

What Actually Worked

Every entry carries commit or document evidence β€” and we honestly list what did not prove itself.

PracticeEvidenceVerdict
spec β†’ design β†’ plan β†’ tasks chain08-28 recording four-commit chain, 09-13 NR2 tasks 1–6βœ… zero rework on complex changes
Red-green acceptance (failing baseline first)3dc6319 "all baselines fail" β†’ tasks pass one by oneβœ… the only reliable path for "feels-like" quality
Metricized audio evaluation (A/B + Latin square + four metrics)09-13 full NR2 acceptanceβœ… ears drift, metrics don't
Postmortem culturePTT_Audio_Postmortem β†’ RC-001 numbered case seriesβœ… incidents become assets
Revert disciplined4a40c2, dab904a β€” two decisive rollbacksβœ… if the new is worse, go back
Feature pruningV5.7 removed FT8/CW; everything got more stableβœ… feature entropy is negatively correlated with reliability
CHANGELOG + tag discipline35 versions, all recordedβœ… the data foundation of this very retrospective
Data as truthATR power meter judged modulation when every software layer looked "fine"βœ… physical quantities pierce log illusions
Code-first docs + auditdocs/current/ + cross-check auditβœ… docs that don't rot
Big-bang architecture rewritesRolled back twice (AudioWorklet/Worker, buffer strategy)❌ not proven
"Optimization" without acceptance criteriaMultiple audio regressions caught by the user's ears❌ not proven

How Verification Evolved

The direction never changed: closer to physical truth, further from guessing.

1

Manual trial and error (early parent project) β€” fix whatever breaks.

2

Logs + power-meter observation (V4.5 ATR saga) β€” first time device readings were cross-checked against software behavior.

3

spec/plan + manual acceptance (V5.x) β€” complex changes started carrying a document chain.

4

Red-green tests + four metrics + A/B listening (V6.0.1) β€” felt quality became test assertions.

5

Runtime telemetry (V6.0.2) β€” IOLoop watchdog / ⏱️ timing probes / .prev death-scene log rotation.

6

Environmental A/B isolation (V6.0.2) β€” Bluetooth DAC disconnected as control: 11 transmissions, all properly modulated.

Looking Forward

Product

  • Multi-radio / multi-instance operations maturity (mrrc_multi.sh in place)
  • Windows package release channel normalized
  • Recording/playback/sharing loop (mono timeline β†’ QSO record assets)

Technology

  • Audio output selector (AudioContext.setSinkId) β€” decouple radio audio from the system default output
  • Host migration to 5 GHz Wi-Fi or wired β€” eliminate 2.4 GHz Bluetooth coexistence noise
  • WDSP tuning driven by metrics (LSD/jitter thresholds into CI)
  • Deeper ATR-1000 protocol work (faster learning, predictive tuning)

Engineering

  • Grow the reliability case series: RC-002+ filed by number; a pattern seen β‰₯3 times gets its own best-practice doc
  • Watchdog evolves from observation to self-healing (stall β†’ safe PTT release β†’ controlled restart)
  • Missing CI is the largest engineering debt: red-green scripts belong in automation
  • Test pyramid: unit layer β†’ integration layer (mock rigctld / mock PyAudio)

Method

  • Product Leverage for feature ordering: only leverage paths that are high-frequency in real QSOs
  • Keep the methodology growing out of the project β€” never design ahead of evidence

Seven Meta-Lessons

Each one was bought with a real incident or regression.

1

Fixing points instead of the surface lets the problem return wearing a new face. Thread blocking was fixed five times before it became a discipline. For recurring problem classes: enumerate every possible site, make a rule, install a probe β€” don't wait for the next incident.

2

Async moves bugs; it doesn't kill them. Every time you move a blocking call off a critical thread, first answer "where do the data and events go while it blocks?"

3

An environment problem is not a code problem. Before touching code, extend observability to the system boundary (OS logs, hardware readings). The ATR power meter and bluetoothd logs located the truth faster than any Python log.

4

Physical quantities are the ultimate assertion. Every software layer can "look fine"; transmit power cannot lie. When you suspect the software chain, find a hardware reading to cross-check first.

5

One human + AI works β€” but discipline cannot be skipped. AI accelerates execution, not judgment; AI acceleration without discipline just pays down debt faster into a wall.

6

Subtraction is an architectural skill. Removing FT8/CW, two rollbacks, menu slimming β€” every cut raised reliability or usability. Projects that dare to delete features get long-term room to evolve.

7

Documentation compounds. A 35-version CHANGELOG, a case library, and code-first docs let this retrospective be written entirely from data β€” no recollection, no polish, only evidence in git.

All Data Lives in the Repository

Sources for this retrospective: git log, CHANGELOG.md (35 versions), the RC-001 reliability case, the FDE practice guide, and the Aladdin V2 methodology β€” all open on GitHub.

View the Source Document