Commit Graph

35 Commits

Author SHA1 Message Date
LittleSam129
92289bdf7c Cover control messages and session state; record the RF decision
Two more suites, 69 checks, bringing the fast tests to 125 in 0.3 s.

test_control_messages: roundtrip for all ten message types, a guard that
fails if a type is added without a test, wrong version, unknown type,
truncation, the control-state range rules including negative and
non-finite speed, and sequence comparison across the 32-bit wrap and the
ambiguous 2^31 boundary.

test_session_state: the safety properties that previously only ran inside
Lab041. Safe boot on both sides, status and authorization not being a
movement command, a new operator command being required, stale session,
boot and epoch identifiers, replay, sequence wrap, ambiguity, persisted
emergency intent surviving a restart, acknowledgement not clearing it,
ordinary commands not releasing the latch, idempotent reset, and reset
not restoring the previous command.

Two of these were literal zeros in the Lab041 report and measured
nothing: negative speed and speed above the limit are now genuinely
exercised against the encoder.

PROJECT_LOG entry 018 records the RF architecture decision: 200-250 MHz
with frequency hopping, a directional ground antenna and spread spectrum
for the command channel, with the rejected alternatives and why.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 15:29:47 +03:00
LittleSam129
2da80d0908 Add the first real test suite for protocol/
56 fast checks, 0.2 s, covering packet.py and the new bpsk_radio.py.

test_bpsk_radio exists mainly to prove the extraction changed nothing. It
loads the original function definitions out of Lab018, Lab019 and Lab023
in isolation, compiling only the wanted AST nodes so the labs' module
level file writing never runs, then compares outputs: bit conversion,
modulation, shaping filter, frame marker and the carrier estimator over
random phase and frequency offsets.

It also covers the frame functions written fresh for the module:
roundtrip at four payload sizes, size and type rejection, broken sync
word, truncation, carrying a real CRC32 packet, and a shaped-signal
search that recovers the packet through matched filtering.

test_packet covers roundtrip across all four message types and five
payload sizes, sync word, length arithmetic, sequence range, truncation,
oversized payload, and single-bit corruption at six positions, which is
the property CRC32 is there to provide.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:38:12 +03:00
LittleSam129
c486039053 Split experiments from tests
The tests/ directory held 50 laboratory programs and no tests. They model
channels, run hundreds of repetitions and write CSV, PNG and reports;
calling that a test suite blocked introducing a real one, because any
pytest run would have collected the labs and re-executed every
experiment.

- move all 50 lab programs to experiments/ with git mv, preserving history
- rewrite the 38 cross-imports between labs from tests.labNNN to
  experiments.labNNN
- leave tests/ empty for actual fast checks of protocol/
- point quick_gate and the hook at the new layout and add experiments/ to
  the syntax sweep
- update the paths quoted in the Lab042 specification and the verifier
  agent definition

This also defuses the import-time work finding without touching 41 files:
the labs still create directories and write files on import, but nothing
imports them now except the gate, which does so deliberately.

Gate passes: syntax clean, protocol imports, 15 lab modules import, 2
functional suites run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:34:58 +03:00
LittleSam129
c9569164e0 Add protocol/bpsk_radio: reusable BPSK radio primitives
Lab042 cannot reuse the DSP from the earlier labs the way its
specification assumed. Three blockers turned up on inspection:

- importing lab018, lab019 or lab023 creates directories and writes .npy,
  .png and report files at module level, so importing them silently
  re-runs their experiments
- build_radio_frame() takes no arguments and encodes a fixed text message
- decode_radio_frame() returns a status string rather than the payload

So the verified primitives move into a module that is safe to import and
does no work of its own. Function bodies are carried over verbatim, and
the source lab is named above each one:

- from Lab023: bytes_to_bits, bits_to_bytes, bpsk_modulate,
  bpsk_demodulate, estimate_carrier_parameters, correct_phase_and_frequency
- from Lab019: build_frame_marker, find_radio_frame
- from Lab018: root_raised_cosine_taps

build_radio_frame and parse_radio_frame are written fresh here to carry
arbitrary payloads; the on-air structure is unchanged, still preamble,
sync word, length, packet.

Verified against the originals by loading their function definitions in
isolation and comparing outputs: 31 comparisons, no divergence, including
the CFO estimator over random phase and frequency offsets.

End-to-end check with no hardware: a 5828-byte JPEG through fragments,
packets, frames, shaping at 128 samples per symbol and matched filtering
recovers 12 of 12 fragments and reassembles byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:16:32 +03:00
LittleSam129
1e4adc0a98 Lab042: correct the sample rate against the real device
Queried the Pluto over IIO before writing any code. Three findings, one
of which invalidated the specification.

The AD9361 will not sample below 2 083 333 Hz, so the 640 kHz taken from
Lab018 is unreachable by a factor of three. Going lower needs the on-chip
FIR decimator, which would add an untested mechanism to the very first
transmit. Instead raise oversampling from 32 to 128 samples per symbol:
the symbol rate stays at 20 000, rolloff, preamble, sync word and guard
are untouched, and the rate becomes 2 560 000 Hz. Only the device
interface changes, not the signal.

Consequence recorded: the shaping filter grows to 1281 taps, so the
convolution has to go through scipy.signal.fftconvolve.

Also from the device:
- it reports as PlutoSDR Rev.C (Z7010-AD9361) with a single RX and a
  single TX buffer channel, so adi.Pluto is right and the adi.ad9361
  fallback is unnecessary
- the chip is a full AD9361: RX tunes 70 MHz to 6 GHz, TX from 46.9 MHz,
  so the sub-350 MHz target band is available without a firmware hack.
  That closes the open question flagged for Lab044
- firmware is v0.32, left alone for now

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:06:44 +03:00
LittleSam129
2a7a380875 Lab042: fix a cross-reference broken by renumbering
The TX cyclic buffer row pointed at section 7, which became the signal
parameters when the hardware and environment sections were inserted. It
means the traps section, now 9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:38:50 +03:00
LittleSam129
49c7009ca5 Lab042: drop the regulatory framing, keep the technical reasons
The project owner holds the permits for over-the-air work, so legality is
not a constraint this document should be reasoning about.

- retitle the section from "safety requirements" to what it actually
  covers: circuit integrity and not destroying the hardware
- rewrite the antenna rule on its real technical ground. An antenna opens
  a radiating path in parallel with the cable, so the level at the
  receiver stops matching the budget and reflections appear; the value of
  a cable loopback is that everything in it is known
- reframe "no over-the-air" as a scope boundary against Lab044 rather
  than a prohibition
- note in the roadmap that Lab044 is purely a technical choice of band,
  power and antenna

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:34:07 +03:00
LittleSam129
9f7387ec2c Lab042: attenuator on hand, relax the gain restriction
The bench has an AT30S: 30 dB, SMA, rated to 200 W. That removes the last
hardware blocker and changes the safety analysis.

With 30 dB in line, TX at full 0 dB gain lands at about -23 dBm on the
receiver, some 25 dB below the +2.5 dBm damage threshold. The whole
tx_hardwaregain range is therefore safe, so the staged -60 dB start and
the -30 dB ceiling are no longer needed.

- record the attenuator in the inventory and note that its 200 W rating is
  irrelevant here, attenuation does not depend on level
- replace the interim procedure with a level budget table and a starting
  point of -30 dB, giving about -53 dBm at the receiver
- require a visual check that the attenuator is actually in the path
  before the first transmit
- keep the ban on running without it: it guards against operator error,
  not against the calculated level

Only the environment blocker is left: pyadi-iio and libiio are missing
from the interpreter on PATH.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:33:24 +03:00
LittleSam129
923e6bec78 Lab042: adapt spec to the actual hardware and environment
Hardware confirmed from a photo of the bench: the device is a Pluto+
(2RX/2TX, Gigabit Ethernet), not the stock ADALM-PLUTO, plus an RTL-SDR
dongle and several antennas. No attenuator on hand.

- record the actual inventory and the Pluto+ differences that matter:
  Ethernet transport, two channels, adi.Pluto first with adi.ad9361 as
  the only permitted fallback
- replace "use an attenuator" with numbers: TX puts out about +7 dBm at
  0 dB, the RX damage threshold is about +2.5 dBm, so give a staged gain
  procedure starting at -60 dB and capped at -30 dB until an attenuator
  arrives
- require the antennas to be physically removed from the bench rather
  than merely left unplugged
- add the environment blocker found on inspection: the interpreter on
  PATH is a standalone Python 3.13.1 without pyadi-iio, libiio or scipy,
  while Lab024a clearly ran somewhere else; identifying and recording
  that environment is now the first task
- renumber sections and align the TX gain figure with the safety section

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:03:17 +03:00
LittleSam129
3d14c75365 Lab042: add hardware loopback specification
Specification for the first transmission through real hardware. The
project has no TX call anywhere across Lab001-Lab041, so the whole chain
exists but has never been connected to a transmitter.

Scope is deliberately minimal: get a JPEG through a cable loopback on a
single PlutoSDR and see the picture. Single device means TX and RX share
a reference clock, which removes the carrier offset and clock drift that
the receiver chain handles weakest.

- reuse Lab018 signal parameters unchanged, so hardware is the only new
  variable
- reuse image_fragments, packet, build_radio_frame, find_radio_frame
- list the first-time traps: cyclic TX buffer, sample scaling, RX started
  after TX, undersized RX buffer, automatic gain, receiver saturation
- define acceptance criteria and required measurements
- state explicitly what is out of scope: retransmission, erasure coding,
  higher rate, two devices, over-the-air

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 11:39:39 +03:00
LittleSam129
28227e4228 Add quick gate and independent review pipeline
Introduce tools/quick_gate.py: a one-second check that parses every file
in protocol, tests and tools, imports each protocol module, and runs the
functional tests of the labs that need no experiment data.

Wire it to a PostToolUse hook so edits under protocol or tests are checked
automatically, and add two read-only review agents with slash commands that
drive them: verifier for independent re-derivation of results, adversary for
unsafe-state hunting in control, failsafe, session and reset code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 17:33:46 +03:00
LittleSam129
7d122b53ed Lab041: remove non-modelled metrics and cite value sources
Audit found seven numbers in simulate_trial that were neither modelled by
Lab041 nor traceable to their claimed source. Video fraction 0.910 did not
match Lab040 (0.9603); base queue length 31 did not match Lab040 (36-38).

- drop video/telemetry/control delivered fractions and queue length: these
  belong to Lab037 and Lab040 and are not modelled here
- drop lab041_traffic_impact.png, which plotted only those metrics
- drop negative_speed_cases and speed_limit_exceeded_cases, never computed,
  along with the tautological asserts that checked them
- bind braking parameters to the Lab039 nominal profile via named constants
  instead of the literals 0.250 and the divisor 6.0
- cite Lab038 as the source of the transferred video and telemetry loads
- rewrite the invariants section: nine architecture-derived properties now
  carry functional-check references, five unmeasurable ones move to their
  own section
- extend check 04 with negative speed and the 15 m/s boundary
- state explicitly what the matrix rolls, what the architecture fixes and
  what is not modelled at all

Regenerated: 180 combinations, 24/24 checks, five CSV and seven PNG.
Six columns removed, no retained value changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 17:32:51 +03:00
LittleSam129
e18200225b Lab041: correct generated Git status wording 2026-08-07 10:50:42 +03:00
LittleSam129
f26d7d74ef Lab041: add session and restart safety 2026-08-05 14:14:24 +03:00
LittleSam129
88addff5b6 Lab040: add persistent emergency intent and safe reset 2026-08-05 13:12:49 +03:00
LittleSam129
b3ebe1637f Lab039: model two-stage failsafe braking 2026-08-05 11:44:43 +03:00
LittleSam129
23cfdf581b Lab038: add control failsafe and emergency acknowledgement 2026-08-04 14:06:50 +03:00
LittleSam129
50e45ca611 Lab037: evaluate control repetition on lossy link 2026-08-04 13:18:49 +03:00
LittleSam129
3e0ef5666e Lab036: validate long-duration video scheduling 2026-08-03 17:10:17 +03:00
LittleSam129
22c2eeab8c Lab035: add proactive video frame admission 2026-08-03 15:42:16 +03:00
LittleSam129
b63e36abdb Lab034: evaluate stale video frame dropping 2026-08-03 13:17:55 +03:00
LittleSam129
21751f41dd Lab033: add priority link scheduler 2026-08-03 12:21:49 +03:00
LittleSam129
3dbb7afa83 Lab032: evaluate FEC block parameters 2026-07-29 12:47:10 +03:00
LittleSam129
2ac1571c40 Lab031: evaluate FEC packet interleaving 2026-07-29 12:25:51 +03:00
LittleSam129
edab87b5d2 Lab030: add packet erasure FEC 2026-07-29 11:40:37 +03:00
LittleSam129
f8575f4de3 Lab029B: simulate time-based burst losses 2026-07-27 16:28:54 +03:00
LittleSam129
a2dd58a44b Lab029: simulate packet loss and channel errors 2026-07-27 15:29:39 +03:00
LittleSam129
04ce66fdfe Lab028: add video packetization and CRC reassembly 2026-07-27 13:46:01 +03:00
LittleSam129
78258b5355 Lab027: optimize synchronized ROI video stream 2026-07-24 17:54:27 +03:00
LittleSam129
6d49036066 Lab026: benchmark low-bitrate video and 4-bit encoding 2026-07-24 11:56:41 +03:00
LittleSam129
557b082f2b lab025_wfm_audio_100_1mhz 2026-07-22 17:29:07 +03:00
LittleSam129
f3a11b29b3 Merge branch 'repair/project-layout' 2026-07-22 14:20:11 +03:00
LittleSam129
35cb25fccc Create lab024a_pluto_rx_100mhz.npy 2026-07-22 11:24:05 +03:00
LittleSam129
1ff04b12b9 Repair project layout and fix Lab024B spectrum detection 2026-07-21 13:51:41 +03:00
LittleSam129
acf7a76546 initial commit 2026-07-20 13:58:58 +03:00