Skip to content

REQ-PTT-01 is doing double duty: 'assert/release within 50 ms' absorbs 'every emission keys the transmitter', which has no requirement #1411

Description

@dc0sk

Surfaced while adjudicating #1402's 29 flagged commits. Not a mislabel — a missing requirement that makes correct trailers look wrong.

The observation

Eight production commits carry Implements: REQ-PTT-01:

d8dfedc9  fix(kiss): the TNC built a SharedPtt and never started its watchdog
63ca1803  fix(repeater): the cross-band relay cannot leave rig_b keyed
68887bd5  fix(daemon): the OTA send stops on a PTT fault without …
fb169538  feat(radio): refuse a second key, defer the ID when …
5d444be2  feat(radio): a PTT guard releases only the key it took
d838d3e9  fix(kiss): key the transmitter for every emission
635010f9  fix(daemon): key the transmitter for every emission
88a0485d  fix(ardop): key the transmitter for every emission

REQ-PTT-01's registered statement is, in full:

PTT assert/release within 50 ms

Keying-at-all and keying-within-50 ms are different properties. Not one of those eight is about latency; they are about whether a transmission is keyed, whether the key is released on every error path, and whether a watchdog bounds a hang. They carry PTT-01 because it is the only PTT requirement — there is nowhere better to point.

Why this is a gap rather than sloppiness

The property is real, load-bearing, and already pinned by tests. CLAUDE.md's acceptance table gives it three separate rows:

  • "Every ARDOP emission keys the transmitter — data, ARQ, IRS ACK/NACK and relay, not just the station ID"
  • "Every DAEMON emission keys the transmitter — handshake (CONREQ/CONACK), both QSY lines, relay forward and the non-OTA send, which all transmitted unkeyed while five guards sat in server.rs"
  • "No relay-path error leaves rig_b keyed while the daemon is alive"

So the repo treats it as an acceptance criterion in prose, with tests, while the registry carries only the timing clause. That is the asymmetry: the requirement that actually governs eight merged commits and three acceptance rows does not exist as an id.

It also has regulatory weight — an unkeyed emission is dead RF, and a stuck key is an unattended transmitter (§97.221 territory), which is why openpulse-mesh had its audio route removed rather than guarded.

Why it matters beyond tidiness

What would close it

A new requirement, roughly: "Every transmission keys the PTT for its duration and releases it on every exit path, including errors and unwinds; no path may leave the transmitter keyed while the process is alive." Then re-point the eight (the ledger is the only place a merged trailer can be corrected — see #1410) and give it the three acceptance rows and their tests.

Open questions, which is why this is an issue and not a PR:

  1. One requirement or two? "Every emission keys" and "no error path leaves it keyed" are arguably separate — the second is the safety-critical half and the one with the watchdog.
  2. enforced or baseline? It has real tests today (ptt_keys_every_transmit, ptt_keys_every_daemon_transmit, abnormal_exit_release, shared_ptt), several of which run in the gate, so enforced looks reachable — but that needs the binding checked rather than assumed.
  3. Which capability covers it? CAP-59 (Radio interface, PTT, CAT) and CAP-74 (PTT backends) both exist, and The requirements-trailer lint checks that a CAP id EXISTS, not that it is the right one — 4 of the last 14 name an unrelated capability #1371 already recorded that shared_ptt.rs → CAP-59 was a judgement call. The emission paths live in ardop/kiss/daemon/repeater, none of which those capabilities own.

Related: #1402 (where this surfaced), #1410 (the nine corrected trailers), #1405 (reachability), #1112 (REQ-PHY-05's deferred audio half).

🤖 Generated with Claude Code

https://claude.ai/code/session_0188ATCj6DZ9aRVQ2vSirua6

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions