From a416dc06dc8adb542c7003b5b4884e03b15a59c9 Mon Sep 17 00:00:00 2001 From: gabeyocum28 Date: Tue, 6 Oct 2026 21:44:45 -0600 Subject: [PATCH] fix: repoint stale doc paths referenced from the package Four places under src/openflight named docs/*.md files that the docs restructure moved, so the pointers have been 404s since: - kld7/radc.py OPS-bin penalty warning -> docs/legacy/troubleshooting.md - cloud/client.py docstring -> docs/reference/cloud-uploader-spec.md - session_logger.py session_uuid comment -> docs/reference/cloud-uploader-spec.md - kld7/two_ray.py docstring: cited an analysis script and findings doc that were never committed; now points at the two-ray section of docs/legacy/launch-angle-explained.md instead. Add tests/test_doc_references.py, which scans the package for docs/...md references and fails on any that do not exist, so a future docs move cannot strand them again. It failed on exactly these four before the fix. --- docs/changelog.md | 5 ++++ src/openflight/cloud/client.py | 2 +- src/openflight/kld7/radc.py | 2 +- src/openflight/kld7/two_ray.py | 18 +++++++------- src/openflight/session_logger.py | 2 +- tests/test_doc_references.py | 40 ++++++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 tests/test_doc_references.py diff --git a/docs/changelog.md b/docs/changelog.md index 151e8676c..37b0624f3 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Electron Kiosk Shell](electron-kiosk-shell.md#browser-local-state-breaking-on-first-electron-launch). ### Fixed +- **Doc paths named from the Python package resolve again.** The K-LD7 + OPS-bin penalty warning, the cloud client and session-logger comments, + and the two-ray module docstring pointed at flat `docs/*.md` files that + moved in the docs restructure. A new test scans `src/openflight` for + `docs/…​.md` references and fails on any that do not exist. - **Stale doc paths from the docs restructure.** The hardware-help issue template and the user-facing messages in `scripts/setup/setup.sh`, `setup_kld7_devices.sh`, `capture_kld7_radc.py`, `replay_spin_dechirp.py`, diff --git a/src/openflight/cloud/client.py b/src/openflight/cloud/client.py index 6128137d5..0f3fcc9a8 100644 --- a/src/openflight/cloud/client.py +++ b/src/openflight/cloud/client.py @@ -5,7 +5,7 @@ the network. The contract lives entirely in this module; nothing here imports FlightWeb -code. See docs/openflight-cloud-uploader-spec.md. +code. See docs/reference/cloud-uploader-spec.md. """ import json diff --git a/src/openflight/kld7/radc.py b/src/openflight/kld7/radc.py index 6f85017f3..101bf8673 100644 --- a/src/openflight/kld7/radc.py +++ b/src/openflight/kld7/radc.py @@ -1901,7 +1901,7 @@ def extract_launch_angle( "[RADC] OPS-bin penalty: %d/%d frames (%.0f%%) > %d " "bins from expected bin %d (peak bins: %s, weight " "/%.1f). High rate suggests a radar mounting or " - "clutter issue — see docs/kld7-troubleshooting.md.", + "clutter issue — see docs/legacy/troubleshooting.md.", penalty_count, len(clean_bins), pct, diff --git a/src/openflight/kld7/two_ray.py b/src/openflight/kld7/two_ray.py index 9e27cd8b0..5bf962f2c 100644 --- a/src/openflight/kld7/two_ray.py +++ b/src/openflight/kld7/two_ray.py @@ -1,14 +1,14 @@ """Two-ray multipath demodulation estimator for vertical launch angle. -Live port of the validated offline pipeline -(scripts/analysis/kld7_subframe_stft.py; findings in -docs/kld7-subframe-stft-findings.md). Each ~28.6 ms RADC frame is split -into overlapping sub-frame windows; the per-sub-frame Rx2/Rx1 phasor -ratios are fit to a two-ray (ball + floor image) interference model, -recovering the ball's true elevation through ground multipath instead of -averaging across it. Impact time is anchored by the multipath-immune F1B -range progression (range = tee distance at impact), so the estimator is -robust to host/OPS clock offsets. +Live port of the validated offline sub-frame STFT pipeline (the two-ray +model is explained in docs/legacy/launch-angle-explained.md, section 4). +Each ~28.6 ms RADC frame is split into overlapping sub-frame windows; +the per-sub-frame Rx2/Rx1 phasor ratios are fit to a two-ray (ball + +floor image) interference model, recovering the ball's true elevation +through ground multipath instead of averaging across it. Impact time is +anchored by the multipath-immune F1B range progression (range = tee +distance at impact), so the estimator is robust to host/OPS clock +offsets. Validated offline: 2.64 deg MAE pooled PW-4i vs TrackMan (2026-06-08 sessions, angle offset 3.5), 3.16 deg blind on a drift-era holdout. diff --git a/src/openflight/session_logger.py b/src/openflight/session_logger.py index b37049a0f..bf074722a 100644 --- a/src/openflight/session_logger.py +++ b/src/openflight/session_logger.py @@ -39,7 +39,7 @@ class SessionMetadata: # Globally unique session identity for cloud sync dedupe. The # timestamp-based session_id stays for filenames and display; this # UUID travels inside the data so renamed/copied session files keep - # their identity (see docs/cloud-sync-design.md). + # their identity (see docs/reference/cloud-uploader-spec.md). session_uuid: str = "" format_version: int = SESSION_FORMAT_VERSION app_version: str = "" diff --git a/tests/test_doc_references.py b/tests/test_doc_references.py new file mode 100644 index 000000000..d536679a2 --- /dev/null +++ b/tests/test_doc_references.py @@ -0,0 +1,40 @@ +"""Doc paths mentioned from the Python package must exist. + +Log messages, docstrings, and comments under ``src/openflight`` point users +at ``docs/...md`` pages. The docs restructure moved those pages into +sectioned directories and several pointers were left naming files that no +longer exist (see the kld7 OPS-bin penalty warning, which sent users to a +404 for months). This test fails on any such reference so a future docs +move cannot silently strand them again. +""" + +import re +from pathlib import Path + +import pytest + +REPO_ROOT = Path(__file__).resolve().parent.parent +PACKAGE_ROOT = REPO_ROOT / "src" / "openflight" +DOC_REF = re.compile(r"docs/[A-Za-z0-9_./-]+\.md") + + +def _doc_references() -> list[tuple[str, str]]: + found: list[tuple[str, str]] = [] + for path in sorted(PACKAGE_ROOT.rglob("*.py")): + text = path.read_text(encoding="utf-8") + for match in sorted(set(DOC_REF.findall(text))): + found.append((str(path.relative_to(REPO_ROOT)), match)) + return found + + +_REFERENCES = _doc_references() + + +def test_package_mentions_at_least_one_doc(): + """Guard against the scan silently matching nothing.""" + assert _REFERENCES, "expected src/openflight to reference docs/*.md somewhere" + + +@pytest.mark.parametrize(("source", "doc"), _REFERENCES, ids=[f"{s}:{d}" for s, d in _REFERENCES]) +def test_referenced_doc_exists(source, doc): + assert (REPO_ROOT / doc).is_file(), f"{source} points at {doc}, which does not exist"