From f9493479c7f109757366b39efbc0980293697c04 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 9 Jul 2026 02:28:29 +0200 Subject: [PATCH] Honor YOLO preflight environment config --- CHANGELOG.md | 1 + backend/scripts/yolo_preflight.py | 17 +++++++---- backend/tests/test_sprint13_yolo_preflight.py | 30 +++++++++++++++++++ docs/CODEX_EXECUTION_LOG.md | 2 ++ docs/TODO.md | 1 + 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3997238..fa23fdf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1416,3 +1416,4 @@ Added: - Recorded live Tower audit results showing `yolo-building-tile-expanded160` as the clean current baseline and r4/r8 hard-negative datasets as repeat-heavy evidence sets that need more unique background AOIs before further hard-negative training. - Expanded the explicit operator background-candidate AOI registry from 3 to 9 unique hard-negative locations and added tests for diversity/spread before further YOLO training. - Fixed the all-in-one Dockerfile so documented operator scripts are copied into `/app/scripts/`, then prepared and audited the new Tower `yolo-building-tile-uniquehardneg160` dataset as the next training candidate. +- Fixed the YOLO preflight CLI so it respects environment-provided runtime configuration instead of reporting `not_configured` unless CLI flags were supplied. diff --git a/backend/scripts/yolo_preflight.py b/backend/scripts/yolo_preflight.py index ebf08fa2..a13d36d7 100644 --- a/backend/scripts/yolo_preflight.py +++ b/backend/scripts/yolo_preflight.py @@ -19,7 +19,7 @@ def main() -> int: parser.add_argument("--model-path", help="Existing local YOLO model path.") parser.add_argument("--tile-manifest-path", help="Existing raster tile manifest path.") parser.add_argument("--enabled", action="store_true", help="Treat YOLO as enabled for this preflight.") - parser.add_argument("--max-tiles", type=int, default=100, help="Maximum tile count allowed by preflight.") + parser.add_argument("--max-tiles", type=int, help="Maximum tile count allowed by preflight.") parser.add_argument( "--assume-dependencies", action="store_true", @@ -35,11 +35,16 @@ def main() -> int: if args.check_model_load and args.assume_dependencies: parser.error("--check-model-load cannot be combined with --assume-dependencies") - settings = Settings( - yolo_enabled=args.enabled or bool(args.model_path), - yolo_model_path=args.model_path, - yolo_max_tiles=args.max_tiles, - ) + settings = Settings() + settings_updates = {} + if args.enabled or args.model_path: + settings_updates["yolo_enabled"] = True + if args.model_path: + settings_updates["yolo_model_path"] = args.model_path + if args.max_tiles is not None: + settings_updates["yolo_max_tiles"] = args.max_tiles + if settings_updates: + settings = settings.model_copy(update=settings_updates) payload = YoloPreflightService.run( settings=settings, tile_manifest_path=args.tile_manifest_path, diff --git a/backend/tests/test_sprint13_yolo_preflight.py b/backend/tests/test_sprint13_yolo_preflight.py index 149190c6..53e3d4fd 100644 --- a/backend/tests/test_sprint13_yolo_preflight.py +++ b/backend/tests/test_sprint13_yolo_preflight.py @@ -197,6 +197,36 @@ def test_yolo_preflight_script_outputs_json(tmp_path: Path) -> None: assert payload["tile_manifest_path"] == str(manifest_path) +def test_yolo_preflight_script_uses_environment_configuration(tmp_path: Path, monkeypatch) -> None: + model_path = tmp_path / "model.pt" + model_path.write_bytes(b"weights") + manifest_path = _manifest(tmp_path) + monkeypatch.setenv("YOLO_ENABLED", "true") + monkeypatch.setenv("YOLO_MODEL_PATH", str(model_path)) + monkeypatch.setenv("YOLO_MAX_TILES", "4") + + result = subprocess.run( + [ + sys.executable, + str(ROOT / "scripts" / "yolo_preflight.py"), + "--tile-manifest-path", + str(manifest_path), + "--assume-dependencies", + "--json", + ], + cwd=ROOT, + check=True, + capture_output=True, + text=True, + ) + payload = json.loads(result.stdout) + + assert payload["status"] == "ready" + assert payload["checks"]["enabled"] is True + assert payload["model_path"] == str(model_path) + assert payload["max_tiles"] == 4 + + def test_yolo_preflight_script_rejects_assumed_dependencies_for_model_load(tmp_path: Path) -> None: result = subprocess.run( [ diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index c8cbcf16..e75b2ced 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -5680,12 +5680,14 @@ Open: - Added sample-registry test coverage for minimum unique background count, unique centers and regional spread. - Updated operator documentation with the expanded default corpus and the next required Tower regeneration step. - Fixed the all-in-one Dockerfile so the documented operator scripts are copied into `/app/scripts/` during normal rebuilds. +- Fixed `scripts/yolo_preflight.py` so it respects `YOLO_ENABLED`, `YOLO_MODEL_PATH` and `YOLO_MAX_TILES` from the runtime environment unless explicit CLI overrides are supplied. - Prepared the expanded Tower operator manifest and exported `yolo-building-tile-uniquehardneg160`. ## What was tested - `python -m pytest backend\tests\test_sprint131_operator_sample_expansion.py -q` - `python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py backend\tests\test_sprint131_operator_sample_expansion.py -q` +- `python -m pytest backend\tests\test_sprint13_yolo_preflight.py -q` - `bash scripts/run_readiness_check.sh` - Tower live operator sample prep: - manifest samples: 16 total, 7 reference and 9 background candidates. diff --git a/docs/TODO.md b/docs/TODO.md index f55f2d1e..2fc91134 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -453,4 +453,5 @@ This file now starts with the current implementation status. Older preparation/b - [x] Add test coverage for minimum background candidate count, unique centers and regional spread. - [x] Prepare the new samples on Tower and build a fresh hard-negative tile dataset. - [ ] Rebuild Tower all-in-one image so the newly copied operator scripts are available inside `/app/scripts` without `docker cp`. +- [x] Fix YOLO preflight CLI so it respects Tower `.env` runtime configuration. - [ ] Train a new candidate from `yolo-building-tile-uniquehardneg160` and run the positive/background promotion gates before activating it.