Project Retrospective · 2026-09

两年,
一次完整复盘

从 2024 年 10 月的第一行代码到 2026 年 9 月的 V6.0.2:六阶段演进、五类反复出现的问题、被证明有效的方法、验证手段的演化,以及面向未来的展望。所有结论由 git 全史与版本记录写成——没有回忆,没有美化,只有证据。

400+Commits 总计
35发布版本
6演进阶段
7元教训

数据概览

本仓(UHRR_mac,2026-03-06 起)206 commits;父项目 UHRR(2024-10 起)约 208 commits。合计 400+ 次提交、35 个版本。

月度节奏

3月 48 / 4月 4 / 5月 35 / 6月 32 / 7月 1 / 8月 55(最狠月份)/ 9月 31。低谷期是"用出来的"——产品在真实通联中跑,问题在积累。

发布峰值日

2026-08-09 单日 5 个版本(V5.7.1 → V5.8.2):RagChew 修复、ATR SWR 守卫、IOLoop 去阻塞、线程错位修复,一场集中爆发的大整修。

平台演化

树莓派/Linux(父项目)→ macOS(本仓起点,2026-03)→ Windows 安装包(V6.0.0,2026-09)。一套代码三个平台。

六阶段历程

每个阶段都由 git 提交链直接写成。

Phase 0 · 2024-10 → 2026-02

从零到可用(父项目)

  • V1.0 → V4.3:核心架构定型(Tornado + WebSocket + PyAudio + Hamlib + Opus)
  • 桌面/移动双界面、基础录音
  • FDE 驻场模式确立:作者自己(BG1SB)是第一个重度用户,日常通联即测试场
Phase 1 · 2026-03 · 48 commits

Mac 移植爆发期

  • ATR-1000 天调接入 saga:SYNC 节流、防断连、智能学习(V4.5.11→V4.5.18)
  • 首次线程化战役:TX AudioWorklet 重构 → 果断回滚(d4a40c2
  • 高品质语音版、WDSP、多实例部署、远程隧道、中英双语界面
Phase 2 · 2026-04 · 4 commits

静默期

  • 只有移动端正修复 + WDSP NF,月底 V5.0.0 移动端 UI 现代化
  • 低提交量 ≠ 停滞:这是真实使用积累问题的阶段
Phase 3 · 2026-05 → 06 · 67 commits

音质军备竞赛 + 方法落成

  • RagChew TX 音频链(V5.1)、RX 引擎重写(V5.2)、卡顿修复再回滚(V5.3.1)
  • 降噪第一战:NR2 Gaussian 重写消除"数码音"
  • ATR 学习 saga 四连修:假 SWR 污染 → 缓冲器 → 继电器保留 → 去重
  • FDE 实践指导书(05-10)→ Aladdin V2(06-06)→ SDD 浮出水面
Phase 4 · 2026-08 · 55 commits

V5.7/V5.8 大整修

  • 高保真音频:48kHz 全带宽 / 64kbps CBR / 软膝限幅 / 水印缓冲
  • 整体删除 FT8/CW 解码器(含模型与前端页)——减法即架构
  • 全面代码审查(8b741b1)+ IOLoop 去阻塞系列(F3 / MAIN_IOLOOP)
  • iOS 后台音频修复、单声道录音时间轴(spec→plan→实现 四连提交)
Phase 5 · 2026-09 · 进行中

跨平台 + 降噪深水区 + RC-001

  • V6.0.0 Windows 安装包:从自用工具到可分发的软件
  • NR2 SSB 语音保护(V6.0.1):C 层补丁 + 红绿验收 + 拉丁方 A/B 试听
  • RC-001(09-14):IOLoop 楔死致端口假死 + 蓝牙 DAC 抖动致 TX 静默——首次把根因追出代码边界

五类反复出现的问题

每一类都有"修了多次才根治"的完整故事。

线程与事件循环阻塞 —— 贯穿全程的第一主题

时间战役修的什么
2026-03-06ba66892 / 1a072b3TX 主线程阻塞、ATR 广播线程安全
2026-03-07d4a40c2新架构回滚(过度工程化的代价)
2026-08-09V5.8.1 / V5.8.2rigctld I/O 进执行器(F3)、MAIN_IOLOOP 固定
2026-08-28F2stream.write() 挪出 IOLoop
2026-09-14RC-001 F4/F4b构造函数 p.open()——最后一个漏网的阻塞点
前四次都是"哪里卡修哪里",RC-001 才把问题总结为纪律——IOLoop 线程零阻塞,并配看门狗把纪律变成可观测的约定。从"修点"到"修面"用了 6 个月。

音频质量:耳朵与指标的双轨演化

RNNoise → WDSP → EMNR Gaussian 重写(数码音)→ 采样率之争(水音)→ NR2 SSB 语音保护(吃语音,C 补丁)。从"听着不对"进化到四个指标断言:voiceΔ / noiseΔ / LSD / jitter

设备脆弱性:围着不可靠外设设计

ATR-1000 的 SYNC 节流、防断连、学习污染、SWR 守卫,加上蓝牙 DAC——模式是同一套:代理隔离 + 缓存应答 + 压力控制 + 异常观测。协议边界永远假设对端会卡。

安全:PTT 是唯一的物理安全面

PTT Safety Monitor(释放失败重试 + TOT 硬上限)、5 秒无帧收 PTT、方向感知状态机(R3)、SWR>2 自动调谐守卫、RC-001 丢弃路径强制释放。软件状态可能骗你,电台不会——判据最终下沉到物理量。

环境边界:代码外的世界

RC-001 首次把根因钉在系统外:杂牌蓝牙固件不应答 Jitter Buffer 配置(error 312)→ CoreAudio 全局阻塞 → 拖住无关的 USB 声卡。观测手段随之装进系统层(unified log / bluetoothd / 功率计 A/B)。

方法验证清单

每条都有提交或文档证据;并诚实列出没有证明有效的做法。

做法证据判定
spec → design → plan → tasks 链条08-28 录音四连提交、09-13 NR2 任务 1-6✅ 复杂改动零返工
红绿验收(先写会失败的基线)3dc6319 "基线均失败" → 任务逐个通过✅ 感觉型质量的唯一可靠路径
指标化音频评估(A/B + 拉丁方 + 四指标)09-13 全套 NR2 验收✅ 耳朵会漂移,指标不会
Postmortem 文化PTT_Audio_Postmortem → RC-001 案例编号制✅ 事故变资产
revert 纪律d4a40c2dab904a 两次果断回滚✅ 新不如旧就退
功能裁剪V5.7 删 FT8/CW 后整体更稳✅ 功能熵与可靠性负相关
CHANGELOG + tag 纪律35 个版本全程记录✅ 本复盘的数据基础
数据即真相ATR 功率计判调制(软件每层都"正常"时)✅ 物理量击穿日志幻觉
code-first docs + auditdocs/current/ + 交叉核对✅ 文档不过期
大而全的新架构重构两次回滚(AudioWorklet/Worker、缓冲策略)❌ 未证明有效
无验收标准的"优化"多次音质回归后靠用户耳朵报警❌ 未证明有效

验证手段的演化史

方向始终一致:离物理真相更近,离猜测更远。

1

手工试错(父项目早期)——有什么修什么。

2

日志 + 功率计观察(V4.5 ATR saga)——第一次用设备读数对照软件行为。

3

spec/plan + 手动验收(V5.x)——复杂改动开始有文档链。

4

红绿测试 + 四指标 + A/B 试听(V6.0.1)——感觉型质量变成测试断言。

5

运行时遥测(V6.0.2)——IOLoop 看门狗 / ⏱️ 耗时打点 / .prev 死亡现场轮转。

6

环境 A/B 隔离实验(V6.0.2)——断开蓝牙 DAC 对照,11 段发射全部正常调制。

未来展望

产品

  • 多电台/多实例运营成熟化(mrrc_multi.sh 已就位)
  • Windows 包发布渠道常态化
  • 录音/回放/分享闭环(单声道时间轴 → 通联记录资产)

技术

  • 音频输出选择器(setSinkId)——电台音频与系统默认输出解耦
  • 主机迁移 5GHz Wi-Fi 或有线——消除 2.4G 蓝牙共存底噪
  • WDSP 调优转入指标驱动(LSD/jitter 阈值进 CI)
  • ATR-1000 协议层继续深挖(学习加速、预测调谐)

工程

  • 可靠性案例系列做大:RC-002+ 按编号入库,模式 ≥3 次即提炼最佳实践
  • 看门狗从观测升级到自愈(stall → 安全收 PTT → 受控重启)
  • CI 缺失是最大工程债:红绿脚本接入自动化
  • 测试金字塔:单元层 → 集成层(mock rigctld / mock PyAudio)

方法

  • Product Leverage 原则排序特性:只杠杆真实通联中高频的路径
  • 方法论保持"从项目里长出来"的节奏,不超前设计

七条元教训

每一条都由真实事故或回归换来。

1

修点不修面,问题会换着面孔回来。线程阻塞修了 5 次才变成纪律。对反复出现的同类问题:枚举所有可能点 + 立规矩 + 装探针,而不是等下一次事故。

2

异步化移动 bug,不消灭 bug。每把一个阻塞点挪出关键线程,必须先回答"阻塞窗口内到达的数据和事件去哪了"。

3

环境问题不等于代码问题。改代码之前,把观测做到系统边界(OS 日志、硬件读数)。ATR 功率计和 bluetoothd 日志比任何 Python 日志都更快定位真相。

4

物理量是终极断言。软件每一层都可以"看起来正常",发射功率不会撒谎。怀疑软件链路时,先找一个硬件读数对照。

5

1 人 + AI 的形态被验证了,但纪律不能省。AI 加速的是执行,不是判断;没有纪律的 AI 加速只是把债还得更快。

6

减法是架构能力。删 FT8/CW、两次回滚、菜单瘦身——每次"砍"都对应可靠性或可用性的上升。敢于删功能的项目才有长期演进空间。

7

文档的复利。CHANGELOG 35 版 + 案例库 + code-first docs,让这份复盘完全由数据写成——没有回忆,没有美化,只有 git 里的证据。

数据全在仓库里

本复盘的数据源:git logCHANGELOG.md(35 个版本)、RC-001 可靠性案例、FDE 实践指导书、阿拉丁 V2 方法论——全部开源在 GitHub。

查看原始文档