Close the remaining audit findings

Environment, README, gitignore and the source self-parsing in Lab041.

requirements.txt and requirements-hardware.txt pin the versions actually
verified today on Python 3.13.1, split so the project comes up on a
machine with no SDR: pyadi-iio and libiio are only needed from Lab042 on.

The gitignore contradiction is fixed in the direction that keeps the
project reproducible. data/raw/ was ignored while six files were tracked
anyway, and four of them are the source images Lab007, Lab009, Lab011 and
Lab012 read as input. Untracking them would have broken those labs, so
the rule now carries explicit exceptions instead. Recorded in the README:
lab026_rover_source.mp4 is genuinely absent and Lab026 and Lab027 cannot
run without it.

README replaced. It claimed the next task was to write the first protocol
module, 41 labs later. It now states what exists, that the transmitter
has never been switched on, how to install either environment, how to run
tests, the gate and a lab, and that rover/, ground_station/ and gnuradio/
are still empty. Added rule 9: every number in a report must come from
the current run, transferred values must name their source.

Lab041 no longer parses its own source to check that plot labels are in
Russian. That belonged to presentation, not to model correctness, and
turned the experiment into an analyser of its own text; ast, inspect and
re are no longer imported. Rerun: 180 combinations, 24/24 checks, five
CSV and seven PNG, unchanged.

125 tests pass, gate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
LittleSam129
2026-08-10 15:33:14 +03:00
parent 92289bdf7c
commit 0ae04ae4a8
6 changed files with 164 additions and 273 deletions

View File

@@ -2,13 +2,10 @@
from __future__ import annotations
import ast
import csv
from dataclasses import asdict, dataclass
from enum import IntEnum
import inspect
from pathlib import Path
import re
from typing import Iterable
import cv2
@@ -1486,12 +1483,11 @@ def validate_outputs(
assert not any(path.suffix.lower() in forbidden for path in actual)
assert not any(path.name == "__pycache__" for path in OUTPUT_DIRECTORY.rglob("*"))
source = inspect.getsource(save_plots)
tree = ast.parse(source)
for node in ast.walk(tree):
if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and node.func.attr in {"set_title", "set_xlabel", "set_ylabel"}:
if node.args and isinstance(node.args[0], ast.Constant) and isinstance(node.args[0].value, str):
assert re.search("[А-Яа-яЁё]", node.args[0].value)
# Прежде здесь лабораторная разбирала собственный исходный код, чтобы
# убедиться, что подписи на графиках русские. Проверка снята: она
# относится к оформлению, а не к корректности модели, и превращала
# эксперимент в анализатор своего же текста. Подписи видны на готовых
# PNG и проверяются при просмотре результатов.
def main() -> None: