rigplane 2.7.0__tar.gz → 2.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1277) hide show
  1. {rigplane-2.7.0 → rigplane-2.7.2}/PKG-INFO +1 -1
  2. {rigplane-2.7.0 → rigplane-2.7.2}/docs/CHANGELOG.md +23 -1
  3. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/rx-player.test.ts +76 -0
  4. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/audio-manager.ts +4 -0
  5. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/rx-player.ts +81 -6
  6. {rigplane-2.7.0 → rigplane-2.7.2}/pyproject.toml +1 -1
  7. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/bridge.py +30 -5
  8. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/usb_driver.py +54 -8
  9. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/_icom_serial_base.py +81 -5
  10. rigplane-2.7.2/src/rigplane/backends/icom7610/serial.py +52 -0
  11. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/server.py +23 -3
  12. rigplane-2.7.0/src/rigplane/web/static/assets/ControlButtonDemo-CbVyzA0h.js → rigplane-2.7.2/src/rigplane/web/static/assets/ControlButtonDemo-CnelvEOz.js +1 -1
  13. rigplane-2.7.0/src/rigplane/web/static/assets/index-BRBm4QAp.js → rigplane-2.7.2/src/rigplane/web/static/assets/index-MRf0y8eM.js +21 -21
  14. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/index.html +1 -1
  15. rigplane-2.7.2/tests/hardware/test_x6200_serial_tx_smoke.py +60 -0
  16. rigplane-2.7.2/tests/integration/test_x6200_audio_scope_smoke.py +100 -0
  17. rigplane-2.7.2/tests/test_audio_scope_dispatch.py +265 -0
  18. rigplane-2.7.2/tests/test_serial_backend_tx_mor242.py +244 -0
  19. rigplane-2.7.2/tests/test_usb_audio_channel_clamp_mor238.py +267 -0
  20. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_x6200_rx_audio_mor236.py +17 -6
  21. {rigplane-2.7.0 → rigplane-2.7.2}/uv.lock +1 -1
  22. rigplane-2.7.0/src/rigplane/backends/icom7610/serial.py +0 -171
  23. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/analyze-failure.md +0 -0
  24. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/audit-ui.md +0 -0
  25. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/decompose-issue.md +0 -0
  26. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/generate-tests.md +0 -0
  27. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/next.md +0 -0
  28. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/refactor.md +0 -0
  29. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/regression-check.md +0 -0
  30. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/scan-issues.md +0 -0
  31. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/commands/solve-issue.md +0 -0
  32. {rigplane-2.7.0 → rigplane-2.7.2}/.claude/skills/release/SKILL.md +0 -0
  33. {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  34. {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  35. {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/epic.yml +0 -0
  36. {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
  37. {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/radio_report.md +0 -0
  38. {rigplane-2.7.0 → rigplane-2.7.2}/.github/ISSUE_TEMPLATE/ui-component.yml +0 -0
  39. {rigplane-2.7.0 → rigplane-2.7.2}/.github/pull_request_template.md +0 -0
  40. {rigplane-2.7.0 → rigplane-2.7.2}/.github/scripts/check-rebrand-allowlist.sh +0 -0
  41. {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/agent-review-gate.yml +0 -0
  42. {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/docs.yml +0 -0
  43. {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/full.yml +0 -0
  44. {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/publish.yml +0 -0
  45. {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/quick.yml +0 -0
  46. {rigplane-2.7.0 → rigplane-2.7.2}/.github/workflows/rebrand-gate.yml +0 -0
  47. {rigplane-2.7.0 → rigplane-2.7.2}/.gitignore +0 -0
  48. {rigplane-2.7.0 → rigplane-2.7.2}/.importlinter +0 -0
  49. {rigplane-2.7.0 → rigplane-2.7.2}/AGENTS.md +0 -0
  50. {rigplane-2.7.0 → rigplane-2.7.2}/ARCHITECTURE.md +0 -0
  51. {rigplane-2.7.0 → rigplane-2.7.2}/CHANGELOG.md +0 -0
  52. {rigplane-2.7.0 → rigplane-2.7.2}/CLAUDE.md +0 -0
  53. {rigplane-2.7.0 → rigplane-2.7.2}/CONTRIBUTING.md +0 -0
  54. {rigplane-2.7.0 → rigplane-2.7.2}/LICENSE +0 -0
  55. {rigplane-2.7.0 → rigplane-2.7.2}/README.md +0 -0
  56. {rigplane-2.7.0 → rigplane-2.7.2}/ROADMAP.md +0 -0
  57. {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/_config.toml +0 -0
  58. {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/arrl-hf.toml +0 -0
  59. {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/broadcast.toml +0 -0
  60. {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/iaru-r1.toml +0 -0
  61. {rigplane-2.7.0 → rigplane-2.7.2}/band-plans/utility.toml +0 -0
  62. {rigplane-2.7.0 → rigplane-2.7.2}/docs/4f4bcd28cb8d426ca58ec08b5035541e.txt +0 -0
  63. {rigplane-2.7.0 → rigplane-2.7.2}/docs/AUDIO_STREAMING_PROFILE.md +0 -0
  64. {rigplane-2.7.0 → rigplane-2.7.2}/docs/CNAME +0 -0
  65. {rigplane-2.7.0 → rigplane-2.7.2}/docs/EXTENDED_PROTOCOL_RESEARCH.md +0 -0
  66. {rigplane-2.7.0 → rigplane-2.7.2}/docs/PERFORMANCE.md +0 -0
  67. {rigplane-2.7.0 → rigplane-2.7.2}/docs/PROJECT.md +0 -0
  68. {rigplane-2.7.0 → rigplane-2.7.2}/docs/SECURITY.md +0 -0
  69. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/audio.md +0 -0
  70. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/auth.md +0 -0
  71. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/backends-icom7610-drivers.md +0 -0
  72. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/backends-icom7610.md +0 -0
  73. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/backends.md +0 -0
  74. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/command-catalog.md +0 -0
  75. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/commander.md +0 -0
  76. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/commands.md +0 -0
  77. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/exceptions.md +0 -0
  78. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/public-api-surface.md +0 -0
  79. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/radio.md +0 -0
  80. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/radios.md +0 -0
  81. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/rig-loader.md +0 -0
  82. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/rigctld.md +0 -0
  83. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/scope.md +0 -0
  84. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/sync.md +0 -0
  85. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/transport.md +0 -0
  86. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/types.md +0 -0
  87. {rigplane-2.7.0 → rigplane-2.7.2}/docs/api/web.md +0 -0
  88. {rigplane-2.7.0 → rigplane-2.7.2}/docs/architecture/open-core-policy.md +0 -0
  89. {rigplane-2.7.0 → rigplane-2.7.2}/docs/assets/scope-example.png +0 -0
  90. {rigplane-2.7.0 → rigplane-2.7.2}/docs/capabilities-matrix.md +0 -0
  91. {rigplane-2.7.0 → rigplane-2.7.2}/docs/contracts/diagnostic-bundle-v1.md +0 -0
  92. {rigplane-2.7.0 → rigplane-2.7.2}/docs/contracts/diagnostic-bundle-v2.md +0 -0
  93. {rigplane-2.7.0 → rigplane-2.7.2}/docs/contracts/validation-matrix-v1.md +0 -0
  94. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/audio-recipes.md +0 -0
  95. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/cli.md +0 -0
  96. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/commands.md +0 -0
  97. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/configuration.md +0 -0
  98. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/connection.md +0 -0
  99. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/diagnostic-reports.md +0 -0
  100. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/hamlib-rigctld-provider.md +0 -0
  101. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic705-usb-setup.md +0 -0
  102. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic7300-usb-setup.md +0 -0
  103. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic7610-usb-setup.md +0 -0
  104. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/ic9700-usb-setup.md +0 -0
  105. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/installation.md +0 -0
  106. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/profiles.md +0 -0
  107. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/quickstart.md +0 -0
  108. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/radios.md +0 -0
  109. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/rig-profiles.md +0 -0
  110. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/troubleshooting.md +0 -0
  111. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/web-ui.md +0 -0
  112. {rigplane-2.7.0 → rigplane-2.7.2}/docs/guide/wsjtx-setup.md +0 -0
  113. {rigplane-2.7.0 → rigplane-2.7.2}/docs/i18n/core-string-inventory.md +0 -0
  114. {rigplane-2.7.0 → rigplane-2.7.2}/docs/i18n/locale-contract.md +0 -0
  115. {rigplane-2.7.0 → rigplane-2.7.2}/docs/i18n/translating.md +0 -0
  116. {rigplane-2.7.0 → rigplane-2.7.2}/docs/index.md +0 -0
  117. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/architecture.md +0 -0
  118. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/cli-design.md +0 -0
  119. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/contributing.md +0 -0
  120. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/github-project-workflow.md +0 -0
  121. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/hamlib-provider-rollout.md +0 -0
  122. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/protocol.md +0 -0
  123. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/raw-civ-transactions.md +0 -0
  124. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/reliability-semantics.md +0 -0
  125. {rigplane-2.7.0 → rigplane-2.7.2}/docs/internals/rfc-audio-v1-mini.md +0 -0
  126. {rigplane-2.7.0 → rigplane-2.7.2}/docs/migrate.md +0 -0
  127. {rigplane-2.7.0 → rigplane-2.7.2}/docs/operations/managed-runtime-packaging.md +0 -0
  128. {rigplane-2.7.0 → rigplane-2.7.2}/docs/opuslib-macos-fix.md +0 -0
  129. {rigplane-2.7.0 → rigplane-2.7.2}/docs/overrides/main.html +0 -0
  130. {rigplane-2.7.0 → rigplane-2.7.2}/docs/parity/README.md +0 -0
  131. {rigplane-2.7.0 → rigplane-2.7.2}/docs/parity/ic7610_command_matrix.json +0 -0
  132. {rigplane-2.7.0 → rigplane-2.7.2}/docs/parity/test_mapping.md +0 -0
  133. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-03-07-ui-architecture.md +0 -0
  134. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-05-desktop-companion-architecture.md +0 -0
  135. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-09-audio-backend-design.md +0 -0
  136. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-frontend-migration-plan.md +0 -0
  137. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-parity-matrix.md +0 -0
  138. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-presentation-architecture.md +0 -0
  139. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-rx-audio-trace.md +0 -0
  140. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-shared-frontend-runtime-contract.md +0 -0
  141. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-11-v2-lcd-runtime-audit.md +0 -0
  142. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-12-architecture-presentation.html +0 -0
  143. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-12-target-frontend-architecture.md +0 -0
  144. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-desktop-meters-panel.md +0 -0
  145. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-lcd-display-enhancements.md +0 -0
  146. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-mobile-ia.md +0 -0
  147. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-receiver-activation.md +0 -0
  148. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-spectrum-controls.md +0 -0
  149. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-18-ui-refinements-execution.md +0 -0
  150. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-19-lcd-layout-redesign-v2.md +0 -0
  151. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-19-lcd-layout-redesign.md +0 -0
  152. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-modularization-discovery.md +0 -0
  153. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-modularization-plan.md +0 -0
  154. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-panel-adapter-migration.md +0 -0
  155. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-04-29-ui-v1-deprecation-audit.md +0 -0
  156. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-03-diagnostic-data-collection-design.md +0 -0
  157. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-07-audio-route-resolver-design.md +0 -0
  158. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-audio-capability-probing.md +0 -0
  159. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-audio-codec-policy.md +0 -0
  160. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-audio-profile-policy-audit.md +0 -0
  161. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-08-usb-audio-negotiation.md +0 -0
  162. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-23-hamlib-provider-contract.md +0 -0
  163. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-28-real-radio-validation-matrix.md +0 -0
  164. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/2026-05-28-universal-validation-matrix.md +0 -0
  165. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/archive/2026-03-04-dx-cluster.md +0 -0
  166. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/archive/2026-03-m5-m6-roadmap.md +0 -0
  167. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/archive/2026-04-19-lcd-twin-skins.md +0 -0
  168. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/build_orphan_report.py +0 -0
  169. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/classify_cycle_edges.py +0 -0
  170. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/cycles-classified.md +0 -0
  171. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/cycles.txt +0 -0
  172. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/discovery_graph.py +0 -0
  173. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/external-usage.md +0 -0
  174. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/file-inventory.json +0 -0
  175. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/file-inventory.md +0 -0
  176. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/import-graph.dot +0 -0
  177. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/importlinter-config-draft.ini +0 -0
  178. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/init-snapshot.md +0 -0
  179. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/orphan-candidates.md +0 -0
  180. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/tach-config-draft.toml +0 -0
  181. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/test-inventory.md +0 -0
  182. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/discovery-artifacts/tooling-assessment.md +0 -0
  183. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/00-epic-final.md +0 -0
  184. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/00-epic.md +0 -0
  185. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/01-skeleton.md +0 -0
  186. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/02-core-foundationals.md +0 -0
  187. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/03-core-contracts.md +0 -0
  188. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/04-commands.md +0 -0
  189. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/05-profiles.md +0 -0
  190. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/06-scope.md +0 -0
  191. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/07-audio.md +0 -0
  192. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/08-runtime-radio.md +0 -0
  193. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/09-runtime-mixins.md +0 -0
  194. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/10-runtime-pollers.md +0 -0
  195. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/11-discovery-to-backends.md +0 -0
  196. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/12-cli.md +0 -0
  197. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/13-import-linter.md +0 -0
  198. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/14-followup-tests.md +0 -0
  199. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/15-followup-web-startup.md +0 -0
  200. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/2026-05-07-core-audio-pipeline-test-harness.md +0 -0
  201. {rigplane-2.7.0 → rigplane-2.7.2}/docs/plans/issue-drafts/2026-05-07-core-audio-route-resolver.md +0 -0
  202. {rigplane-2.7.0 → rigplane-2.7.2}/docs/radio-protocol.md +0 -0
  203. {rigplane-2.7.0 → rigplane-2.7.2}/docs/robots.txt +0 -0
  204. {rigplane-2.7.0 → rigplane-2.7.2}/docs/screenshots/amber-lcd.png +0 -0
  205. {rigplane-2.7.0 → rigplane-2.7.2}/docs/screenshots/hero.png +0 -0
  206. {rigplane-2.7.0 → rigplane-2.7.2}/docs/screenshots/lcd-scope.png +0 -0
  207. {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/running-validation.md +0 -0
  208. {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/ftx1.json +0 -0
  209. {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/ic7300.json +0 -0
  210. {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/tx500.json +0 -0
  211. {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/templates/x6200.json +0 -0
  212. {rigplane-2.7.0 → rigplane-2.7.2}/docs/validation/universal-matrix.md +0 -0
  213. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/.gitignore +0 -0
  214. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/README.md +0 -0
  215. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/eslint.config.js +0 -0
  216. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/index.html +0 -0
  217. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/package-lock.json +0 -0
  218. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/package.json +0 -0
  219. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/playwright.config.ts +0 -0
  220. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/playwright.i18n.config.ts +0 -0
  221. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/pnpm-lock.yaml +0 -0
  222. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/apple-touch-icon.png +0 -0
  223. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/lockup-dark.svg +0 -0
  224. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/lockup-light.svg +0 -0
  225. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/lockup-mono.svg +0 -0
  226. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/mark-dark.svg +0 -0
  227. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/mark-light.svg +0 -0
  228. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/mark-mono.svg +0 -0
  229. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/marketing/github-social-preview.png +0 -0
  230. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/marketing/readme-banner.png +0 -0
  231. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/wordmark-dark.svg +0 -0
  232. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/wordmark-light.svg +0 -0
  233. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/brand/wordmark-mono.svg +0 -0
  234. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon-16.png +0 -0
  235. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon-32.png +0 -0
  236. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon-48.png +0 -0
  237. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicon.ico +0 -0
  238. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-128.png +0 -0
  239. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-16.png +0 -0
  240. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-180.png +0 -0
  241. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-192.png +0 -0
  242. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-256.png +0 -0
  243. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-32.png +0 -0
  244. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-48.png +0 -0
  245. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-512.png +0 -0
  246. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon-64.png +0 -0
  247. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/ink/favicon.ico +0 -0
  248. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-128.png +0 -0
  249. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-16.png +0 -0
  250. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-180.png +0 -0
  251. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-192.png +0 -0
  252. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-256.png +0 -0
  253. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-32.png +0 -0
  254. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-48.png +0 -0
  255. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-512.png +0 -0
  256. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon-64.png +0 -0
  257. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/paper/favicon.ico +0 -0
  258. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-128.png +0 -0
  259. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-16.png +0 -0
  260. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-180.png +0 -0
  261. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-192.png +0 -0
  262. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-256.png +0 -0
  263. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-32.png +0 -0
  264. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-48.png +0 -0
  265. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-512.png +0 -0
  266. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/favicons/transparent/favicon-64.png +0 -0
  267. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/manifest.json +0 -0
  268. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/og-image.png +0 -0
  269. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/pwa-192x192.png +0 -0
  270. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/pwa-512x512.png +0 -0
  271. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/public/twitter-card.png +0 -0
  272. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/scripts/i18n-check.mjs +0 -0
  273. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/App.svelte +0 -0
  274. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/app.css +0 -0
  275. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/assets/svelte.svg +0 -0
  276. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/shared/Toast.svelte +0 -0
  277. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/shared/__tests__/Toast.component.test.ts +0 -0
  278. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/BandPlanOverlay.svelte +0 -0
  279. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/DxOverlay.svelte +0 -0
  280. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/EiBiBrowser.svelte +0 -0
  281. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/ScopeSettingsPopover.svelte +0 -0
  282. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/SpectrumCanvas.svelte +0 -0
  283. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/SpectrumPanel.svelte +0 -0
  284. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/SpectrumToolbar.svelte +0 -0
  285. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/WaterfallCanvas.svelte +0 -0
  286. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/BandPlanOverlay.component.test.ts +0 -0
  287. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/DxOverlay.test.ts +0 -0
  288. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/EiBiBrowser.test.ts +0 -0
  289. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/SpectrumPanel.component.test.ts +0 -0
  290. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/SpectrumToolbar.component.test.ts +0 -0
  291. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/band-plan-overlay.test.ts +0 -0
  292. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/click-to-tune.test.ts +0 -0
  293. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/passband-geometry.test.ts +0 -0
  294. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/spectrum-panel-logic.test.ts +0 -0
  295. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/spectrum-toolbar.test.ts +0 -0
  296. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/__tests__/tuning-indicator.test.ts +0 -0
  297. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/band-plan-logic.ts +0 -0
  298. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/passband-geometry.ts +0 -0
  299. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/spectrum-logic.ts +0 -0
  300. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components/spectrum/spectrum-toolbar-logic.ts +0 -0
  301. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/AttenuatorControl.svelte +0 -0
  302. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/BandSelector.svelte +0 -0
  303. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/BottomSheet.svelte +0 -0
  304. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/CollapsiblePanel.svelte +0 -0
  305. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/ControlButtonDemo.svelte +0 -0
  306. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/InstallPrompt.svelte +0 -0
  307. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/LanguageSelector.svelte +0 -0
  308. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/PttFab.svelte +0 -0
  309. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/PullToRefresh.svelte +0 -0
  310. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/SegmentedButton.svelte +0 -0
  311. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/StatusBadge.svelte +0 -0
  312. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/ThemePicker.svelte +0 -0
  313. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/ValueControlLab.svelte +0 -0
  314. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/AttenuatorControl.test.ts +0 -0
  315. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/BandSelector.test.ts +0 -0
  316. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/BottomSheet.test.ts +0 -0
  317. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/CollapsiblePanel.test.ts +0 -0
  318. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/InstallPrompt.test.ts +0 -0
  319. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/LanguageSelector.test.ts +0 -0
  320. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/PullToRefresh.test.ts +0 -0
  321. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/SegmentedButton.test.ts +0 -0
  322. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/StatusBadge.test.ts +0 -0
  323. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/__tests__/broadcast-presets.test.ts +0 -0
  324. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/band-utils.ts +0 -0
  325. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/broadcast-presets.ts +0 -0
  326. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/button-tokens.css +0 -0
  327. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/control-button.css +0 -0
  328. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/install-prompt-utils.ts +0 -0
  329. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/status-badge-style.ts +0 -0
  330. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/BipolarRenderer.svelte +0 -0
  331. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/DiscreteRenderer.svelte +0 -0
  332. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/DualParamRenderer.svelte +0 -0
  333. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/HBarRenderer.svelte +0 -0
  334. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/KnobRenderer.svelte +0 -0
  335. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/ValueControl.svelte +0 -0
  336. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/__tests__/ValueControl.test.ts +0 -0
  337. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/__tests__/value-control-core.test.ts +0 -0
  338. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/index.ts +0 -0
  339. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/skin.ts +0 -0
  340. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/skins/ProfessionalKnob.svelte +0 -0
  341. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/skins/index.ts +0 -0
  342. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/value-control-core.ts +0 -0
  343. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/controls/value-control/value-control.css +0 -0
  344. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/dialogs/SendReportDialog.svelte +0 -0
  345. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/dialogs/__tests__/SendReportDialog.test.ts +0 -0
  346. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/FrequencyDisplay.svelte +0 -0
  347. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/FrequencyDisplayInteractive.svelte +0 -0
  348. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/__tests__/FrequencyDisplay.test.ts +0 -0
  349. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/__tests__/frequency-tuning.test.ts +0 -0
  350. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/frequency-format.ts +0 -0
  351. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/display/frequency-tuning.ts +0 -0
  352. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/KeyboardHandler.svelte +0 -0
  353. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/LcdLayout.svelte +0 -0
  354. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/LeftSidebar.svelte +0 -0
  355. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/MobileNav.svelte +0 -0
  356. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/MobileRadioLayout.svelte +0 -0
  357. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/RadioLayout.svelte +0 -0
  358. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/RightSidebar.svelte +0 -0
  359. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/StatusBar.svelte +0 -0
  360. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/VfoHeader.svelte +0 -0
  361. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/KeyboardHandler.test.ts +0 -0
  362. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/LeftSidebar.test.ts +0 -0
  363. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/MobileRadioLayout.component.svelte.test.ts +0 -0
  364. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/RadioLayout.test.ts +0 -0
  365. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/SpectrumPanelStub.svelte +0 -0
  366. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/keyboard-map.test.ts +0 -0
  367. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/mobile-layout-logic.test.ts +0 -0
  368. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/mobile-nav.test.ts +0 -0
  369. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/top-row-visual-regression.test.ts +0 -0
  370. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/vfo-header.test.ts +0 -0
  371. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/__tests__/vfo-layout-tokens.test.ts +0 -0
  372. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/keyboard-map.ts +0 -0
  373. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/layout-utils.ts +0 -0
  374. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/mobile-chip-bar.svelte +0 -0
  375. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/mobile-layout-logic.ts +0 -0
  376. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/mobile-nav-utils.ts +0 -0
  377. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/responsive.css +0 -0
  378. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/shortcut-hints.ts +0 -0
  379. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/layout/vfo-layout-tokens.ts +0 -0
  380. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/BarGauge.svelte +0 -0
  381. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/LinearSMeter.svelte +0 -0
  382. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/NeedleGauge.svelte +0 -0
  383. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/SMeterDemo.svelte +0 -0
  384. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/__tests__/BarGauge.test.ts +0 -0
  385. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/__tests__/LinearSMeter.test.ts +0 -0
  386. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/__tests__/NeedleGauge.test.ts +0 -0
  387. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/bar-gauge-utils.ts +0 -0
  388. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/needle-gauge-utils.ts +0 -0
  389. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/meters/smeter-scale.ts +0 -0
  390. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/AgcPanel.svelte +0 -0
  391. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/AntennaPanel.svelte +0 -0
  392. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/AudioRoutingControl.svelte +0 -0
  393. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/CwPanel.svelte +0 -0
  394. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/DockMeterPanel.svelte +0 -0
  395. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/DspPanel.svelte +0 -0
  396. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/EssentialsPanel.svelte +0 -0
  397. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/FilterPanel.svelte +0 -0
  398. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/MemoryPanel.svelte +0 -0
  399. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/MeterPanel.svelte +0 -0
  400. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/MetersDockPanel.svelte +0 -0
  401. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/ModePanel.svelte +0 -0
  402. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/RfFrontEnd.svelte +0 -0
  403. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/RitXitPanel.svelte +0 -0
  404. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/RxAudioPanel.svelte +0 -0
  405. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/ScanPanel.svelte +0 -0
  406. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/TxPanel.svelte +0 -0
  407. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/VoxPanel.svelte +0 -0
  408. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/AgcPanel.test.ts +0 -0
  409. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/AudioRoutingControl.test.ts +0 -0
  410. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/CwPanel.component.test.ts +0 -0
  411. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/DspPanel.component.test.ts +0 -0
  412. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/DspPanel.test.ts +0 -0
  413. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/FilterPanel.test.ts +0 -0
  414. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/MeterPanel.test.ts +0 -0
  415. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/MetersDockPanel.test.ts +0 -0
  416. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/ModePanel.test.ts +0 -0
  417. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/RfFrontEnd.test.ts +0 -0
  418. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/RitXitPanel.test.ts +0 -0
  419. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/RxAudioPanel.test.ts +0 -0
  420. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/TxPanel.test.ts +0 -0
  421. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/cw-panel-logic.test.ts +0 -0
  422. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/dsp-panel-logic.test.ts +0 -0
  423. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/__tests__/filter-controls.test.ts +0 -0
  424. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/agc-utils.ts +0 -0
  425. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/AudioSpectrumCanvas.svelte +0 -0
  426. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/AudioSpectrumPanel.svelte +0 -0
  427. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/__tests__/audio-spectrum-renderer.test.ts +0 -0
  428. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-scope/audio-spectrum-renderer.ts +0 -0
  429. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/audio-utils.ts +0 -0
  430. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/cw-panel-logic.ts +0 -0
  431. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/dsp-panel-logic.ts +0 -0
  432. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/dsp-utils.ts +0 -0
  433. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/filter-controls.ts +0 -0
  434. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/filter-utils.ts +0 -0
  435. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberAfScope.svelte +0 -0
  436. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberCockpit.svelte +0 -0
  437. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberFilterGhost.svelte +0 -0
  438. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberFrequency.svelte +0 -0
  439. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberIndStrip.svelte +0 -0
  440. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberLcdDisplay.svelte +0 -0
  441. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberMemoryStrip.svelte +0 -0
  442. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberScope.svelte +0 -0
  443. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberSmeter.svelte +0 -0
  444. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberSparkline.svelte +0 -0
  445. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/AmberTelemetryStrip.svelte +0 -0
  446. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/LcdContrastControl.svelte +0 -0
  447. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/LcdDisplayModeControl.svelte +0 -0
  448. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/VfoControlPanel.svelte +0 -0
  449. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/__tests__/lcd-components.test.ts +0 -0
  450. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/__tests__/scope-frame.test.ts +0 -0
  451. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/lcd/lcd-vintage.css +0 -0
  452. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/meter-utils.test.ts +0 -0
  453. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/meter-utils.ts +0 -0
  454. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/rf-frontend-utils.ts +0 -0
  455. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/rit-utils.ts +0 -0
  456. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/tx-utils.ts +0 -0
  457. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/vfo/DualVfoDisplay.svelte +0 -0
  458. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/panels/vfo/__tests__/DualVfoDisplay.test.ts +0 -0
  459. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/fonts-digital.css +0 -0
  460. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/fonts.css +0 -0
  461. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/index.ts +0 -0
  462. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/theme-switcher.ts +0 -0
  463. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/amoled-black.css +0 -0
  464. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/ayu-dark.css +0 -0
  465. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/catppuccin-latte.css +0 -0
  466. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/catppuccin-mocha.css +0 -0
  467. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/crt-green.css +0 -0
  468. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/custom-ic7610.css +0 -0
  469. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/dracula.css +0 -0
  470. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/github-light.css +0 -0
  471. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/gruvbox-dark.css +0 -0
  472. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/gruvbox-light.css +0 -0
  473. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/high-contrast.css +0 -0
  474. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/index.ts +0 -0
  475. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/lcd-blue.css +0 -0
  476. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/lcd-warm.css +0 -0
  477. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/nixie-tube.css +0 -0
  478. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/nord-light.css +0 -0
  479. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/nord.css +0 -0
  480. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/one-dark.css +0 -0
  481. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/solarized-dark.css +0 -0
  482. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/solarized-light.css +0 -0
  483. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/themes/tokyo-night.css +0 -0
  484. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/tokens.css +0 -0
  485. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/crt-green.css +0 -0
  486. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/index.ts +0 -0
  487. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/lcd-blue.css +0 -0
  488. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/theme/vfo-themes/nixie-tube.css +0 -0
  489. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/ActiveReceiverToggle.svelte +0 -0
  490. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/VfoOps.svelte +0 -0
  491. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/VfoPanel.svelte +0 -0
  492. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/__tests__/ActiveReceiverToggle.test.ts +0 -0
  493. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/__tests__/VfoOps.test.ts +0 -0
  494. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/__tests__/VfoPanel.test.ts +0 -0
  495. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/vfo-ops-utils.ts +0 -0
  496. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/vfo/vfo-utils.ts +0 -0
  497. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/double-click.test.ts +0 -0
  498. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/focus-mode-race.test.ts +0 -0
  499. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/keyboard-wiring.test.ts +0 -0
  500. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/state-adapter.test.ts +0 -0
  501. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/__tests__/vfo-wiring.test.ts +0 -0
  502. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/command-bus.ts +0 -0
  503. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/double-click.ts +0 -0
  504. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/components-v2/wiring/state-adapter.ts +0 -0
  505. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/ControlButton.svelte +0 -0
  506. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/DotButton.svelte +0 -0
  507. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/FillButton.svelte +0 -0
  508. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/HardwareButton.svelte +0 -0
  509. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/HardwarePlainButton.svelte +0 -0
  510. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/StatusIndicator.svelte +0 -0
  511. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/__tests__/ControlButton.test.ts +0 -0
  512. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/__tests__/ControlledHarness.svelte +0 -0
  513. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/index.ts +0 -0
  514. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/roleMapping.ts +0 -0
  515. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/Button/types.ts +0 -0
  516. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/SegmentedControl/index.ts +0 -0
  517. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/__tests__/drag-reorder.test.ts +0 -0
  518. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/__tests__/migrate-legacy-storage.test.ts +0 -0
  519. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/actions/keyboard.ts +0 -0
  520. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/api/__tests__/diagnostics.test.ts +0 -0
  521. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/api/diagnostics.ts +0 -0
  522. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/audio-manager.test.ts +0 -0
  523. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/constants.test.ts +0 -0
  524. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/__tests__/tx-mic.test.ts +0 -0
  525. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/constants.ts +0 -0
  526. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/audio/tx-mic.ts +0 -0
  527. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/data/__tests__/arrl-band-plan.test.ts +0 -0
  528. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/data/arrl-band-plan.ts +0 -0
  529. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/drag-reorder.svelte.ts +0 -0
  530. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/gestures/gesture-recognizer.ts +0 -0
  531. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/gestures/use-gesture.ts +0 -0
  532. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/CONTRIBUTING.md +0 -0
  533. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/index.test.ts +0 -0
  534. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/locale-contract.test.ts +0 -0
  535. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/plural.test.ts +0 -0
  536. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/pseudo-locale.smoke.test.ts +0 -0
  537. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/pseudo.test.ts +0 -0
  538. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/runtime.test.ts +0 -0
  539. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/__tests__/store.test.ts +0 -0
  540. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/index.ts +0 -0
  541. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locale-contract.ts +0 -0
  542. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locales/en-US.json +0 -0
  543. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locales/ja-JP.json +0 -0
  544. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/locales/ru-RU.json +0 -0
  545. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/plural.ts +0 -0
  546. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/pseudo.ts +0 -0
  547. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/runtime.ts +0 -0
  548. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/store.svelte.ts +0 -0
  549. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/i18n/types.ts +0 -0
  550. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/LocalExtensionsHost.svelte +0 -0
  551. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/__tests__/dock-layout.test.ts +0 -0
  552. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/__tests__/host-api.test.ts +0 -0
  553. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/__tests__/manifest.test.ts +0 -0
  554. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/dock-layout.ts +0 -0
  555. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/host-api.ts +0 -0
  556. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/keyboard-scope.ts +0 -0
  557. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/local-extensions/manifest.ts +0 -0
  558. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/media/__tests__/media-session.test.ts +0 -0
  559. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/media/media-session.ts +0 -0
  560. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/migrate-legacy-storage.ts +0 -0
  561. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/radio/filter-controls.ts +0 -0
  562. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/radio/pending-focus.test.ts +0 -0
  563. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/radio/pending-focus.ts +0 -0
  564. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/__tests__/spectrum-renderer.test.ts +0 -0
  565. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/__tests__/waterfall-renderer.test.ts +0 -0
  566. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/spectrum-renderer.ts +0 -0
  567. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/renderers/waterfall-renderer.ts +0 -0
  568. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/__tests__/frontend-runtime.test.ts +0 -0
  569. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/__tests__/scope-controller.test.ts +0 -0
  570. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/audio-adapter.ts +0 -0
  571. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/capabilities-adapter.ts +0 -0
  572. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/lcd-chrome-adapter.ts +0 -0
  573. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/panel-adapters.ts +0 -0
  574. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/qsy-history-adapter.ts +0 -0
  575. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/scope-adapter.ts +0 -0
  576. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/tx-adapter.ts +0 -0
  577. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/adapters/vfo-adapter.ts +0 -0
  578. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/commands/panel-commands.ts +0 -0
  579. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/frontend-runtime.ts +0 -0
  580. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/index.ts +0 -0
  581. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/props/panel-props.ts +0 -0
  582. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/scope-controller.svelte.ts +0 -0
  583. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/runtime/system-controller.ts +0 -0
  584. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/audio.test.ts +0 -0
  585. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/capabilities.test.ts +0 -0
  586. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/commands.test.ts +0 -0
  587. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/connection.test.ts +0 -0
  588. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/radio.test.ts +0 -0
  589. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/__tests__/ui.test.ts +0 -0
  590. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/audio.svelte.ts +0 -0
  591. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/capabilities.svelte.ts +0 -0
  592. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/commands.svelte.ts +0 -0
  593. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/connection.svelte.ts +0 -0
  594. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/connection.test.ts +0 -0
  595. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/layout.svelte.ts +0 -0
  596. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/lcd-contrast.svelte.ts +0 -0
  597. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/lcd-display-mode.svelte.ts +0 -0
  598. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/qsy-history.svelte.ts +0 -0
  599. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/radio.svelte.test.ts +0 -0
  600. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/radio.svelte.ts +0 -0
  601. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/tuning.svelte.ts +0 -0
  602. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/stores/ui.svelte.ts +0 -0
  603. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/__tests__/http-client.test.ts +0 -0
  604. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/__tests__/ws-client.test.ts +0 -0
  605. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/http-client.ts +0 -0
  606. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/transport/ws-client.ts +0 -0
  607. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/types/capabilities.ts +0 -0
  608. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/types/protocol.ts +0 -0
  609. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/types/state.ts +0 -0
  610. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/__tests__/battery.test.ts +0 -0
  611. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/battery.ts +0 -0
  612. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/filter-width.ts +0 -0
  613. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/haptics.ts +0 -0
  614. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/meter-utils.ts +0 -0
  615. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/smoothing.svelte.ts +0 -0
  616. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/tx-permit.ts +0 -0
  617. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/lib/utils/uuid.ts +0 -0
  618. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/main.ts +0 -0
  619. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/amber-lcd/LcdSkin.svelte +0 -0
  620. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/desktop-v2/DesktopSkin.svelte +0 -0
  621. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/lcd-cockpit/LcdCockpitSkin.svelte +0 -0
  622. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/lcd-scope/LcdScopeSkin.svelte +0 -0
  623. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/mobile/MobileSkin.svelte +0 -0
  624. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/registry.ts +0 -0
  625. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/sdr-test/SdrTestSkin.svelte +0 -0
  626. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/skins/sdr-test/SdrVfoScreen.svelte +0 -0
  627. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/styles/animations.css +0 -0
  628. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/styles/tokens.css +0 -0
  629. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/types/pwa.d.ts +0 -0
  630. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/src/types/webcodecs.d.ts +0 -0
  631. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/static/fonts/DSEG7Classic-Bold.woff2 +0 -0
  632. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/svelte.config.js +0 -0
  633. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/README.md +0 -0
  634. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/app-shell-desktop.png +0 -0
  635. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/app-shell-mobile.png +0 -0
  636. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/connection-overlay-desktop.png +0 -0
  637. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/connection-overlay-mobile.png +0 -0
  638. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/send-report-dialog-desktop.png +0 -0
  639. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/send-report-dialog-mobile.png +0 -0
  640. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/settings-modal-desktop.png +0 -0
  641. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/settings-modal-mobile.png +0 -0
  642. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/status-bar-desktop.png +0 -0
  643. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/status-bar-mobile.png +0 -0
  644. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/toast-desktop.png +0 -0
  645. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/en-US/toast-mobile.png +0 -0
  646. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/app-shell-desktop.png +0 -0
  647. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/app-shell-mobile.png +0 -0
  648. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/connection-overlay-desktop.png +0 -0
  649. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/connection-overlay-mobile.png +0 -0
  650. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/send-report-dialog-desktop.png +0 -0
  651. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/send-report-dialog-mobile.png +0 -0
  652. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/settings-modal-desktop.png +0 -0
  653. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/settings-modal-mobile.png +0 -0
  654. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/status-bar-desktop.png +0 -0
  655. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/status-bar-mobile.png +0 -0
  656. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/toast-desktop.png +0 -0
  657. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/ja-JP/toast-mobile.png +0 -0
  658. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/app-shell-desktop.png +0 -0
  659. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/app-shell-mobile.png +0 -0
  660. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/connection-overlay-desktop.png +0 -0
  661. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/connection-overlay-mobile.png +0 -0
  662. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/send-report-dialog-desktop.png +0 -0
  663. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/send-report-dialog-mobile.png +0 -0
  664. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/settings-modal-desktop.png +0 -0
  665. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/settings-modal-mobile.png +0 -0
  666. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/status-bar-desktop.png +0 -0
  667. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/status-bar-mobile.png +0 -0
  668. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/toast-desktop.png +0 -0
  669. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/__screenshots__/i18n/qps-ploc/toast-mobile.png +0 -0
  670. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/fixtures.ts +0 -0
  671. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/i18n/i18n-visual.spec.ts +0 -0
  672. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tests/e2e/v2-ui-interactive.impl.ts +0 -0
  673. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tsconfig.app.json +0 -0
  674. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tsconfig.json +0 -0
  675. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/tsconfig.node.json +0 -0
  676. {rigplane-2.7.0 → rigplane-2.7.2}/frontend/vite.config.ts +0 -0
  677. {rigplane-2.7.0 → rigplane-2.7.2}/hooks/sitemap_noindex.py +0 -0
  678. {rigplane-2.7.0 → rigplane-2.7.2}/mkdocs.yml +0 -0
  679. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/_keyboard-default.toml +0 -0
  680. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/_schema.md +0 -0
  681. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/_schema_v2.md +0 -0
  682. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/ftx1.toml +0 -0
  683. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/lab599_tx500.toml +0 -0
  684. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/sdrplay_rspdx.toml +0 -0
  685. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/examples/xiegu_x6200.toml +0 -0
  686. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ftx1.toml +0 -0
  687. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic705.toml +0 -0
  688. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic7300.toml +0 -0
  689. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic7610.toml +0 -0
  690. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/ic9700.toml +0 -0
  691. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/tx500.toml +0 -0
  692. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/x6100.toml +0 -0
  693. {rigplane-2.7.0 → rigplane-2.7.2}/rigs/x6200.toml +0 -0
  694. {rigplane-2.7.0 → rigplane-2.7.2}/src/icom_lan/__init__.py +0 -0
  695. {rigplane-2.7.0 → rigplane-2.7.2}/src/icom_lan/_cli_shim.py +0 -0
  696. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/__init__.py +0 -0
  697. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/__main__.py +0 -0
  698. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_codecs.py +0 -0
  699. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_recovery.py +0 -0
  700. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_runtime_mixin.py +0 -0
  701. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_audio_transcoder.py +0 -0
  702. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_bounded_queue.py +0 -0
  703. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_bridge_metrics.py +0 -0
  704. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_bridge_state.py +0 -0
  705. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_civ_rx.py +0 -0
  706. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_connection_state.py +0 -0
  707. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_control_phase.py +0 -0
  708. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_dual_rx_runtime.py +0 -0
  709. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_optional_deps.py +0 -0
  710. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_platformdirs_migration.py +0 -0
  711. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_poller_types.py +0 -0
  712. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_queue_pressure.py +0 -0
  713. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_runtime_protocols.py +0 -0
  714. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_scope_runtime.py +0 -0
  715. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_shared_state_runtime.py +0 -0
  716. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_state_cache.py +0 -0
  717. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/_state_queries.py +0 -0
  718. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/LAYER.md +0 -0
  719. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/__init__.py +0 -0
  720. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_bridge_metrics.py +0 -0
  721. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_bridge_state.py +0 -0
  722. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_codecs.py +0 -0
  723. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_macos_uid.py +0 -0
  724. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_transcoder.py +0 -0
  725. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/_usb_resolve.py +0 -0
  726. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/analyzer.py +0 -0
  727. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/backend.py +0 -0
  728. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/bus.py +0 -0
  729. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/config.py +0 -0
  730. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/dsp.py +0 -0
  731. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/fft_scope.py +0 -0
  732. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/lan_stream.py +0 -0
  733. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/probe.py +0 -0
  734. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/probe_profile.py +0 -0
  735. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/probe_runner.py +0 -0
  736. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/resample.py +0 -0
  737. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio/route.py +0 -0
  738. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_analyzer.py +0 -0
  739. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_bridge.py +0 -0
  740. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_bus.py +0 -0
  741. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/audio_fft_scope.py +0 -0
  742. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/auth.py +0 -0
  743. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/LAYER.md +0 -0
  744. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/__init__.py +0 -0
  745. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/config.py +0 -0
  746. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/discovery.py +0 -0
  747. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/factory.py +0 -0
  748. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/hamlib_models.py +0 -0
  749. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/hamlib_probe.py +0 -0
  750. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic705/__init__.py +0 -0
  751. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic705/core.py +0 -0
  752. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic705/serial.py +0 -0
  753. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic7300/__init__.py +0 -0
  754. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic7300/core.py +0 -0
  755. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic7300/serial.py +0 -0
  756. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic9700/__init__.py +0 -0
  757. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic9700/core.py +0 -0
  758. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/ic9700/serial.py +0 -0
  759. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/__init__.py +0 -0
  760. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/__init__.py +0 -0
  761. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/contracts.py +0 -0
  762. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/serial_civ_link.py +0 -0
  763. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/serial_session.py +0 -0
  764. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/serial_stub.py +0 -0
  765. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/drivers/usb_audio.py +0 -0
  766. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/icom7610/lan.py +0 -0
  767. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/rigctld_client/__init__.py +0 -0
  768. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/rigctld_client/radio.py +0 -0
  769. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/rigctld_client/transport.py +0 -0
  770. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/__init__.py +0 -0
  771. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/parser.py +0 -0
  772. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/poller.py +0 -0
  773. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/radio.py +0 -0
  774. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/backends/yaesu_cat/transport.py +0 -0
  775. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/capabilities.py +0 -0
  776. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/civ.py +0 -0
  777. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/LAYER.md +0 -0
  778. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/__init__.py +0 -0
  779. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_convert.py +0 -0
  780. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_diagnose.py +0 -0
  781. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_discover_hamlib.py +0 -0
  782. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_radio_validate.py +0 -0
  783. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cli/_validate.py +0 -0
  784. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/command_map.py +0 -0
  785. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/command_spec.py +0 -0
  786. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commander.py +0 -0
  787. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/LAYER.md +0 -0
  788. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/__init__.py +0 -0
  789. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/_builders.py +0 -0
  790. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/_codec.py +0 -0
  791. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/_frame.py +0 -0
  792. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/antenna.py +0 -0
  793. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/command_map.py +0 -0
  794. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/command_spec.py +0 -0
  795. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/commander.py +0 -0
  796. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/config.py +0 -0
  797. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/cw.py +0 -0
  798. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/dsp.py +0 -0
  799. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/freq.py +0 -0
  800. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/levels.py +0 -0
  801. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/memory.py +0 -0
  802. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/meters.py +0 -0
  803. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/mode.py +0 -0
  804. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/power.py +0 -0
  805. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/ptt.py +0 -0
  806. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/scope.py +0 -0
  807. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/speech.py +0 -0
  808. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/system.py +0 -0
  809. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/tone.py +0 -0
  810. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/tx_band.py +0 -0
  811. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/commands/vfo.py +0 -0
  812. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/LAYER.md +0 -0
  813. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/__init__.py +0 -0
  814. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_bounded_queue.py +0 -0
  815. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_optional_deps.py +0 -0
  816. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_queue_pressure.py +0 -0
  817. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/_state_cache.py +0 -0
  818. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/auth.py +0 -0
  819. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/capabilities.py +0 -0
  820. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/civ.py +0 -0
  821. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/env_config.py +0 -0
  822. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/exceptions.py +0 -0
  823. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/protocol.py +0 -0
  824. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/radio_protocol.py +0 -0
  825. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/radio_state.py +0 -0
  826. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/transport.py +0 -0
  827. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/core/types.py +0 -0
  828. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/cw_auto_tuner.py +0 -0
  829. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/__init__.py +0 -0
  830. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_discovery.py +0 -0
  831. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_error_ring.py +0 -0
  832. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_errors.py +0 -0
  833. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_logging.py +0 -0
  834. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/_manifest.py +0 -0
  835. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/bundle.py +0 -0
  836. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributor.py +0 -0
  837. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/__init__.py +0 -0
  838. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/audio.py +0 -0
  839. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/config.py +0 -0
  840. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/dependencies.py +0 -0
  841. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/errors.py +0 -0
  842. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/invocation.py +0 -0
  843. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/logs.py +0 -0
  844. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/radio.py +0 -0
  845. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/state.py +0 -0
  846. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/contributors/system.py +0 -0
  847. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/redaction.py +0 -0
  848. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/diagnostics/upload.py +0 -0
  849. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/discovery.py +0 -0
  850. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/LAYER.md +0 -0
  851. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/__init__.py +0 -0
  852. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/exceptions.py +0 -0
  853. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/nodes/__init__.py +0 -0
  854. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/nodes/base.py +0 -0
  855. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/nodes/nr_scipy.py +0 -0
  856. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/pipeline.py +0 -0
  857. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/resample.py +0 -0
  858. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/dsp/tap_registry.py +0 -0
  859. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/env_config.py +0 -0
  860. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/exceptions.py +0 -0
  861. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/hamlib_bridge.py +0 -0
  862. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/ic705.py +0 -0
  863. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/meter_cal.py +0 -0
  864. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles/LAYER.md +0 -0
  865. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles/__init__.py +0 -0
  866. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles/rig_loader.py +0 -0
  867. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/profiles_runtime.py +0 -0
  868. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/protocol.py +0 -0
  869. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/proxy.py +0 -0
  870. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/py.typed +0 -0
  871. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio.py +0 -0
  872. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_initial_state.py +0 -0
  873. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_protocol.py +0 -0
  874. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_reconnect.py +0 -0
  875. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_state.py +0 -0
  876. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radio_state_snapshot.py +0 -0
  877. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/radios.py +0 -0
  878. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rig_loader.py +0 -0
  879. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/LAYER.md +0 -0
  880. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/__init__.py +0 -0
  881. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/audit.py +0 -0
  882. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/circuit_breaker.py +0 -0
  883. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/contract.py +0 -0
  884. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/handler.py +0 -0
  885. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/poller.py +0 -0
  886. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/protocol.py +0 -0
  887. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/routing.py +0 -0
  888. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/server.py +0 -0
  889. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/state_cache.py +0 -0
  890. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/rigctld/utils.py +0 -0
  891. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/LAYER.md +0 -0
  892. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/__init__.py +0 -0
  893. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_audio_recovery.py +0 -0
  894. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_audio_runtime_mixin.py +0 -0
  895. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_civ_rx.py +0 -0
  896. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_connection_state.py +0 -0
  897. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_control_phase.py +0 -0
  898. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_dual_rx_runtime.py +0 -0
  899. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_poller_types.py +0 -0
  900. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_runtime_protocols.py +0 -0
  901. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_scope_runtime.py +0 -0
  902. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_shared_state_runtime.py +0 -0
  903. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/_state_queries.py +0 -0
  904. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/cw_auto_tuner.py +0 -0
  905. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/ic705.py +0 -0
  906. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/meter_cal.py +0 -0
  907. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/profiles_runtime.py +0 -0
  908. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/proxy.py +0 -0
  909. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio.py +0 -0
  910. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio_initial_state.py +0 -0
  911. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio_reconnect.py +0 -0
  912. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radio_state_snapshot.py +0 -0
  913. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/radios.py +0 -0
  914. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/startup_checks.py +0 -0
  915. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/runtime/sync.py +0 -0
  916. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope/LAYER.md +0 -0
  917. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope/__init__.py +0 -0
  918. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope/render.py +0 -0
  919. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/scope_render.py +0 -0
  920. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/startup_checks.py +0 -0
  921. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/sync.py +0 -0
  922. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/transport.py +0 -0
  923. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/types.py +0 -0
  924. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/usb_audio_resolve.py +0 -0
  925. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/LAYER.md +0 -0
  926. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/__init__.py +0 -0
  927. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/comparison.py +0 -0
  928. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/hardware.py +0 -0
  929. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/overrides.py +0 -0
  930. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/registry.py +0 -0
  931. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/runner.py +0 -0
  932. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/validation/schema.py +0 -0
  933. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/LAYER.md +0 -0
  934. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/__init__.py +0 -0
  935. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/_delta_encoder.py +0 -0
  936. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/api_contract.py +0 -0
  937. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/band_plan.py +0 -0
  938. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/discovery.py +0 -0
  939. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/dx_cluster.py +0 -0
  940. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/eibi.py +0 -0
  941. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/__init__.py +0 -0
  942. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/audio.py +0 -0
  943. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/control.py +0 -0
  944. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/diagnostics.py +0 -0
  945. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/handlers/scope.py +0 -0
  946. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/protocol.py +0 -0
  947. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/radio_poller.py +0 -0
  948. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/rtc.py +0 -0
  949. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/runtime_helpers.py +0 -0
  950. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/apple-touch-icon.png +0 -0
  951. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/assets/ControlButtonDemo-Ddi7py1_.css +0 -0
  952. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/assets/index-CvOPafTi.css +0 -0
  953. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/lockup-dark.svg +0 -0
  954. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/lockup-light.svg +0 -0
  955. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/lockup-mono.svg +0 -0
  956. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/mark-dark.svg +0 -0
  957. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/mark-light.svg +0 -0
  958. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/mark-mono.svg +0 -0
  959. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/marketing/github-social-preview.png +0 -0
  960. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/marketing/readme-banner.png +0 -0
  961. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/wordmark-dark.svg +0 -0
  962. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/wordmark-light.svg +0 -0
  963. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/brand/wordmark-mono.svg +0 -0
  964. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon-16.png +0 -0
  965. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon-32.png +0 -0
  966. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon-48.png +0 -0
  967. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicon.ico +0 -0
  968. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-128.png +0 -0
  969. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-16.png +0 -0
  970. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-180.png +0 -0
  971. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-192.png +0 -0
  972. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-256.png +0 -0
  973. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-32.png +0 -0
  974. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-48.png +0 -0
  975. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-512.png +0 -0
  976. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon-64.png +0 -0
  977. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/ink/favicon.ico +0 -0
  978. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-128.png +0 -0
  979. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-16.png +0 -0
  980. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-180.png +0 -0
  981. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-192.png +0 -0
  982. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-256.png +0 -0
  983. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-32.png +0 -0
  984. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-48.png +0 -0
  985. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-512.png +0 -0
  986. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon-64.png +0 -0
  987. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/paper/favicon.ico +0 -0
  988. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-128.png +0 -0
  989. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-16.png +0 -0
  990. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-180.png +0 -0
  991. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-192.png +0 -0
  992. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-256.png +0 -0
  993. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-32.png +0 -0
  994. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-48.png +0 -0
  995. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-512.png +0 -0
  996. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/favicons/transparent/favicon-64.png +0 -0
  997. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/manifest.json +0 -0
  998. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/og-image.png +0 -0
  999. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/pwa-192x192.png +0 -0
  1000. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/pwa-512x512.png +0 -0
  1001. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static/twitter-card.png +0 -0
  1002. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/static.old/index.html +0 -0
  1003. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/tls.py +0 -0
  1004. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/web_routing.py +0 -0
  1005. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/web_startup.py +0 -0
  1006. {rigplane-2.7.0 → rigplane-2.7.2}/src/rigplane/web/websocket.py +0 -0
  1007. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_audio_pipeline_helpers.py +0 -0
  1008. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_audio_stream_fake.py +0 -0
  1009. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_caps.py +0 -0
  1010. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_command_test_helpers.py +0 -0
  1011. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_diagnostics_mock_server.py +0 -0
  1012. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_helpers.py +0 -0
  1013. {rigplane-2.7.0 → rigplane-2.7.2}/tests/_perf_helpers.py +0 -0
  1014. {rigplane-2.7.0 → rigplane-2.7.2}/tests/conftest.py +0 -0
  1015. {rigplane-2.7.0 → rigplane-2.7.2}/tests/contracts/__init__.py +0 -0
  1016. {rigplane-2.7.0 → rigplane-2.7.2}/tests/contracts/test_lazy_imports.py +0 -0
  1017. {rigplane-2.7.0 → rigplane-2.7.2}/tests/e2e/package.json +0 -0
  1018. {rigplane-2.7.0 → rigplane-2.7.2}/tests/e2e/v2-ui-interactive.spec.ts +0 -0
  1019. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fake_rigctld.py +0 -0
  1020. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/civ_rx_frames.json +0 -0
  1021. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/hamlib_dump_caps_ts480.txt +0 -0
  1022. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/hamlib_rigctl_list.txt +0 -0
  1023. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/validation_artifact_mixed.json +0 -0
  1024. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/validation_artifact_reverse_sync_fail.json +0 -0
  1025. {rigplane-2.7.0 → rigplane-2.7.2}/tests/fixtures/validation_template_ic7300.json +0 -0
  1026. {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/dump_state_ic7610.txt +0 -0
  1027. {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/dump_state_yaesu.txt +0 -0
  1028. {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/fldigi_dual_rx_session.txt +0 -0
  1029. {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/js8call_dual_rx_session.txt +0 -0
  1030. {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/protocol_golden.json +0 -0
  1031. {rigplane-2.7.0 → rigplane-2.7.2}/tests/golden/wsjtx_dual_rx_session.txt +0 -0
  1032. {rigplane-2.7.0 → rigplane-2.7.2}/tests/hardware/test_ic7610_audio_pipeline.py +0 -0
  1033. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/README.md +0 -0
  1034. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/conftest.py +0 -0
  1035. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/full_handshake.py +0 -0
  1036. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/logging_utils.py +0 -0
  1037. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/probe_handshake.py +0 -0
  1038. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/probe_login.py +0 -0
  1039. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_audio_integration.py +0 -0
  1040. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_audio_routing.py +0 -0
  1041. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_connect.py +0 -0
  1042. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_controls_extended_integration.py +0 -0
  1043. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_dsp_levels_integration.py +0 -0
  1044. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_get_freq.py +0 -0
  1045. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_media_scope_integration.py +0 -0
  1046. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_memory_set_only.py +0 -0
  1047. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_negative_auth_integration.py +0 -0
  1048. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_operator_toggles_integration.py +0 -0
  1049. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_radio_integration.py +0 -0
  1050. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_reliability_matrix_integration.py +0 -0
  1051. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rigctld_audio_pipeline.py +0 -0
  1052. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rigctld_golden_replay.py +0 -0
  1053. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rigctld_wsjtx.py +0 -0
  1054. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_rit_tuner_integration.py +0 -0
  1055. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_scope_advanced_integration.py +0 -0
  1056. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_tone_tsql_integration.py +0 -0
  1057. {rigplane-2.7.0 → rigplane-2.7.2}/tests/integration/test_vfo_dual_watch_integration.py +0 -0
  1058. {rigplane-2.7.0 → rigplane-2.7.2}/tests/mock_server.py +0 -0
  1059. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio.py +0 -0
  1060. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_analyzer.py +0 -0
  1061. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_backend.py +0 -0
  1062. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_bridge.py +0 -0
  1063. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_bridge_stereo.py +0 -0
  1064. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_bus.py +0 -0
  1065. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_codec.py +0 -0
  1066. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_codecs.py +0 -0
  1067. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_config.py +0 -0
  1068. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_dsp.py +0 -0
  1069. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_fft_scope.py +0 -0
  1070. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_fullduplex.py +0 -0
  1071. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_pipeline_harness.py +0 -0
  1072. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_pipeline_os_smoke.py +0 -0
  1073. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_probe.py +0 -0
  1074. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_probe_profile.py +0 -0
  1075. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_probe_runner.py +0 -0
  1076. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_recovery.py +0 -0
  1077. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_resample.py +0 -0
  1078. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_route.py +0 -0
  1079. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_rx_tx_transition.py +0 -0
  1080. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_stress.py +0 -0
  1081. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_transcoder.py +0 -0
  1082. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_transcoder_coverage.py +0 -0
  1083. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audio_watchdog.py +0 -0
  1084. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_audit.py +0 -0
  1085. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_auth.py +0 -0
  1086. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_authz_registry_gated.py +0 -0
  1087. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_backend_contract_matrix.py +0 -0
  1088. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_backend_factory.py +0 -0
  1089. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_bounded_queue.py +0 -0
  1090. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_bsr_band_switching.py +0 -0
  1091. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_circuit_breaker.py +0 -0
  1092. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ.py +0 -0
  1093. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_command_profiling.py +0 -0
  1094. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_coverage.py +0 -0
  1095. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_dispatch_golden.py +0 -0
  1096. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_mixin_host.py +0 -0
  1097. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_rx_short_frame_robustness.py +0 -0
  1098. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_civ_transaction_ownership.py +0 -0
  1099. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli.py +0 -0
  1100. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_async.py +0 -0
  1101. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_coverage.py +0 -0
  1102. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_diagnose.py +0 -0
  1103. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_diagnose_lazy_import.py +0 -0
  1104. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_e2e.py +0 -0
  1105. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cli_model.py +0 -0
  1106. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cmd29_parsing.py +0 -0
  1107. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_command_catalog_docs.py +0 -0
  1108. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_command_map_integration.py +0 -0
  1109. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_command_spec.py +0 -0
  1110. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_commander.py +0 -0
  1111. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_commands.py +0 -0
  1112. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_commands_extended.py +0 -0
  1113. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_convert.py +0 -0
  1114. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_convert_cli.py +0 -0
  1115. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cw_auto_tune_wiring.py +0 -0
  1116. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_cw_auto_tuner.py +0 -0
  1117. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_data_mode.py +0 -0
  1118. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_delta_encoder.py +0 -0
  1119. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_bundle.py +0 -0
  1120. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributor.py +0 -0
  1121. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributors_batch1.py +0 -0
  1122. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributors_batch2.py +0 -0
  1123. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_contributors_batch3.py +0 -0
  1124. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_e2e.py +0 -0
  1125. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_logging.py +0 -0
  1126. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_privacy_invariants.py +0 -0
  1127. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_redaction.py +0 -0
  1128. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_diagnostics_upload.py +0 -0
  1129. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_discovery.py +0 -0
  1130. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_discovery_responder.py +0 -0
  1131. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_docs_runtime_sync.py +0 -0
  1132. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_filter_family.py +0 -0
  1133. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_levels_part1.py +0 -0
  1134. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_levels_part2.py +0 -0
  1135. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_nodes.py +0 -0
  1136. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_nr_scipy.py +0 -0
  1137. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dsp_pipeline.py +0 -0
  1138. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_dx_cluster.py +0 -0
  1139. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_env_config.py +0 -0
  1140. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_exports.py +0 -0
  1141. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_fake_rigctld.py +0 -0
  1142. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_frontend_e2e_config.py +0 -0
  1143. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ftx1_audio.py +0 -0
  1144. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ftx1_radio.py +0 -0
  1145. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_golden_protocol.py +0 -0
  1146. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_bridge.py +0 -0
  1147. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_dump_caps.py +0 -0
  1148. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_external_rigctld_contract.py +0 -0
  1149. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_models.py +0 -0
  1150. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_hamlib_probe.py +0 -0
  1151. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_coverage.py +0 -0
  1152. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_dsp_407_408.py +0 -0
  1153. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_protocol_gap_399.py +0 -0
  1154. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_handlers_sys_band.py +0 -0
  1155. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic705.py +0 -0
  1156. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic705_backend.py +0 -0
  1157. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic7300_backend.py +0 -0
  1158. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic7610_parity_matrix.py +0 -0
  1159. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_ic9700_backend.py +0 -0
  1160. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_icom7610_serial_radio.py +0 -0
  1161. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_icom_lan_shim.py +0 -0
  1162. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_icom_receiver_tier.py +0 -0
  1163. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_issue_141_core_refactor.py +0 -0
  1164. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_jitter_buffer.py +0 -0
  1165. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_lifecycle_diagnostics.py +0 -0
  1166. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_macos_audio_uid.py +0 -0
  1167. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_main_sub_tracking.py +0 -0
  1168. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_managed_runtime_packaging_doc.py +0 -0
  1169. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_memory_commands.py +0 -0
  1170. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_mock_integration.py +0 -0
  1171. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_naming_parity.py +0 -0
  1172. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_operator_toggles.py +0 -0
  1173. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_overrides.py +0 -0
  1174. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_pcm_e2e.py +0 -0
  1175. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_per_receiver_vfo_roundtrip.py +0 -0
  1176. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_performance_regressions.py +0 -0
  1177. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_platformdirs_migration.py +0 -0
  1178. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_poller.py +0 -0
  1179. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_poller_coverage.py +0 -0
  1180. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_power_unit_extension.py +0 -0
  1181. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_profiles_routing.py +0 -0
  1182. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_profiles_runtime.py +0 -0
  1183. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_protocol.py +0 -0
  1184. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_proxy.py +0 -0
  1185. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_proxy_coverage.py +0 -0
  1186. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_public_api_surface.py +0 -0
  1187. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio.py +0 -0
  1188. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_connect.py +0 -0
  1189. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_coverage.py +0 -0
  1190. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_extended.py +0 -0
  1191. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_poller_coverage.py +0 -0
  1192. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_protocol.py +0 -0
  1193. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_state.py +0 -0
  1194. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radio_validate.py +0 -0
  1195. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_radios.py +0 -0
  1196. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rate_limiter.py +0 -0
  1197. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_raw_civ_pipe.py +0 -0
  1198. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_raw_civ_transaction.py +0 -0
  1199. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_reconnect.py +0 -0
  1200. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rf_gain_af_level.py +0 -0
  1201. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_ic7300.py +0 -0
  1202. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_ic7610.py +0 -0
  1203. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_loader.py +0 -0
  1204. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_multi_vendor.py +0 -0
  1205. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rig_schema.py +0 -0
  1206. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_client_backend.py +0 -0
  1207. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_consistency.py +0 -0
  1208. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_dump_state_snapshot.py +0 -0
  1209. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_handler.py +0 -0
  1210. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_init_coverage.py +0 -0
  1211. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_protocol.py +0 -0
  1212. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_routable_extension.py +0 -0
  1213. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_server.py +0 -0
  1214. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_server_coverage.py +0 -0
  1215. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_rigctld_utils.py +0 -0
  1216. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope.py +0 -0
  1217. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope_render.py +0 -0
  1218. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope_render_coverage.py +0 -0
  1219. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_scope_stress.py +0 -0
  1220. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_security_headers.py +0 -0
  1221. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_selected_freq_mode.py +0 -0
  1222. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_backend_smoke.py +0 -0
  1223. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_civ_link.py +0 -0
  1224. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_session.py +0 -0
  1225. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_serial_stub_framing.py +0 -0
  1226. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_server_wire.py +0 -0
  1227. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_shared_state_runtime.py +0 -0
  1228. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_single_rx_plain_routing.py +0 -0
  1229. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_cache.py +0 -0
  1230. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_cache_coverage.py +0 -0
  1231. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_pollable_extension.py +0 -0
  1232. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_state_queries.py +0 -0
  1233. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_supports_command.py +0 -0
  1234. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_swr_calibration.py +0 -0
  1235. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_sync.py +0 -0
  1236. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_sync_coverage.py +0 -0
  1237. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tap_registry.py +0 -0
  1238. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tls.py +0 -0
  1239. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_token_renewal.py +0 -0
  1240. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tone_tsql.py +0 -0
  1241. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_transport.py +0 -0
  1242. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_tx_band_edge.py +0 -0
  1243. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_usb_audio_capable_extension.py +0 -0
  1244. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_usb_audio_resolve.py +0 -0
  1245. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_usb_audio_stub.py +0 -0
  1246. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validate_hamlib_provider.py +0 -0
  1247. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validate_overrides.py +0 -0
  1248. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_comparison.py +0 -0
  1249. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_runner.py +0 -0
  1250. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_schema.py +0 -0
  1251. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_validation_templates.py +0 -0
  1252. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_vfo_dual_watch.py +0 -0
  1253. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_vox_tone_state.py +0 -0
  1254. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_api_contract.py +0 -0
  1255. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_audio_streaming_profile.py +0 -0
  1256. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_auth_compare_digest.py +0 -0
  1257. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_capability_guards.py +0 -0
  1258. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_command_batch_http.py +0 -0
  1259. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_cw_http_control.py +0 -0
  1260. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_diagnostics.py +0 -0
  1261. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_post_body_cap.py +0 -0
  1262. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_ptt_readonly.py +0 -0
  1263. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_runtime_helpers.py +0 -0
  1264. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_server.py +0 -0
  1265. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_server_coverage.py +0 -0
  1266. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_web_server_token_redaction.py +0 -0
  1267. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_webrtc_signaling.py +0 -0
  1268. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_websocket_coverage.py +0 -0
  1269. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_audio.py +0 -0
  1270. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cat_parser.py +0 -0
  1271. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cat_poller.py +0 -0
  1272. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cat_transport.py +0 -0
  1273. {rigplane-2.7.0 → rigplane-2.7.2}/tests/test_yaesu_cli_factory.py +0 -0
  1274. {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_generator.py +0 -0
  1275. {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_generator_hamlib.py +0 -0
  1276. {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_hardware.py +0 -0
  1277. {rigplane-2.7.0 → rigplane-2.7.2}/tests/validation/test_registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rigplane
3
- Version: 2.7.0
3
+ Version: 2.7.2
4
4
  Summary: Multi-vendor radio control library and Web UI with native providers and planned Hamlib-backed CAT coverage
5
5
  Project-URL: Homepage, https://rigplane.dev/
6
6
  Project-URL: Documentation, https://rigplane.dev/
@@ -11,6 +11,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [2.7.2] — 2026-05-30
15
+
16
+ ### Fixed
17
+
18
+ - Desktop RX audio: resume the `AudioContext` from the LIVE user-gesture so streamed RX audio plays under WKWebView/autoplay-restricted contexts, and recover from suspended-context frame drops instead of silently dropping them (MOR-239, #1694, 921f4c88)
19
+ - Audio scope: dispatch audio-FFT frames to `/api/v1/audio-scope` for radios without a hardware scope (e.g. Xiegu X6200), fixing the blank AUDIO SCOPE panel; hardware-scope radios (IC-7610) are unchanged (MOR-241, #1695, 4e98ab0d)
20
+ - Serial USB-audio TX: arm the PCM TX path in the shared serial Icom base so bridge TX reaches the radio (IC-705/IC-7300/IC-9700/X6200) instead of raising "PCM TX not started" per frame; the audio bridge now degrades to RX-only on TX failure instead of spamming (MOR-242, #1696, 37fe3d0a)
21
+
22
+ ## [2.7.1] — 2026-05-29
23
+
24
+ ### Fixed
25
+ - USB audio now clamps the requested channel count to the device's real
26
+ capability (`input_channels` for RX, `output_channels` for TX) at stream
27
+ open, mirroring the existing sample-rate negotiation. Any mono USB codec
28
+ self-heals instead of failing the global stereo default with PortAudio
29
+ `-9998` ("Invalid number of channels") and starving the stream; the Xiegu
30
+ X6200 mono RX path no longer depends on its profile `codec_preference`
31
+ entry (verified on hardware). The effective channel count and its source
32
+ are recorded on the stream contract for diagnostics (#1692).
33
+
14
34
  ## [2.7.0] — 2026-05-29
15
35
 
16
36
  ### Added
@@ -1523,7 +1543,9 @@ These deprecation closures were announced in v0.19 and dropped on schedule.
1523
1543
  - Transport layer, authentication, CI-V commands, meters, PTT, keep-alive.
1524
1544
  - Clean-room Icom LAN UDP protocol implementation.
1525
1545
 
1526
- [Unreleased]: https://github.com/rigplane/rigplane-core/compare/v2.7.0...HEAD
1546
+ [Unreleased]: https://github.com/rigplane/rigplane-core/compare/v2.7.2...HEAD
1547
+ [2.7.2]: https://github.com/rigplane/rigplane-core/compare/v2.7.1...v2.7.2
1548
+ [2.7.1]: https://github.com/rigplane/rigplane-core/compare/v2.7.0...v2.7.1
1527
1549
  [2.7.0]: https://github.com/rigplane/rigplane-core/compare/v2.6.0...v2.7.0
1528
1550
  [2.6.0]: https://github.com/rigplane/rigplane-core/compare/v2.5.1...v2.6.0
1529
1551
  [2.5.1]: https://github.com/rigplane/rigplane-core/compare/v2.5.0...v2.5.1
@@ -248,3 +248,79 @@ describe('RxPlayer jitter bounds (#1363)', () => {
248
248
  p.stop();
249
249
  });
250
250
  });
251
+
252
+ describe('RxPlayer suspended-context recovery (MOR-239)', () => {
253
+ it('start() resumes a context that is created suspended (WKWebView autoplay)', () => {
254
+ ctx.state = 'suspended';
255
+ const p = new RxPlayer();
256
+ p.start();
257
+ expect(ctx.resume).toHaveBeenCalled();
258
+ p.stop();
259
+ });
260
+
261
+ it('drops the frame while suspended but re-attempts resume and warns (not silent)', () => {
262
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
263
+ ctx.state = 'suspended';
264
+ const p = new RxPlayer();
265
+ p.start();
266
+ ctx.resume.mockClear();
267
+
268
+ p.feed(pcm16(480));
269
+
270
+ // Frame can't play on a suspended ctx, but instead of a silent return
271
+ // we re-attempt resume() and surface a warning so it's observable.
272
+ expect(ctx.createBufferSource).not.toHaveBeenCalled();
273
+ expect(ctx.resume).toHaveBeenCalled();
274
+ expect(warn).toHaveBeenCalled();
275
+ p.stop();
276
+ warn.mockRestore();
277
+ });
278
+
279
+ it('plays frames once the context has resumed to running', () => {
280
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
281
+ ctx.state = 'suspended';
282
+ const p = new RxPlayer();
283
+ p.start();
284
+ p.feed(pcm16(480)); // dropped — suspended
285
+ expect(ctx._lastSrc).toBeNull();
286
+
287
+ ctx.state = 'running'; // resume() honoured by the gesture
288
+ p.feed(pcm16(480)); // now audible
289
+ expect(ctx.createBufferSource).toHaveBeenCalled();
290
+ expect(ctx._lastSrc.start).toHaveBeenCalled();
291
+ p.stop();
292
+ warn.mockRestore();
293
+ });
294
+
295
+ it('re-attempts resume on focus/visibility regain (WKWebView re-suspend)', () => {
296
+ ctx.state = 'suspended';
297
+ const p = new RxPlayer();
298
+ p.start();
299
+ ctx.resume.mockClear();
300
+ window.dispatchEvent(new Event('focus'));
301
+ expect(ctx.resume).toHaveBeenCalled();
302
+ p.stop();
303
+ // After stop the listener must be gone — no further resume calls.
304
+ ctx.resume.mockClear();
305
+ window.dispatchEvent(new Event('focus'));
306
+ expect(ctx.resume).not.toHaveBeenCalled();
307
+ });
308
+ });
309
+
310
+ describe('RxPlayer mono routing (MOR-239)', () => {
311
+ it('routes a mono (1-ch) PCM16 buffer to the audible MAIN channel', () => {
312
+ const p = new RxPlayer();
313
+ p.start(); // default focus='both' → MAIN gain audible
314
+ p.feed(pcm16(480)); // header marks 1 channel
315
+
316
+ // Mono buffer allocated as 1 channel...
317
+ expect(ctx.createBuffer).toHaveBeenCalledWith(1, 480, SAMPLE_RATE);
318
+ // ...fed into preGain (→ splitter[0] → mainGain → mainPanner → destination).
319
+ const [preGain, mainGain] = ctx._gains;
320
+ expect(ctx._lastSrc.connect).toHaveBeenCalledWith(preGain);
321
+ // MAIN channel must carry audible gain so mono lands on an output, not
322
+ // only on the silenced SUB (channel 1) of the splitter.
323
+ expect(mainGain.gain.value).toBeGreaterThan(0);
324
+ p.stop();
325
+ });
326
+ });
@@ -228,6 +228,10 @@ class AudioManager {
228
228
  setAudioConnected(true);
229
229
  console.log('[audio-ws] connected');
230
230
  if (this._rxEnabled) {
231
+ // Idempotent resume nudge: if the AudioContext re-entered
232
+ // 'suspended' while the WS was down (WKWebView backgrounding), wake
233
+ // it as we resubscribe so streamed frames are not dropped.
234
+ this.rxPlayer.start();
231
235
  ws.send(JSON.stringify({
232
236
  type: 'audio_start',
233
237
  direction: 'rx',
@@ -51,6 +51,12 @@ export class RxPlayer {
51
51
  private _floorSec = 0.05;
52
52
  private _ceilingSec = 0.30;
53
53
 
54
+ // Count of frames dropped because the context was suspended (autoplay
55
+ // policy). Surfaced via console.warn so a silent no-audio state is
56
+ // observable instead of invisible. Reset once the context resumes.
57
+ private _droppedSuspendedFrames = 0;
58
+ private _resumeListenersAttached = false;
59
+
54
60
  get volume(): number {
55
61
  return this._volume;
56
62
  }
@@ -104,9 +110,18 @@ export class RxPlayer {
104
110
  return this.ctx !== null && this.ctx.state !== 'closed';
105
111
  }
106
112
 
113
+ /** Start (or resume) playback.
114
+ *
115
+ * MUST be called synchronously from a user-gesture handler (e.g. the LIVE
116
+ * button click): WKWebView / mobile-Safari autoplay policy only honours
117
+ * ``AudioContext.resume()`` when it runs inside the gesture's call stack.
118
+ * Calling again on an existing context is a cheap idempotent resume — the
119
+ * AudioManager re-invokes start() on ``audio_start`` and reconnect to keep
120
+ * nudging a context that re-entered ``suspended``.
121
+ */
107
122
  start(): void {
108
123
  if (this.ctx) {
109
- if (this.ctx.state === 'suspended') this.ctx.resume();
124
+ this._resume();
110
125
  return;
111
126
  }
112
127
  const Ctx = globalThis.AudioContext ?? (globalThis as any).webkitAudioContext;
@@ -129,9 +144,8 @@ export class RxPlayer {
129
144
  this.subPanner.connect(this.ctx.destination);
130
145
  this._applyGraphState();
131
146
  this.nextPlayTime = 0;
132
- if (this.ctx.state === 'suspended') {
133
- this.ctx.resume().catch(() => {});
134
- }
147
+ this._attachResumeListeners();
148
+ this._resume();
135
149
  }
136
150
 
137
151
  stop(): void {
@@ -139,6 +153,7 @@ export class RxPlayer {
139
153
  try { this.decoder.close(); } catch { /* ok */ }
140
154
  this.decoder = null;
141
155
  }
156
+ this._detachResumeListeners();
142
157
  if (this.ctx) {
143
158
  this.ctx.close().catch(() => {});
144
159
  this.ctx = null;
@@ -151,6 +166,66 @@ export class RxPlayer {
151
166
  }
152
167
  this.nextPlayTime = 0;
153
168
  this.opusTs = 0;
169
+ this._droppedSuspendedFrames = 0;
170
+ }
171
+
172
+ /** Best-effort resume of a suspended context. Safe to call repeatedly. */
173
+ private _resume(): void {
174
+ if (this.ctx && this.ctx.state === 'suspended') {
175
+ this.ctx.resume().catch(() => {});
176
+ }
177
+ }
178
+
179
+ /** Resume-on-regain-focus handler: WKWebView re-suspends an AudioContext
180
+ * when the webview is backgrounded; resume it when we come back. Bound as
181
+ * an arrow property so add/removeEventListener see a stable reference. */
182
+ private _onResumeEvent = (): void => {
183
+ this._resume();
184
+ };
185
+
186
+ private _attachResumeListeners(): void {
187
+ if (this._resumeListenersAttached) return;
188
+ if (typeof document !== 'undefined') {
189
+ document.addEventListener('visibilitychange', this._onResumeEvent);
190
+ }
191
+ if (typeof window !== 'undefined') {
192
+ window.addEventListener('focus', this._onResumeEvent);
193
+ }
194
+ this._resumeListenersAttached = true;
195
+ }
196
+
197
+ private _detachResumeListeners(): void {
198
+ if (!this._resumeListenersAttached) return;
199
+ if (typeof document !== 'undefined') {
200
+ document.removeEventListener('visibilitychange', this._onResumeEvent);
201
+ }
202
+ if (typeof window !== 'undefined') {
203
+ window.removeEventListener('focus', this._onResumeEvent);
204
+ }
205
+ this._resumeListenersAttached = false;
206
+ }
207
+
208
+ /** Returns true when frames can be scheduled (context running). When the
209
+ * context is suspended this re-attempts resume() and warns — rather than
210
+ * silently dropping every frame, which previously made a stuck-suspended
211
+ * context (no sound, blank scope) impossible to diagnose. */
212
+ private _ensureRunning(): boolean {
213
+ if (!this.ctx) return false;
214
+ if (this.ctx.state === 'running') {
215
+ this._droppedSuspendedFrames = 0;
216
+ return true;
217
+ }
218
+ if (this.ctx.state === 'suspended') {
219
+ this._resume();
220
+ this._droppedSuspendedFrames++;
221
+ if (this._droppedSuspendedFrames <= 3 || this._droppedSuspendedFrames % 200 === 0) {
222
+ console.warn(
223
+ `RxPlayer: AudioContext suspended — dropped ${this._droppedSuspendedFrames} ` +
224
+ `frame(s), retrying resume(). Audio needs a user gesture (click LIVE).`,
225
+ );
226
+ }
227
+ }
228
+ return false;
154
229
  }
155
230
 
156
231
  /** Feed a raw binary frame from WS */
@@ -174,7 +249,7 @@ export class RxPlayer {
174
249
 
175
250
  private playPcm16(payload: Uint8Array, sr: number, ch: number): void {
176
251
  if (!this.ctx || !this.preGain) return;
177
- if (this.ctx.state === 'suspended') return;
252
+ if (!this._ensureRunning()) return;
178
253
  const channels = ch === 2 ? 2 : 1;
179
254
  const frameCount = Math.floor(payload.byteLength / (2 * channels));
180
255
  if (frameCount <= 0) return;
@@ -194,7 +269,7 @@ export class RxPlayer {
194
269
 
195
270
  private decodeOpus(payload: Uint8Array, sr: number, ch: number): void {
196
271
  if (!this.ctx || !this.preGain) return;
197
- if (this.ctx.state === 'suspended') return;
272
+ if (!this._ensureRunning()) return;
198
273
  if (typeof AudioDecoder === 'undefined') return;
199
274
 
200
275
  if (!this.decoder) {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "rigplane"
7
- version = "2.7.0"
7
+ version = "2.7.2"
8
8
  description = "Multi-vendor radio control library and Web UI with native providers and planned Hamlib-backed CAT coverage"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -478,11 +478,25 @@ class AudioBridge:
478
478
 
479
479
  # --- TX path: virtual device input → radio ---
480
480
  if self._tx_enabled:
481
- await self._radio.start_audio_tx_pcm(
482
- sample_rate=self._sample_rate,
483
- channels=self._channels,
484
- frame_ms=self._frame_ms,
485
- )
481
+ try:
482
+ await self._radio.start_audio_tx_pcm(
483
+ sample_rate=self._sample_rate,
484
+ channels=self._channels,
485
+ frame_ms=self._frame_ms,
486
+ )
487
+ except (RuntimeError, NotImplementedError) as exc:
488
+ # The radio cannot arm a PCM TX stream (e.g. a serial backend
489
+ # that never set up its USB-audio TX path). Degrade to RX-only
490
+ # instead of spinning a _tx_loop that would reject — and log —
491
+ # every captured frame (MOR-242).
492
+ self._tx_enabled = False
493
+ self._tx_started = False
494
+ logger.warning(
495
+ "%s: radio rejected TX start (%s); running RX-only",
496
+ self._label,
497
+ exc,
498
+ )
499
+ return
486
500
  self._tx_started = True
487
501
 
488
502
  tx_dev_id = dev_id
@@ -829,6 +843,17 @@ class AudioBridge:
829
843
 
830
844
  try:
831
845
  await self._radio.push_audio_tx_pcm(pcm_bytes)
846
+ except (RuntimeError, NotImplementedError) as exc:
847
+ # The radio cannot accept PCM TX frames (TX path not armed).
848
+ # Degrade to RX-only and stop the loop instead of rejecting
849
+ # — and logging — every captured frame (MOR-242).
850
+ self._tx_enabled = False
851
+ logger.warning(
852
+ "%s: radio rejected TX frame (%s); switching to RX-only",
853
+ self._label,
854
+ exc,
855
+ )
856
+ return
832
857
  except Exception:
833
858
  if self._tx_frames <= 5:
834
859
  logger.warning("%s: TX push error", self._label, exc_info=True)
@@ -111,6 +111,7 @@ class UsbAudioStreamContract:
111
111
  channels: int
112
112
  frame_ms: int
113
113
  sample_rate_source: str
114
+ channel_source: str = "requested"
114
115
  fallback_reason: str | None = None
115
116
 
116
117
  def to_dict(self) -> dict[str, object]:
@@ -121,6 +122,7 @@ class UsbAudioStreamContract:
121
122
  "channels": self.channels,
122
123
  "frame_ms": self.frame_ms,
123
124
  "sample_rate_source": self.sample_rate_source,
125
+ "channel_source": self.channel_source,
124
126
  }
125
127
  if self.fallback_reason:
126
128
  payload["fallback_reason"] = self.fallback_reason
@@ -480,6 +482,35 @@ class UsbAudioDriver:
480
482
  def _sample_rate_candidates(self, requested: int) -> tuple[int, ...]:
481
483
  return tuple(dict.fromkeys((requested, *_DEFAULT_SAMPLE_RATE_CANDIDATES)))
482
484
 
485
+ def _clamp_channels(
486
+ self,
487
+ *,
488
+ direction: str,
489
+ device: UsbAudioDevice,
490
+ requested_channels: int,
491
+ ) -> tuple[int, str, str | None]:
492
+ """Clamp requested channels to the device's real capability (MOR-238).
493
+
494
+ A profile / codec may request stereo from a device that only exposes a
495
+ mono capture (or playback) endpoint. PortAudio rejects that open with
496
+ PaErrorCode -9998 ("Invalid number of channels"). Mirroring the
497
+ sample-rate negotiation, the effective channel count is clamped down to
498
+ what the device advertises so any mono/stereo USB codec self-heals
499
+ without a per-profile ``codec_preference`` entry. Downstream DSP is
500
+ 48 kHz mono, so a 1-channel capture feeds the broadcaster cleanly.
501
+ """
502
+
503
+ device_max = (
504
+ device.input_channels if direction == "rx" else device.output_channels
505
+ )
506
+ # A device advertising zero channels for this direction is a selection
507
+ # bug, not a clamp target — leave the request untouched and let the
508
+ # open surface the real error.
509
+ if device_max >= 1 and requested_channels > device_max:
510
+ reason = f"channels-{requested_channels}-clamped-to-device-{device_max}"
511
+ return device_max, "device-clamp", reason
512
+ return requested_channels, "requested", None
513
+
483
514
  def _resolve_stream_contract(
484
515
  self,
485
516
  *,
@@ -491,6 +522,11 @@ class UsbAudioDriver:
491
522
  allow_sample_rate_fallback: bool,
492
523
  ) -> UsbAudioStreamContract:
493
524
  device_id = AudioDeviceId(device.index)
525
+ effective_channels, channel_source, channel_reason = self._clamp_channels(
526
+ direction=direction,
527
+ device=device,
528
+ requested_channels=channels,
529
+ )
494
530
  if self._backend.check_sample_rate(
495
531
  device_id,
496
532
  requested_sample_rate,
@@ -501,9 +537,11 @@ class UsbAudioDriver:
501
537
  direction=direction,
502
538
  device=device,
503
539
  sample_rate_hz=requested_sample_rate,
504
- channels=channels,
540
+ channels=effective_channels,
505
541
  frame_ms=frame_ms,
506
542
  sample_rate_source=source,
543
+ channel_source=channel_source,
544
+ fallback_reason=channel_reason,
507
545
  )
508
546
 
509
547
  if not allow_sample_rate_fallback:
@@ -521,16 +559,21 @@ class UsbAudioDriver:
521
559
  candidate,
522
560
  direction=direction,
523
561
  ):
562
+ sample_reason = f"sample-rate-{requested_sample_rate}-unsupported"
563
+ fallback_reason = (
564
+ f"{sample_reason}; {channel_reason}"
565
+ if channel_reason
566
+ else sample_reason
567
+ )
524
568
  return UsbAudioStreamContract(
525
569
  direction=direction,
526
570
  device=device,
527
571
  sample_rate_hz=candidate,
528
- channels=channels,
572
+ channels=effective_channels,
529
573
  frame_ms=frame_ms,
530
574
  sample_rate_source="fallback",
531
- fallback_reason=(
532
- f"sample-rate-{requested_sample_rate}-unsupported"
533
- ),
575
+ channel_source=channel_source,
576
+ fallback_reason=fallback_reason,
534
577
  )
535
578
 
536
579
  raise AudioDriverLifecycleError(
@@ -595,18 +638,21 @@ class UsbAudioDriver:
595
638
  # RX frames reaching the browser.
596
639
  logger.info(
597
640
  "usb-audio: opening RX capture — device=[%d] %s, %d Hz, "
598
- "%d ch, %d ms (device input_channels=%d)",
641
+ "%d ch (requested %d, source=%s), %d ms "
642
+ "(device input_channels=%d)",
599
643
  selected_rx.index,
600
644
  selected_rx.name,
601
645
  contract.sample_rate_hz,
646
+ contract.channels,
602
647
  ch,
648
+ contract.channel_source,
603
649
  fm,
604
650
  selected_rx.input_channels,
605
651
  )
606
652
  self._rx_stream = self._backend.open_rx(
607
653
  AudioDeviceId(selected_rx.index),
608
654
  sample_rate=contract.sample_rate_hz,
609
- channels=ch,
655
+ channels=contract.channels,
610
656
  frame_ms=fm,
611
657
  )
612
658
  await self._rx_stream.start(callback)
@@ -657,7 +703,7 @@ class UsbAudioDriver:
657
703
  self._tx_stream = self._backend.open_tx(
658
704
  AudioDeviceId(selected_tx.index),
659
705
  sample_rate=contract.sample_rate_hz,
660
- channels=ch,
706
+ channels=contract.channels,
661
707
  frame_ms=fm,
662
708
  )
663
709
  await self._tx_stream.start()
@@ -454,7 +454,38 @@ class _IcomSerialRadioBase(CoreRadio):
454
454
  await self._serial_audio_driver.stop_rx()
455
455
 
456
456
  # ------------------------------------------------------------------
457
- # Audio TX
457
+ # Audio TX (Opus)
458
+ # ------------------------------------------------------------------
459
+
460
+ async def start_audio_tx_opus(self) -> None:
461
+ self._check_connected()
462
+ await self._serial_audio_driver.start_tx(
463
+ sample_rate=self.audio_sample_rate,
464
+ channels=self._serial_audio_channels_for_codec(),
465
+ frame_ms=20,
466
+ )
467
+
468
+ async def push_audio_tx_opus(self, opus_data: bytes) -> None:
469
+ self._check_connected()
470
+ if not self._serial_audio_driver.tx_running:
471
+ raise RuntimeError("Audio TX not started")
472
+ payload = bytes(opus_data)
473
+ if self._serial_codec_is_opus():
474
+ transcoder = self._get_pcm_transcoder(
475
+ sample_rate=self.audio_sample_rate,
476
+ channels=self._serial_audio_channels_for_codec(),
477
+ frame_ms=20,
478
+ )
479
+ payload = transcoder.opus_to_pcm(payload)
480
+ await self._serial_audio_driver._push_tx_pcm(payload)
481
+
482
+ async def stop_audio_tx_opus(self) -> None:
483
+ await self._serial_audio_driver.stop_tx()
484
+ self._pcm_tx_fmt = None
485
+
486
+ # ------------------------------------------------------------------
487
+ # Audio TX (PCM) — arms ``_pcm_tx_fmt`` so ``push_audio_tx_pcm`` works
488
+ # over the serial USB CODEC path (MOR-242).
458
489
  # ------------------------------------------------------------------
459
490
 
460
491
  async def start_audio_tx_pcm(
@@ -485,15 +516,51 @@ class _IcomSerialRadioBase(CoreRadio):
485
516
  "sample_rate * frame_ms must produce an integer frame size."
486
517
  )
487
518
 
519
+ # Icom USB CODEC mic input is mono-only by hardware; the LAN path
520
+ # enforces this by forcing txcodec to a mono value in _send_conninfo
521
+ # (issue #794). For the serial path we clamp channels to 1 here so
522
+ # that PortAudio always opens the USB CODEC as a mono output stream.
523
+ # Opening with channels=2 causes the radio ALC to behave erratically
524
+ # for the first 5-10 seconds of TX (GH#1382 regression; consistent with
525
+ # the MOR-238 RX clamp).
526
+ tx_channels = 1
527
+
488
528
  self._check_connected()
489
529
  await self._serial_audio_driver.start_tx(
490
530
  sample_rate=sample_rate,
491
- channels=channels,
531
+ channels=tx_channels,
492
532
  frame_ms=frame_ms,
493
533
  )
534
+ self._pcm_tx_fmt = (sample_rate, tx_channels, frame_ms)
535
+
536
+ async def push_audio_tx_pcm(
537
+ self,
538
+ pcm_bytes: bytes | bytearray | memoryview,
539
+ ) -> None:
540
+ self._check_connected()
541
+ if self._pcm_tx_fmt is None:
542
+ raise RuntimeError(
543
+ "PCM TX not started; call start_audio_tx_pcm() before push_audio_tx_pcm()."
544
+ )
545
+ if not isinstance(pcm_bytes, (bytes, bytearray, memoryview)):
546
+ raise AudioFormatError("PCM input must be bytes-like.")
547
+ sample_rate, channels, frame_ms = self._pcm_tx_fmt
548
+ if (sample_rate * frame_ms) % 1000 != 0:
549
+ raise AudioFormatError(
550
+ "sample_rate * frame_ms must produce an integer frame size."
551
+ )
552
+ frame_samples = (sample_rate * frame_ms) // 1000
553
+ expected = frame_samples * channels * 2
554
+ frame = bytes(pcm_bytes)
555
+ if len(frame) != expected:
556
+ raise AudioFormatError(
557
+ f"PCM frame size mismatch: expected {expected} bytes "
558
+ f"({frame_ms}ms at {sample_rate}Hz, {channels}ch s16le), got {len(frame)}."
559
+ )
560
+ await self._serial_audio_driver._push_tx_pcm(frame)
494
561
 
495
562
  async def stop_audio_tx_pcm(self) -> None:
496
- await self._serial_audio_driver.stop_tx()
563
+ await self.stop_audio_tx_opus()
497
564
 
498
565
  async def _push_pcm_tx(self, frame: bytes) -> None:
499
566
  if not isinstance(frame, bytes):
@@ -613,8 +680,17 @@ class _IcomSerialRadioBase(CoreRadio):
613
680
  # ------------------------------------------------------------------
614
681
 
615
682
  async def _stop_serial_audio_driver(self) -> None:
616
- await self._serial_audio_driver.stop_rx()
617
- await self._serial_audio_driver.stop_tx()
683
+ self._pcm_tx_fmt = None
684
+ self._pcm_rx_user_callback = None
685
+ self._opus_rx_user_callback = None
686
+ try:
687
+ await self._serial_audio_driver.stop_tx()
688
+ except Exception:
689
+ logger.debug("serial-audio: failed to stop TX path", exc_info=True)
690
+ try:
691
+ await self._serial_audio_driver.stop_rx()
692
+ except Exception:
693
+ logger.debug("serial-audio: failed to stop RX path", exc_info=True)
618
694
 
619
695
  def _ensure_scope_baud_guardrail(self) -> None:
620
696
  if self._serial_baudrate >= _SERIAL_SCOPE_MIN_BAUD:
@@ -0,0 +1,52 @@
1
+ """Serial adaptation layer for the IC-7610 backend."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+
7
+ from ...exceptions import CommandError
8
+ from .._icom_serial_base import _IcomSerialRadioBase, _SERIAL_SCOPE_MIN_BAUD
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ __all__ = ["Icom7610SerialRadio"]
13
+
14
+
15
+ class Icom7610SerialRadio(_IcomSerialRadioBase):
16
+ """IC-7610 backend wired to shared core over serial CI-V session driver.
17
+
18
+ The audio TX (Opus + PCM) path and audio-driver teardown live in
19
+ ``_IcomSerialRadioBase`` (lifted there in MOR-242); this subclass only
20
+ carries the IC-7610-specific RX-PCM delegation and the scope baud
21
+ guardrail that raises ``CommandError``.
22
+ """
23
+
24
+ _DEFAULT_MODEL = ""
25
+
26
+ # ------------------------------------------------------------------
27
+ # IC-7610 specific: stop_audio_rx_pcm delegates to stop_audio_rx_opus
28
+ # ------------------------------------------------------------------
29
+
30
+ async def stop_audio_rx_pcm(self) -> None:
31
+ self._pcm_rx_user_callback = None
32
+ await self.stop_audio_rx_opus()
33
+
34
+ # ------------------------------------------------------------------
35
+ # IC-7610 specific: scope guardrail uses CommandError
36
+ # ------------------------------------------------------------------
37
+
38
+ def _ensure_scope_baud_guardrail(self) -> None:
39
+ if self._serial_baudrate >= _SERIAL_SCOPE_MIN_BAUD:
40
+ return
41
+
42
+ msg = (
43
+ "Scope over serial requires baudrate >= "
44
+ f"{_SERIAL_SCOPE_MIN_BAUD} for stable command path; got baudrate="
45
+ f"{self._serial_baudrate}. Set allow_low_baud_scope=True to override."
46
+ )
47
+ if not self._allow_low_baud_scope:
48
+ raise CommandError(msg)
49
+
50
+ if not self._low_baud_scope_warned:
51
+ logger.warning("%s Running with override may increase timeout risk.", msg)
52
+ self._low_baud_scope_warned = True
@@ -413,10 +413,12 @@ class WebServer:
413
413
  _has_scope = (CAP_SCOPE in radio.capabilities) if radio is not None else False
414
414
  if radio is not None and _has_audio:
415
415
  self._audio_fft_scope = AudioFftScope(fft_size=2048, fps=20, avg_count=2)
416
- self._audio_fft_scope.on_frame(self._broadcast_audio_scope)
416
+ # AudioFftScope.on_frame() is a single-slot setter: register one
417
+ # dispatch method that fans out to BOTH broadcasters. Registering
418
+ # twice would clobber the first callback (MOR-241).
419
+ self._audio_fft_scope.on_frame(self._dispatch_audio_fft_frame)
417
420
  if not _has_scope:
418
- # No hardware scope — audio FFT also feeds /api/v1/scope
419
- self._audio_fft_scope.on_frame(self._broadcast_scope)
421
+ # No hardware scope — audio FFT also feeds /api/v1/scope.
420
422
  self._audio_broadcaster.set_pcm_tap(self._audio_fft_scope.feed_audio)
421
423
  logger.info(
422
424
  "Audio FFT scope available (has_audio=%s, has_hw_scope=%s)",
@@ -609,6 +611,24 @@ class WebServer:
609
611
  if self._radio is not None:
610
612
  self._set_scope_data_callback(self._broadcast_scope)
611
613
 
614
+ def _dispatch_audio_fft_frame(self, frame: Any) -> None:
615
+ """Fan out an audio FFT frame to the relevant scope channels.
616
+
617
+ Single registered callback for :class:`AudioFftScope` (whose
618
+ ``on_frame`` is a single-slot setter). Always feeds the dedicated
619
+ ``/api/v1/audio-scope`` channel. For radios WITHOUT a hardware scope
620
+ the same frame also drives ``/api/v1/scope`` (the main panadapter),
621
+ since those radios derive their spectrum from RX audio. Hardware-scope
622
+ radios (e.g. IC-7610) keep ``/api/v1/scope`` sourced exclusively from
623
+ the real scope, so the audio FFT never touches it (MOR-241).
624
+ """
625
+ self._broadcast_audio_scope(frame)
626
+ _has_scope = (
627
+ CAP_SCOPE in self._radio.capabilities if self._radio is not None else False
628
+ )
629
+ if not _has_scope:
630
+ self._broadcast_scope(frame)
631
+
612
632
  def _broadcast_scope(self, frame: Any) -> None:
613
633
  """Broadcast scope frame to all registered handlers.
614
634