Layer 3 Doc-vs-Impl Audit (2026-06-26)

Snapshot audit of Layer 3 documentation drift against the in-repo src/rfgen/ implementation, taken on the same branch as the 6 new TorchSig emitter wrappers (feat(emitters): add 6 TorchSig builder wrappers...). This file is informational and prescribes no fixes; severity tags are calibrated to the user’s downstream tolerance for misleading vs imprecise drift.

Dominant pattern: several Layer 3 doc files still describe a richer pre-implementation surface (long catalog of class names, dotted taxonomy strings, ChannelPipeline / ChainKind machinery, Transformation.CHANNEL enum member) that no longer matches the lean code shipped under src/rfgen/. Several Layer 3 reference pages are also referenced from peer docs but do not exist on disk (docs/reference/api/{device-fingerprint,propagation,rx-frontend}.md).

#

Doc

Doc claim

Impl status

Severity

1

docs/reference/api/emitters.md:38 (class index)

LoRaEmitter is the canonical class

src/rfgen/emitters/lora.py exports LoRaSdrEmitter and LoRaPHYEmitter (subclasses of private _LoRaBase); no class named LoRaEmitter exists

high

2

docs/reference/api/emitters.md:78-89

supported_classes is a long tuple of dotted labels like "iot.lora.css.sf7.bw125.cr-4-5"

lora.py: supported_classes = ("lora",) only; the entire SF/BW/CR taxonomy is undelivered

high

3

docs/reference/api/emitters.md:42-56 (class index)

Lists ADSBEmitter, WiFiEmitter, ZigbeeEmitter, BLEEmitter, LTEDownlinkEmitter, NRPUSCHEmitter, OcuSyncShellEmitter, LightbridgeShellEmitter, FPVAnalogEmitter, MAVLinkTelemetryEmitter, CrossfireELRSEmitter, NRDownlinkEmitter, GSMEmitter, CapturedPlaybackEmitter, FrequencyHoppingRadarEmitter, FMCWRadarEmitter

Actual classes: AdsBEmitter, WifiEmitter, ZigbeeEmitter, BLEEmitter, LTEEmitter, NRPuschEmitter, ChirpRadarEmitter, PulsedRadarEmitter. No drone, GSM, captured-playback, FH-radar, FMCW, NR-downlink classes exist

high

4

docs/reference/api/emitters.md:44-46

PulsedRadarEmitter, FMCWRadarEmitter, FrequencyHoppingRadarEmitter shipped

radar.py ships PulsedRadarEmitter (supported_classes=("pulsed",)) and ChirpRadarEmitter (("lfm_chirp",)); no FMCW or FH classes

high

5

docs/signal-catalog/index.md:65-72

Radar covers Barker B5/B7/B11/B13, polyphase Frank/P1/P2/P3/P4, PMCW Costas/Frank, FH Costas

radar.py exposes only "pulsed" and "lfm_chirp" labels; no Barker codes, polyphase, PMCW, or FH labels reach the API

high

6

docs/signal-catalog/index.md:91-105

Drone family with OcuSync, Lightbridge, FPV analog, MAVLink, Crossfire/ELRS

No drone emitter module under src/rfgen/emitters/; EmitterFamily.DRONE enum value exists but no class binds to it

high

7

docs/signal-catalog/index.md:165-173

ADS-B supports DF11, DF17, DF18 with airborne-position/velocity/identification distribution

adsb.py: supported_classes=("adsb_extended_squitter",) only; no DF11/DF18 selection surface

medium

8

docs/signal-catalog/index.md:177-181

LTE 1.4-20 MHz bandwidth list

cellular.py: LTEEmitter.supported_classes = ("lte_pusch", "lte_pdsch"); bandwidth is a runtime param, but the class labels are protocol/channel rather than the BW set the catalog implies

low

9

docs/signal-catalog/index.md:192-196

GSM/2G GMSK class shipped

No GSM emitter class anywhere in src/rfgen/emitters/

high

10

docs/signal-catalog/index.md:200-207

Captures-and-playback is a first-class emitter implementing BaseEmitter

No CapturedPlaybackEmitter (or any captured emitter) in src/rfgen/emitters/

high

11

docs/reference/api/channels.md:128-153

Transformation enum members include DAC_QUANTIZATION, PA_NONLINEARITY, TX_IQ_IMBALANCE, CHANNEL, ADC_QUANTIZATION, RX_IQ_IMBALANCE

src/rfgen/enums.py: actual member names are DAC, PA, TX_IQ_IMB, PROPAGATION (value 21, not CHANNEL), ADC, RX_IQ_IMB

high

12

docs/reference/api/channels.md:164-208

ChannelPipeline and ChainKind classes with kind=/strict= constructor

Neither ChannelPipeline nor ChainKind exists anywhere in src/rfgen/

high

13

docs/reference/api/channels.md:554-568

ChannelChainConfig Pydantic model with pre_sum / post_sum

No ChannelChainConfig class exists in src/rfgen/

high

14

docs/reference/api/channels.md:576-661

Default propagation backends named SionnaRTChannel, SionnaCDLChannel, SionnaTDLChannel, SionnaUMaChannel, SionnaUMiChannel, SionnaRMaChannel

src/rfgen/propagation.py exports SionnaRT, SionnaCDL, SionnaTDL, SionnaUMa, SionnaUMi, SionnaRMa (no ...Channel suffix)

high

15

docs/reference/api/channels.md:594-599

SionnaCDLChannel.__init__ takes profile, delay_spread_ns, carrier_freq_hz, ut_velocity_ms keyword args

propagation.py:_SionnaPropagationBase.__init__(self, **kwargs) is the only constructor; no explicit keyword schema is declared at the class level

medium

16

docs/reference/api/channels.md:96

SionnaCDLChannel advertised as concrete default backend “CDL profiles A-E via Sionna PHY”

propagation.py:SionnaCDL is a pass-through wrapper requiring sionna; profile A-E support is not encoded in the class signature

low

17

docs/reference/api/channels.md:75-101

Index lists exactly the 13 per-transformation ABCs and explicitly disclaims AWGN as a stage

Contradicted by propagation.py:AWGNChannel(BaseChannelPropagation) shipped as a concrete class and registered under awgn_channel in pyproject.toml

medium

18

docs/reference/algorithms/fingerprint-math.md:8,20,286,353

Fingerprint is a single DeviceFingerprint(BaseChannel) plugin with an .apply() method that runs the CFO/SFO/IQ-imb/phase-noise/PA/DAC chain

src/rfgen/device_fingerprint.py exports FingerprintParams + DeviceRegistry; the impairments are realised by separate classes in tx_impairments.py (LinearCFO, LeesonTXPhaseNoise, TorchSigTXIQImbalance, RappPA, SalehPA, LinearDACQuantizer). No DeviceFingerprint BaseChannel subclass exists

high

19

docs/reference/algorithms/emitter-radar.md:15-78

Pulsed-radar class labels pulsed.rect, pulsed.barker.{b5,b7,b11,b13}, pulsed.polyphase.{frank64,p1_64,...}

radar.py:PulsedRadarEmitter.supported_classes = ("pulsed",); none of the dotted Barker / polyphase labels are accepted

high

20

docs/reference/api/emitters.md (missing peer pages)

Page text references docs/reference/api/device-fingerprint.md, propagation.md, rx-frontend.md as peer pages

Only channels.md exists; device-fingerprint.md, propagation.md, rx-frontend.md are absent from docs/reference/api/, leaving the entire RX/TX impairment surface undocumented at the API layer

medium

21

docs/reference/algorithms/fingerprint-math.md:353

Cross-references AnalyticReceiverFrontend as the RX-side counterpart class

No AnalyticReceiverFrontend in src/rfgen/; the RX surface is LinearRXMixer, ScipyFIRIFFilter, ScipyPolyResampler, LinearLNANoise, LinearADCQuantizer, LeesonRXPhaseNoise, TorchSigRXIQImbalance, LinearAGC in rx_frontend.py

medium

22

docs/reference/api/emitters.md:330 (anchor block)

Anchors block lists TorchSigFSKEmitter / TorchSigOFDMEmitter / etc. as stubs

These now exist as of this branch but the anchor block still places them alongside true stubs rather than promoting them to full class-index rows next to TorchSigCommsEmitter

low

23

docs/reference/algorithms/rf-frontend-models.md:34

“There is no separate AWGN stage in the current design”

Contradicted by propagation.py:AWGNChannel(BaseChannelPropagation) which is a shipped concrete; either remove the impl class or update this doc claim

medium

Severity summary: 12 high, 7 medium, 4 low (23 findings total).

Top three most surprising:

  1. The Transformation enum docs name members (CHANNEL, DAC_QUANTIZATION, …) that simply do not exist in src/rfgen/enums.py; the impl uses short names (PROPAGATION, DAC, …). This is doc-only drift that could mislead any first-time reader who copies a doc snippet.

  2. ChannelPipeline and ChainKind are documented in detail (constructor, apply semantics, kind= flag) but neither class exists anywhere in the repo; the channel pipeline is realized by separate per-transformation classes wired via the entry-point registry.

  3. LoRaEmitter.supported_classes is documented as a multi-class taxonomy (iot.lora.css.sf7.bw125.cr-4-5, …) but the shipped implementation accepts only the single literal "lora", so any user driving the framework from doc-listed labels will hit a class_label not in supported_classes error.


Resolution status (as of 2026-06-27)

Per-finding annotations:

#

Status

Resolution

1

RESOLVED in f2cb3e8

docs/reference/api/emitters.md rewritten to reflect the shipped LoRaSdrEmitter + LoRaPHYEmitter dual-backend; the LoRaEmitter name is preserved only as an anchor alias pointing to the new LoRa subsection.

2

RESOLVED in f2cb3e8

The dotted-taxonomy table is replaced with the actual ("lora",) label; SF/BW/CR knobs are documented on LoRaParams instead.

3

RESOLVED in f2cb3e8 + daa4b99

Class index in emitters.md lists the actual shipped classes (AdsBEmitter, WifiEmitter, ZigbeeEmitter, BLEEmitter, LTEEmitter, NRPuschEmitter, ChirpRadarEmitter, PulsedRadarEmitter, plus the seven TorchSig*Emitter siblings, plus the LoRa pair). Deferred classes (drone family, NRDownlinkEmitter, GSMEmitter, CapturedPlaybackEmitter, FMCWRadarEmitter, FrequencyHoppingRadarEmitter) are listed under ## Deferred for future emitter expansion in docs/signal-catalog/index.md and kept as anchor aliases that point to that deferral subsection.

4

RESOLVED in f2cb3e8 + daa4b99

Class index lists only the shipped PulsedRadarEmitter (pulsed) and ChirpRadarEmitter (lfm_chirp); FMCW and FH-radar classes are explicitly deferred.

5

DEFERRED per user decision: planned for future emitter expansion. docs/signal-catalog/index.md § ## Deferred for future emitter expansion -> ### Extended radar waveforms (added in daa4b99).

6

DEFERRED per user decision: planned for future emitter expansion. docs/signal-catalog/index.md § ## Deferred for future emitter expansion -> ### Drone family (added in daa4b99).

7

RESOLVED in daa4b99

ADS-B catalog row trimmed to the single shipped ("adsb_extended_squitter",) label; DF11/DF18 distinction is explicitly deferred to a future cadence-and-message-mix expansion.

8

RESOLVED in daa4b99

LTE row updated to ("lte_pusch", "lte_pdsch"); bandwidth knobs documented on LTEParams as runtime parameters.

9

DEFERRED per user decision: planned for future emitter expansion. docs/signal-catalog/index.md § ## Deferred for future emitter expansion -> ### GSM / 2G GMSK (added in daa4b99).

10

DEFERRED per user decision: planned for future emitter expansion. docs/signal-catalog/index.md § ## Deferred for future emitter expansion -> ### CapturedPlaybackEmitter (replay-from-IQ-files) (added in daa4b99).

11

RESOLVED in b6a773f

docs/reference/api/channels.md Transformation enum block rewritten with the actual short member names (DAC, PA, TX_IQ_IMB, PROPAGATION = 21, ADC, RX_IQ_IMB, …) matching src/rfgen/enums.py.

12

RESOLVED in b6a773f

ChannelPipeline and ChainKind doc blocks removed; the new prose describes how the scene composer dispatches each emitter via the transformation ClassVar on every concrete. Anchor aliases preserve old {ref} targets.

13

RESOLVED in b6a773f

ChannelChainConfig removed; the anchor is preserved as an alias inside the cross-reference-compatibility block at the foot of the page.

14

RESOLVED in b6a773f + a98bdf1

Sionna concretes documented with the actual shipped names (SionnaRT, SionnaCDL, SionnaTDL, SionnaUMa, SionnaUMi, SionnaRMa) in the new docs/reference/api/propagation.md page; the old ...Channel-suffixed names are preserved as anchor aliases in channels.md.

15

RESOLVED in a98bdf1

propagation.md documents the shipped **kwargs constructor pattern on _SionnaPropagationBase (which all six skeletons inherit) rather than a per-skeleton keyword schema that does not exist.

16

RESOLVED in a98bdf1

SionnaCDL is documented as a Pass-1 lazy-import skeleton wrapping sionna.phy.channel.tr38901.CDL, not a fully-wired concrete; CDL A-E profile support is explicitly identified as a future Pass-N concern.

17

RESOLVED in b6a773f + a98bdf1

channels.md class-index reframed to describe Layer 2 ABCs only; propagation.md lists AWGNChannel as a shipped concrete. rf-frontend-models.md (finding 23) updated in lockstep.

18

RESOLVED in 2c499be

docs/reference/algorithms/fingerprint-math.md introduction rewritten to describe the shipped factoring: FingerprintParams + DeviceRegistry in rfgen.device_fingerprint, plus per-impairment concretes in rfgen.tx_impairments dispatched by the scene composer in canonical pipeline order. The monolithic DeviceFingerprint(BaseChannel) class-stub and dataclass examples are replaced with the actual surface.

19

RESOLVED in ee9dc7c

docs/reference/algorithms/emitter-radar.md rewritten to document the two shipped class labels (pulsed, lfm_chirp); the dotted Barker / polyphase / FMCW / FH-radar labels are moved to an explicit deferred-waveforms subsection pointing at the catalog deferral list.

20

RESOLVED in a98bdf1

Three new API reference pages created: docs/reference/api/device-fingerprint.md, docs/reference/api/propagation.md, docs/reference/api/rx-frontend.md. Each follows the existing emitters.md / channels.md shape (intro, class index, per-class section with signature, behaviour, parameters) and ships a Scientific validation admonition linking to the matching report(s). All three are wired into docs/reference/api/index.md (module map + toctree).

21

RESOLVED in 2c499be

The dangling AnalyticReceiverFrontend reference on fingerprint-math.md:353 is replaced with a one-line description of the actual RX surface (LinearRXMixer, ScipyFIRIFFilter, ScipyPolyResampler, LinearLNANoise, LinearADCQuantizer, LeesonRXPhaseNoise, TorchSigRXIQImbalance, LinearAGC) and a link to the new rx-frontend.md API page.

22

RESOLVED in f2cb3e8

The six new TorchSig builder wrappers (TorchSigFSKEmitter, TorchSigOFDMEmitter, TorchSigAMEmitter, TorchSigFMEmitter, TorchSigChirpEmitter, TorchSigToneEmitter, plus TorchSigCommsEmitter) are promoted to full class-index rows in docs/reference/api/emitters.md; the anchor aliases still exist for backward compatibility.

23

RESOLVED in b6a773f + b396c6c

rf-frontend-models.md replaces the contradicted “there is no separate AWGN stage in the current design” sentence with a description of what actually ships: rfgen.propagation exports AWGNChannel as the default Group.CHANNEL SNR-parameterised pure-torch backend alongside BaseLNANoise in Group.RX_CAPTURE (noise-figure-parameterised thermal noise). channels.md adjusts its index accordingly.

Updated severity summary

  • Resolved on this PR: 18 findings (1, 2, 3, 4, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23). The category-A “doc-update-only” plus category-B trivial fix plus category-C three new API pages all landed.

  • Deferred per user decision: 5 findings (5, 6, 9, 10, plus the radar half of 4) - all explicitly listed under ## Deferred for future emitter expansion in docs/signal-catalog/index.md with a one-sentence note that each is planned for a future release and NOT shipped today.

  • Net status: 18 resolved, 5 deferred-with-marker, 0 outstanding.