547 KiB
Sprint 169 Filtered YOLO candidate gate and operator hardening (2026-07-12)
Changed:
- Trained inactive local model asset
geointel-building-yolov8s-aoi1024cleanpx12vis035lowvar512e50-ptfrom the visually audited AOI1024 dataset after low-variance negative filtering. - Added SHA256 provenance fields to future
training_summary.jsonoutput fordataset.yaml, the dataset summary, the local base model and the copied trained model. - Kept long workbench context names compact with matching native tooltips and clamped readiness values to two lines.
- Archived the training, positive-AOI, split-background and promotion evidence under
artifacts/model-review/aoi1024cleanpx12vis035lowvar512e50locally and matching Tower artifact directories.
Runtime evidence:
- Training completed for 50 CPU epochs with YOLOv8s, image size
512, batch4; best-model validation ended at precision0.454, recall0.491, mAP500.368and mAP50-950.149. - Model catalog SHA256:
75345767b51cc66692a9d2c2cd6577b7feecaf5971c8762365e8b610b9dfde8e; catalog statusavailable,active=false,will_download_models=false. - Local model-load preflight passed with Torch
2.13.0and Ultralytics8.4.92; CUDA is unavailable and no model download occurred. - Seven-AOI persisted QA matrix produced 28 runs. Best single result was Westerlo at threshold
0.15, F10.3002114164904862. - Mean positive F1 was
0.153943at threshold0.05,0.153872at0.15,0.128891at0.25and0.099011at0.35. - Strict pure-empty background evidence was clean at thresholds
0.15,0.25and0.35; threshold0.05produced one Postel-bos detection. - Split-aware promotion report recommended
none: every threshold failed the positive mean-F1 gate, and0.05also failed background false-positive pressure. - The existing active
geointel-building-yolov8s-aoi1024bg512r3e50-ptremains materially stronger at its promoted0.35profile with mean F10.320866; no model default or.envvalue was changed. - Pushed implementation commit
8daaa07and redeployed the AI-enabled Tower all-in-one container onhttp://192.168.10.150:1202. - Post-deploy live migration smoke passed with PostGIS
3.6, required schema objects and Alembic head202606120900. - In-app browser verification found no console warnings/errors, confirmed matching full-value context tooltips and a two-line readiness value, and showed both the inactive low-variance candidate and the unchanged active
aoi1024bg512r3e50asset in Detection Lab.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint169_long_context_name_readability.py -qfailed before context tooltips and readiness clamping were present. python -m pytest backend/tests/test_sprint169_long_context_name_readability.py backend/tests/test_sprint22_workbench_status_strip.py backend/tests/test_sprint161_widescreen_workbench.py -q(5 passed).- Red step:
python -m pytest backend/tests/test_sprint129_operator_yolo_training_dataset.py::test_operator_yolo_train_smoke_script_contract -qfailed before training hashes were recorded. python -m pytest backend/tests/test_sprint129_operator_yolo_training_dataset.py -q(3 passed).bash -n scripts/train_operator_yolo_detector.shand frontend typecheck passed.- Full readiness:
bash scripts/run_readiness_check.sh(461 passed; one Alembic head; frontend typecheck/build and shell syntax gates passed).
Next:
- Do not retrain the same architecture blindly. Inspect per-AOI false-negative evidence and improve label geometry/class balance or add targeted positive samples for the weakest AOIs before the next candidate.
Sprint 164 Tower AI deploy env hardening (2026-07-11)
Changed:
- Hardened
scripts/deploy_tower.shandscripts/deploy_tower.ps1so the remote Tower.envis sourced before building the all-in-one image. - Updated the PowerShell deploy wrapper to stream the remote script through
bash -s, matching the Bash deploy path and preserving Bash variable expansion during.env-driven builds. - The PowerShell wrapper now writes a UTF-8-without-BOM temporary script, copies it with
scp, runs it withbashon Tower and removes the remote temp file while preserving the deploy exit code. GEOINTEL_INSTALL_AI=truein/mnt/user/appdata/geointel/.envnow drives the automatic image build by default; explicit local overrides remain possible for one-off deploys.- Documented the deploy behavior in
deploy/unraid/README.md.
Why:
- A manual
docker compose up -d --buildagainst the multi-container compose file failed on Tower because Docker had exhausted default bridge address pools. The healthy runtime is the Unraid all-in-one container, which should be redeployed through the Dockerman-native scripts instead. - The previous deploy script path could build a GIS-only image while the remote runtime
.envenabled YOLO, leaving the configured detector independency_unavailable.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint31_unraid_template.py::test_tower_deploy_build_uses_remote_env_ai_setting_by_defaultfailed because the deploy scripts did not source remote.envbeforedocker build. python -m pytest backend/tests/test_sprint31_unraid_template.py::test_tower_deploy_build_uses_remote_env_ai_setting_by_default backend/tests/test_sprint31_unraid_template.py::test_tower_deploy_uses_single_container_unraid_compose backend/tests/test_docker_runtime_config.py::test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env(3 passed).- Red step:
python -m pytest backend/tests/test_sprint31_unraid_template.py::test_powershell_tower_deploy_streams_remote_script_to_bash -qfailed because the PowerShell wrapper passed the remote script as an SSH command argument instead of streaming it tobash -s. python -m pytest backend/tests/test_sprint31_unraid_template.py::test_powershell_tower_deploy_streams_remote_script_to_bash backend/tests/test_sprint31_unraid_template.py::test_tower_deploy_build_uses_remote_env_ai_setting_by_default backend/tests/test_docker_runtime_config.py::test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env -q(3 passed).- Red step: the same PowerShell deploy transport test failed until the wrapper wrote a
[System.Text.UTF8Encoding]::new($false)temp script, copied it viascp, ran it through remotebashand propagated the remote exit code.
Sprint 150 YOLO label visible-ratio gate (2026-07-09)
Changed:
- Added
--min-label-visible-ratio/OPERATOR_YOLO_MIN_LABEL_VISIBLE_RATIOtoscripts/export_operator_yolo_tile_dataset.py. - The tile exporter now computes the visible share of each original building bbox inside a tile and can drop labels below the configured ratio.
- Default remains
0for legacy behavior; use0.25for the next overlap-heavy operator dataset experiment. - Tile dataset summaries include
min_label_visible_ratio. scripts/audit_operator_yolo_dataset_quality.pynow reportsmin_label_visible_ratioin JSON and Markdown.- Added operator-only
--width,--heightand--half-size-scaleoptions toscripts/prepare_operator_real_data_samples.py; generated raster names now include the requested width. - Updated operator script documentation.
Why:
- The current rejected AOI512 candidate still shows low precision/recall after max-det and duplicate suppression hardening.
- A likely label-quality issue is that overlapping tile export can create many small clipped edge labels for buildings mostly outside a tile.
- This pass improves the next training dataset gate without activating a model, faking detections, fetching providers or changing persistence.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py -qfailed because the exporter lackedmin_label_visible_ratio, CLI help and visible-fragment filtering. python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py -q(6 passed)- Red step:
python -m pytest backend\tests\test_sprint146_operator_yolo_dataset_quality_audit.py -qfailed because the audit report did not exposemin_label_visible_ratio. python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py backend\tests\test_sprint146_operator_yolo_dataset_quality_audit.py -q(7 passed)- Red step:
python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py backend\tests\test_sprint131_operator_sample_expansion.py -qfailed because sample prep lacked larger-AOI options. python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py backend\tests\test_sprint131_operator_sample_expansion.py -q(8 passed)- Full readiness:
bash scripts/run_readiness_check.sh(427 passed, frontend typecheck/build passed). - Tower deploy: first AI rebuild failed with Docker storage full; after Docker build cache cleanup
/var/lib/dockerhad 98G free and redeploy passed live migration smoke and browser runtime verification onhttp://192.168.10.150:1202. - Tower dataset audit: exported
/app/storage/operator-data/yolo-building-aoi512-visible025withmin_label_visible_ratio=0.25; audit returnedneeds_attentionbecause the current 512x512 source rasters still produce only 16 tiles and median normalized box area remains below gate.
Next:
- Prepare a larger explicit operator sample manifest, for example
/app/storage/operator-data/operator-samples-1024with--width 1024 --height 1024 --half-size-scale 2, then export/audityolo-building-aoi1024-visible025before another CPU training candidate.
Sprint 149 YOLO duplicate suppression evidence (2026-07-09)
Changed:
- Added configured-YOLO cross-tile duplicate suppression after pixel boxes are converted to EPSG:4326 geometries and before
Detectionrows are persisted. - Added backend setting
YOLO_DUPLICATE_IOU_THRESHOLDwith default0.5;0disables the GeoIntel-side pass for debugging. - Detection run
result_jsonnow records:raw_detection_countsuppressed_detection_countduplicate_iou_threshold
- Updated
.env.example, Docker Compose, Unraid env examples and the Dockerman run script. - Updated calibration and quality matrix scripts to fetch detection run details and include raw/suppressed counts in per-run and aggregate summaries.
- Updated backend/API/AI/pipeline documentation.
Why:
- Dense overlapping tile inference can produce duplicate candidate buildings, which inflates persisted false positives before QA/QC.
- The previous Sprint 148 cap fix allowed dense AOIs to persist more candidates, but made duplicate pressure more visible.
- This pass keeps all outputs honest: no model activation, no fake detections and no migration. It only removes lower-confidence same-class geometric duplicates before persistence.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint8b_yolo_foundation.py::test_yolo_run_suppresses_cross_tile_duplicate_detections -qfailed withdetection_count == 2. python -m pytest backend\tests\test_sprint8b_yolo_foundation.py::test_yolo_run_suppresses_cross_tile_duplicate_detections -q(1 passed)- Red step: Docker runtime config tests failed before
.env.exampleand Unraid runner exposedYOLO_DUPLICATE_IOU_THRESHOLD. python -m pytest backend\tests\test_sprint8b_yolo_foundation.py backend\tests\test_docker_runtime_config.py::test_env_example_uses_runtime_env_names_read_by_backend_and_frontend backend\tests\test_docker_runtime_config.py::test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env -q(17 passed)- Red step: calibration/matrix script tests failed before detection-run raw/suppressed metadata was included.
python -m pytest backend\tests\test_sprint124_detection_calibration_sweep.py backend\tests\test_sprint126_detection_quality_matrix.py backend\tests\test_sprint127_operator_sample_quality_matrix.py::test_multi_sample_detection_quality_matrix_runs_existing_matrix_for_each_sample -q(3 passed)bash -n scripts/run_detection_calibration_sweep.shbash -n scripts/run_detection_quality_matrix.shbash -n scripts/run_multi_sample_detection_quality_matrix.shbash scripts/run_readiness_check.sh(426 passed, frontend typecheck/build passed)- Redeployed Tower all-in-one image with AI dependencies and verified
YOLO_MAX_DETECTIONS=1000plusYOLO_DUPLICATE_IOU_THRESHOLD=0.5in the live container. - Tower live migration smoke and browser runtime verification passed.
- Live Westerlo calibration with
geointel-building-yolov8s-aoi512e80-pt:0.25: 202 persisted / 270 raw / 68 suppressed, F10.25373134328358210.15: 328 persisted / 523 raw / 195 suppressed, F10.220543806646525680.05: 586 persisted / 1000 raw / 414 suppressed, F10.17173913043478262
- Live Turnhout calibration with
geointel-building-yolov8s-aoi512e80-pt:0.25: 559 persisted / 822 raw / 263 suppressed, F10.141141141141141120.15: 659 persisted / 1000 raw / 341 suppressed, F10.143854748603351960.05: 659 persisted / 1000 raw / 341 suppressed, F10.14385474860335196
Conclusion:
- Cross-tile duplicate suppression reduces false-positive pressure and improves F1 versus the Sprint 148 uncapped baseline on the checked dense AOIs.
- The current AOI512 YOLOv8s candidate remains rejected for default use because recall/precision are still too low after post-processing.
- Next model work should focus on stronger training data/label strategy and a new candidate gate, not further default threshold lowering.
Sprint 148 YOLO max-detection cap hardening (2026-07-09)
Changed:
- Added backend setting
YOLO_MAX_DETECTIONS/Settings.yolo_max_detections. YoloDetectionAdapternow forwards the value to Ultralytics asmax_det.- Default is
1000instead of relying on Ultralytics' upstream default of 300. - Added Docker/Unraid/runtime wiring:
.env.exampledocker-compose.ymldocker-compose.unraid.ymldeploy/unraid/geointel.env.exampledeploy/unraid/run-dockerman-container.sh
- Updated backend/API/AI environment documentation.
Why:
- Real Kempen building AOIs often contain more than 300 reference buildings.
- The previous configured-YOLO path could saturate at 300 detections before QA/QC, capping recall independently of model quality.
- This does not activate a model and does not fake detections; it removes an inference runtime cap so persisted QA/QC can measure candidate models honestly.
Tested:
- Red step: targeted YOLO adapter tests failed because
max_detwas not passed to the model. python -m pytest backend\tests\test_sprint8b_yolo_foundation.py::test_yolo_adapter_converts_single_band_tiles_to_rgb_before_prediction backend\tests\test_sprint8b_yolo_foundation.py::test_yolo_adapter_uses_configured_max_detections -q(2 passed)- Red step: Docker runtime config tests failed before
.env.exampleand Unraid runner exposedYOLO_MAX_DETECTIONS. python -m pytest backend\tests\test_docker_runtime_config.py::test_env_example_uses_runtime_env_names_read_by_backend_and_frontend backend\tests\test_docker_runtime_config.py::test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env backend\tests\test_sprint8b_yolo_foundation.py -q(16 passed)bash scripts/run_readiness_check.sh(425 passed, frontend typecheck/build passed)- Redeployed Tower all-in-one image with AI dependencies and verified
YOLO_MAX_DETECTIONS=1000in the live container. - Tower live migration smoke passed against embedded PostGIS.
- Live Westerlo calibration with
geointel-building-yolov8s-aoi512e80-pt:0.25: 270 detections, F10.235099337748344380.15: 523 detections, F10.196032672112018640.05: 1000 detections, F10.13193403298350823
- Live Turnhout calibration with
geointel-building-yolov8s-aoi512e80-pt:0.25: 822 detections, F10.13040752351097180.15: 1000 detections, F10.130851663846587720.05: 1000 detections, F10.13085166384658772
Conclusion:
- The former 300-detection runtime cap is removed; dense AOIs can now persist more candidates.
- The current AOI512 YOLOv8s candidate remains rejected for operational use because precision/recall quality is still too low and low thresholds saturate the configured
1000cap. - Next model work should focus on training data coverage, label strategy and post-processing/NMS behavior rather than only threshold lowering.
Sprint 147 AOI512 YOLOv8s scale-match candidate gate (2026-07-09)
Changed:
- Built an alternate operator YOLO dataset at AOI scale instead of small 160px tiles:
- output
/app/storage/operator-data/yolo-building-aoi512-uniquehardneg - tile size
512, stride512 - validation samples
turnhout,retie,westerlo,arendonk_heide - 16 total images, 13 positive images, 3 negative images, 3172 labels
- output
- Audited the AOI512 dataset:
- output
/mnt/user/appdata/geointel/artifacts/operator-yolo-dataset-audits/aoi512-uniquehardneg/operator_yolo_dataset_quality_audit.json - status
ok - no missing label files
- no invalid label rows
- 13 positive samples
- 3 positive validation samples
- median normalized box area
0.000793456875
- output
- Trained a Tower-local YOLOv8s scale-match candidate:
- dataset
/app/storage/operator-data/yolo-building-aoi512-uniquehardneg/dataset.yaml - base model
/app/models/yolov8s.pt - 80 CPU epochs
- image size
512 - batch
4 - artifact
/app/models/geointel-building-yolov8s-aoi512e80.pt - model asset id
geointel-building-yolov8s-aoi512e80-pt - SHA256
b796284a13358498c296fa41270dd234a81718a76cdafe62490a5206bb86ac5b
- dataset
- The training validation improved versus the previous 160px candidate but remained weak:
- precision
0.404 - recall
0.270 - mAP50
0.163 - mAP50-95
0.0505
- precision
Tested:
- Ran 7-AOI positive calibration sweeps for Geel, Mol, Turnhout, Herentals, Balen, Retie and Westerlo:
- output root
/mnt/user/appdata/geointel/artifacts/detection-calibration/aoi512e80-positive - best sample: Westerlo threshold
0.25, F10.23509933774834438, precision0.26296296296296295, recall0.2125748502994012, detections270 - most other AOIs remained around F1
0.10to0.14
- output root
- Ran 9-sample hard-negative/background matrix:
- output
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/aoi512e80/hard_negative_matrix_summary.json - threshold
0.25: total background detections105, max sample detections56 - threshold
0.15: total background detections181, max sample detections100 - threshold
0.05: total background detections503, max sample detections278
- output
- Assembled positive evidence portfolio:
- output
/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/aoi512e80-positive/calibration_evidence_portfolio.json - sample count
7 - evidence features
17156
- output
- Ran promotion report:
- output
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/aoi512e80-positive-vs-hard-negative/detection_model_promotion_report.json - threshold
0.05: rejected forpositive_mean_f1_below_gateandbackground_false_positive_pressure, mean F10.1335249717919908, max background detections278 - threshold
0.15: rejected for the same reasons, mean F10.1335249717919908, max background detections100 - threshold
0.25: rejected for the same reasons, mean F10.13511851520077328, max background detections56 - recommended candidate
none
- output
Open:
- Do not activate
geointel-building-yolov8s-aoi512e80-ptas the V1 default. - AOI-scale training improves the Ultralytics validation curve but does not improve persisted QA/QC enough for operational use.
- The recurring failure mode is overproduction near the 300-detection cap with low recall and too many false positives.
- Next recommended pass: add/export more diverse positive AOIs and improve label quality/geometry-to-box strategy before training another higher-capacity model. A pure scale or epoch change is not enough.
Sprint 146 Unique hard-negative YOLOv8s candidate gate (2026-07-09)
Changed:
- Fixed the all-in-one Docker runtime so
/app/scripts/train_operator_yolo_detector.shis copied into the image and made executable. - Added regression coverage in
backend/tests/test_docker_runtime_config.pyso the all-in-one image must include the operator YOLO training wrapper. - Hardened
scripts/build_detection_model_promotion_report.pywith explicit--default-positive-tile-sizeand--default-positive-tile-overlapoptions for older positive evidence portfolios that record the model at portfolio level but omit per-run tile provenance. - Added regression coverage in
backend/tests/test_sprint143_detection_model_promotion_report.pyfor portfolio-level model fallback plus explicit positive tile defaults.
Tested:
- Red step:
python -m pytest backend\tests\test_docker_runtime_config.py::test_all_in_one_dockerfile_copies_operator_scripts_for_runtime_use -qfailed because the all-in-one Dockerfile did not copy the training wrapper. python -m pytest backend\tests\test_docker_runtime_config.py -q(22 passed)bash scripts/run_readiness_check.sh(423 passed; frontend typecheck/build passed; Alembic head202606120900)- Pushed commit
afd2cbaand redeployed Tower with.\scripts\deploy_tower.ps1 -InstallAi true; browser runtime verification and live migration smoke passed. - Verified the wrapper in the live container:
/app/scripts/train_operator_yolo_detector.shexists and is executable. - Trained
geointel-building-yolov8s-uniquehardneg160e50-pton Tower from/app/storage/operator-data/yolo-building-tile-uniquehardneg160/dataset.yamlusing local/app/models/yolov8s.pt, 50 CPU epochs, image size160, batch8. - Training completed with final validation precision
0.38, recall0.365, mAP500.278, mAP50-950.0803. - Live model asset:
/app/models/geointel-building-yolov8s-uniquehardneg160e50.pt- model asset id
geointel-building-yolov8s-uniquehardneg160e50-pt - SHA256
c4e480273d3da5fc27532cd8bdc3fa7786582e06848ea11b56714ab8cb1750b3
- Ran 7-AOI positive calibration sweeps for Geel, Mol, Turnhout, Herentals, Balen, Retie and Westerlo:
- output root
/mnt/user/appdata/geointel/artifacts/detection-calibration/uniquehardneg160e50-positive - best observed AOI result: Westerlo threshold
0.25, F10.384180790960452, precision0.5177664974619289, recall0.30538922155688625, detections197 - other positive AOIs remained weak, with best F1 roughly
0.10to0.17.
- output root
- Assembled positive evidence portfolio:
- output
/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/uniquehardneg160e50-positive/calibration_evidence_portfolio.json - sample count
7 - evidence features
17008 - role counts
false_negative=9710,false_positive=4734,match_candidate=1282,match_reference=1282
- output
- Ran 9-sample hard-negative/background matrix:
- output
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/uniquehardneg160e50/hard_negative_matrix_summary.json - threshold
0.25: total background detections98, max sample detections58 - threshold
0.15: total background detections137, max sample detections85 - threshold
0.05: total background detections276, max sample detections172
- output
- Red step:
python -m pytest backend\tests\test_sprint143_detection_model_promotion_report.py -qfailed because the promotion report could not yet accept explicit positive tile defaults. python -m pytest backend\tests\test_sprint143_detection_model_promotion_report.py -q(2 passed)- Rebuilt the promotion report using explicit positive tile defaults:
- output
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/uniquehardneg160e50-positive-vs-hard-negative-v2/detection_model_promotion_report.json - threshold
0.05: rejected forpositive_mean_f1_below_gateandbackground_false_positive_pressure, mean F10.15797188547918842, max background detections172 - threshold
0.15: rejected for the same reasons, mean F10.1598974047548654, max background detections85 - threshold
0.25: rejected for the same reasons, mean F10.15967766715169612, max background detections58 - recommended candidate
none
- output
Open:
- Do not activate
geointel-building-yolov8s-uniquehardneg160e50-ptas the V1 default. - The candidate improves some individual AOIs but still combines low mean positive F1 with unacceptable false-positive pressure on background samples.
- Next model work should focus on materially better training data/model strategy, not another default activation attempt with this artifact.
Sprint 145 YOLOv8s hardneg r8 e60 full candidate evaluation (2026-07-08)
Changed:
- Verified that the Tower-local YOLOv8s hardneg r8 training run completed all 60 requested CPU epochs.
- Finalized the completed model artifact:
/app/models/geointel-building-yolov8s-hardneg160r8e60.pt- model asset id
geointel-building-yolov8s-hardneg160r8e60-pt - SHA256
d7daea04bd51a54a06944f0d4bf1961fe453dceb1fb34ef51daa73f6901fca81
- Wrote
/app/storage/training/operator-yolo/geointel-building-yolov8s-hardneg160r8e60/training_summary.json.
Tested:
- Training summary reports
status=ok, requested epochs60, completed epochs60. - Ran 7-AOI positive matrix:
- output
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/yolov8s-hardneg160r8e60-positive-20260708/multi_sample_quality_summary.json - sample count
7 - run count
21 - best result: Westerlo threshold
0.15, F1/score0.20588235294117646, precision0.26666666666666666, recall0.16766467065868262, detections210, false positives154, false negatives278.
- output
- Ran hard-negative matrix:
- output
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/yolov8s-hardneg160r8e60-live/hard_negative_matrix_summary.json - Postel-bos detections
0/0/0at thresholds0.05/0.15/0.25 - Lommel-heide detections
0/0/0 - Kasterlee-bos detections
30/11/9
- output
- Assembled evidence portfolio:
- output
/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/yolov8s-hardneg160r8e60-positive-20260708/output/calibration_evidence_portfolio.json - sample count
7 - evidence features
15714 - role counts
false_negative=10468,false_positive=4198,match_candidate=524,match_reference=524
- output
- Ran promotion report:
- output
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/yolov8s-hardneg160r8e60-20260708/detection_model_promotion_report.json - evaluated
3candidate thresholds - recommended candidate
none - threshold
0.05: mean F10.07825931710275633, max background detections30, rejected forpositive_mean_f1_below_gateandbackground_false_positive_pressure - threshold
0.15: mean F10.07870592446136859, max background detections11, rejected for the same reasons - threshold
0.25: mean F10.06111741186503092, max background detections9, rejected for the same reasons
- output
- Comparison baseline:
geointel-building-yolov8n-expanded160e50-pt|640|64|0.15had mean F10.19718007234060198and max background detections46.
Open:
- The e60 YOLOv8s hardneg r8 candidate improves hard-negative behavior at threshold
0.15compared withexpanded160e50, but its positive-AOI mean F1 is too low for operational use. - Do not activate this model as default.
- Next model pass should focus on improving positive recall/fit without losing the hard-negative gains, likely through better labels, more positive AOIs, or a different architecture/training strategy rather than simply extending this same run.
Sprint 144 YOLOv8s hardneg r8 partial candidate evaluation (2026-07-08)
Changed:
- Started a Tower-local YOLOv8s training run using:
- dataset
/app/storage/operator-data/yolo-building-tile-hardneg160r8/dataset.yaml - base model
/app/models/yolov8s.pt - requested epochs
60 - image size
640 - batch
2 - device
cpu
- dataset
- The Codex command reached its 1-hour timeout after 12 completed epochs; the run had produced
weights/best.ptandweights/last.pt. - Preserved the partial best artifact as
/app/models/geointel-building-yolov8s-hardneg160r8e12partial.pt. - Wrote
/app/storage/training/operator-yolo/geointel-building-yolov8s-hardneg160r8e60/training_summary_partial_e12.json. - Treated the artifact explicitly as a partial evaluation candidate, not as a completed 60-epoch model.
Tested:
- Live model catalog listed
geointel-building-yolov8s-hardneg160r8e12partial-ptwith SHA2560246202cddc47eb994a0afc9ee10d56b72298bd1cdc0b72b75e12b28e2202330. - Ran 7-AOI positive matrix:
- output
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/yolov8s-hardneg160r8e12partial-positive-20260708/multi_sample_quality_summary.json - sample count
7 - run count
21 - best result: Westerlo threshold
0.05, F1/score0.14826498422712936, precision0.15666666666666668, recall0.1407185628742515, detections300, false positives253, false negatives287.
- output
- Ran hard-negative matrix:
- output
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/yolov8s-hardneg160r8e12partial-live/hard_negative_matrix_summary.json - Postel-bos detections
0/0/0at thresholds0.05/0.15/0.25 - Lommel-heide detections
0/0/0 - Kasterlee-bos detections
18/1/0
- output
- Assembled evidence portfolio:
- output
/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/yolov8s-hardneg160r8e12partial-positive-20260708/output/calibration_evidence_portfolio.json - sample count
7 - evidence features
12908 - role counts
false_negative=10861,false_positive=1785,match_candidate=131,match_reference=131
- output
- Ran promotion report:
- output
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/yolov8s-hardneg160r8e12partial-20260708/detection_model_promotion_report.json - evaluated
3candidate thresholds - recommended candidate
none - threshold
0.05rejected forpositive_mean_f1_below_gateandbackground_false_positive_pressure, with mean F10.05026994383963278and max background detections18 - threshold
0.15rejected for the same reasons, with mean F10.0022606965174129354and max background detections1 - threshold
0.25rejected for insufficient positive evidence and positive F1 below gate.
- output
Open:
- The partial YOLOv8s r8 candidate is materially worse than the existing
expanded160e50positive-AOI baseline and must not be activated. - CPU-only training is too slow for a complete 60-epoch YOLOv8s pass inside a 1-hour interactive command window.
- Next pass should either resume/finish long-running training outside the interactive timeout or use GPU/accelerated runtime; only then rerun the same positive, hard-negative, evidence portfolio and promotion gates.
Sprint 143 Detection model promotion decision report (2026-07-08)
Changed:
- Added
scripts/build_detection_model_promotion_report.pyas operator-only evidence tooling. - The script combines a positive-AOI
calibration_evidence_portfolio.jsonwith one or morehard_negative_matrix_summary.jsonfiles. - Candidate rows are grouped by
model_asset_id,tile_size,tile_overlapandthreshold. - Promotion gates are explicit:
- minimum positive sample count
- minimum background sample count
- minimum mean positive F1
- maximum background detections per sample
- Added readiness
py_compilecoverage for the new script. - Documented the Tower command in
scripts/README.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint143_detection_model_promotion_report.py -qfailed because the report script did not exist. python -m pytest backend\tests\test_sprint143_detection_model_promotion_report.py -q(1 passed)python -m pytest backend\tests\test_sprint143_detection_model_promotion_report.py backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py -q(2 passed)python -m py_compile scripts\build_detection_model_promotion_report.pypython scripts\smoke_docs.pybash scripts/run_readiness_check.sh(419 passed; frontend typecheck/build passed; Alembic head202606120900)- Tower pulled commit
c2fba67and generated:/mnt/user/appdata/geointel/artifacts/detection-model-promotion/positive-expanded-vs-hard-negative-20260708/detection_model_promotion_report.json/mnt/user/appdata/geointel/artifacts/detection-model-promotion/positive-expanded-vs-hard-negative-20260708/detection_model_promotion_report.md
- Live promotion report evaluated 15 model/tile/threshold candidates and recommended
none. - Best current positive candidate
geointel-building-yolov8n-expanded160e50-pt|640|64|0.15was rejected by gates:positive_mean_f1_below_gatebackground_false_positive_pressure- positive samples
7 - background samples
3 - mean F1
0.19718007234060198 - max background detections
46 - total background detections
46
- Tower container remained healthy on
0.0.0.0:1202->80/tcp.
Open:
- No evaluated model/threshold is ready for default promotion.
- Next model work should improve positive recall/F1 while preserving a strict hard-negative false-positive gate.
Sprint 141 Expanded positive-AOI matrix and portfolio metadata hardening (2026-07-08)
Changed:
- Ran a fresh Tower multi-sample quality matrix for additional positive AOIs
balen,herentalsandwesterlousing:geointel-building-yolov8n-expanded160e50-ptgeointel-building-yolov8n-hardneg160r8e40-pt- tile size
640, overlap64, thresholds0.15and0.05.
- Assembled a broader positive-AOI evidence portfolio across 7 AOIs:
- Geel, Mol, Turnhout and Retie from
expanded160e50-live. - Balen, Herentals and Westerlo from the fresh
balen-herentals-westerlo-live-20260708run.
- Geel, Mol, Turnhout and Retie from
- Hardened
scripts/export_detection_calibration_evidence.shso evidence bundles preserve calibration provenance fields in run summaries and GeoJSON properties:model_asset_idmodel_requesttile_sizetile_overlap
- Extended
backend/tests/test_sprint139_multi_aoi_calibration_evidence_portfolio.pyto assert portfolio best-run model/tile provenance is retained.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py -qfailed withKeyError: 'model_asset_id'while bundle summaries dropped model provenance. python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py -q(1 passed)python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py backend\tests\test_sprint138_calibration_evidence_bundle_smoke.py backend\tests\test_sprint137_browser_calibration_summary_evidence_script.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py -q(4 passed)bash -n scripts/export_detection_calibration_evidence.shbash -n scripts/assemble_detection_calibration_evidence_portfolio.shpython -m compileall backend/appbash scripts/run_readiness_check.sh(418 passed; frontend typecheck/build passed; Alembic head202606120900; shell syntax gates passed)- Tower fresh matrix completed for Balen, Herentals and Westerlo.
- Tower positive-AOI portfolio assembly completed for 7 AOIs.
- Tower runtime remained healthy on
0.0.0.0:1202->80/tcp.
Evidence:
- Fresh Balen/Herentals/Westerlo output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/balen-herentals-westerlo-live-20260708/multi_sample_quality_summary.json. - Expanded 7-AOI portfolio output:
/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/positive-aoi-expanded-20260708/output/calibration_evidence_portfolio.json. - Expanded positive-AOI portfolio sample count:
7. - Expanded positive-AOI evidence features:
12438. - Expanded positive-AOI role counts:
false_negative=9200,false_positive=2270,match_candidate=484,match_reference=484. - Best fresh positive-AOI result: Westerlo with
geointel-building-yolov8n-expanded160e50-pt, threshold0.05, F1/score0.3659305993690852, precision0.38666666666666666, recall0.3473053892215569. - Fresh Balen best: expanded160e50 threshold
0.05, F1/score0.16091954022988506, precision0.16333333333333333, recall0.15857605177993528. - Fresh Herentals best: expanded160e50 threshold
0.05, F1/score0.14093264248704665, precision0.22666666666666666, recall0.10225563909774436. - Hard-negative context from existing matrices:
- expanded160e50 at
0.05: Kasterlee-bos76, Lommel-heide10, Postel-bos1detections. - hardneg160r8e40 at
0.05: Kasterlee-bos25, Lommel-heide0, Postel-bos0detections.
- expanded160e50 at
Open:
- expanded160e50 is stronger on positive AOIs, especially Westerlo, but still produces many false positives and misses many references.
- hardneg160r8e40 is cleaner on hard-negative AOIs but materially weaker on the fresh positive AOIs.
- No current candidate should be promoted blindly as V1 default without a combined positive/hard-negative decision rule.
Limitations:
- This pass ran additional live inference/QA workflows and produced operator artifacts, but did not change backend APIs, migrations, frontend runtime behavior, model weights, provider fetching or Docker runtime configuration.
- The 7-AOI portfolio initially generated before the metadata fix lacked model/tile provenance in
best_run_by_score; it should be regenerated after Tower pulls this commit.
Next recommended pass:
- Add a model promotion decision report that combines positive-AOI F1/recall and hard-negative false-positive pressure into one explicit accept/reject table per model and threshold.
Sprint 140 Live multi-AOI calibration portfolio run (2026-07-08)
Changed:
- Created a Tower-local
calibration-evidence-portfolio-manifest.jsonfor existing persisted multi-sample quality matrix summaries:- Geel:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/geel/quality_matrix_summary.json - Mol:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/mol/quality_matrix_summary.json - Turnhout:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/turnhout/quality_matrix_summary.json
- Geel:
- Ran
scripts/assemble_detection_calibration_evidence_portfolio.shagainst the live Tower app athttp://127.0.0.1:1202. - Produced the first real multi-AOI calibration evidence handoff:
/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/live-20260708/output/calibration_evidence_portfolio.json/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/live-20260708/output/calibration_evidence_portfolio.md- per-sample
calibration_evidence.geojson,calibration_evidence_summary.jsonandcalibration_evidence_review.htmlartifacts for Geel, Mol and Turnhout.
Tested:
- Tower manifest validation passed with
python3 -m json.tool. - Live portfolio assembly passed against persisted QA evidence from the running app.
- Output validation passed: portfolio JSON/Markdown and all per-sample evidence GeoJSON/summary/review files exist and are non-empty.
- Tower runtime remained healthy on
0.0.0.0:1202->80/tcp.
Evidence:
- Portfolio sample count:
3. - Total evidence features:
5509. - Combined role counts:
false_negative=5239,false_positive=164,match_candidate=53,match_reference=53. - Best sample by score:
mol. - Best per-sample scores:
- Geel: threshold
0.15, F1/score0.0187207488299532, precision0.25, recall0.009724473257698542, evidence features1885. - Mol: threshold
0.15, F1/score0.04195804195804196, precision0.16363636363636364, recall0.02406417112299465, evidence features1223. - Turnhout: threshold
0.15, F1/score0.03597122302158273, precision0.2459016393442623, recall0.019404915912031046, evidence features2401.
- Geel: threshold
Open:
- The live portfolio confirms the evidence pipeline works, but the evaluated model/threshold set is not yet operational-quality for building extraction due to very low recall and a dominant false-negative count.
Limitations:
- This pass produced operator artifacts only. It did not rerun inference, mutate application data, change database state, add endpoints, change frontend runtime behavior, download models, train models or rebuild the Docker app.
- The portfolio input came from the existing
20260707T025932Zquality matrix; the next model review should use fresh matrices when new AOIs or model candidates are added.
Next recommended pass:
- Add more positive and hard-negative AOIs, then run a fresh multi-sample quality matrix and portfolio for the next model candidate. Do not promote the current evaluated model as a V1 default.
Sprint 139 Multi-AOI calibration evidence portfolio (2026-07-08)
Changed:
- Added
scripts/assemble_detection_calibration_evidence_portfolio.shfor packaging multiple AOI calibration summaries and their persisted QA evidence bundles into one model-review portfolio. - The assembler reads
calibration-evidence-portfolio-manifest.json, copies each AOI summary into a sample folder, runs the existingscripts/export_detection_calibration_evidence.shexporter per sample and writes:calibration_evidence_portfolio.jsoncalibration_evidence_portfolio.md
- Added optional
CURL_BINsupport toscripts/export_detection_calibration_evidence.shso operator smokes/tests can inject a deterministic endpoint mock while defaulting to normalcurl. - Added readiness syntax coverage and operator docs for the manifest convention.
- Updated
scripts/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint139_multi_aoi_calibration_evidence_portfolio.py.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py -qfailed whilescripts/assemble_detection_calibration_evidence_portfolio.shwas absent. python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py -q(1 passed)python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py backend\tests\test_sprint138_calibration_evidence_bundle_smoke.py backend\tests\test_sprint137_browser_calibration_summary_evidence_script.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py -q(4 passed)bash -n scripts/assemble_detection_calibration_evidence_portfolio.shbash scripts/assemble_detection_calibration_evidence_portfolio.sh --helpbash -n scripts/export_detection_calibration_evidence.shbash scripts/export_detection_calibration_evidence.sh --helppython -m compileall backend/appbash scripts/run_readiness_check.sh(418 passed; frontend typecheck/build passed; Alembic head202606120900; shell syntax gates passed)
Open:
- None for this pass.
Limitations:
- This is local/operator evidence packaging only. It does not run inference, call live production data by itself, mutate application data, add backend endpoints, change migrations, create QA metrics, promote thresholds, download models, add provider fetching or change frontend runtime behavior.
- The regression test uses mocked canonical QA evidence responses; real persisted QA evidence remains validated by running the portfolio assembler against live Detection Lab or calibration-sweep summaries.
Next recommended pass:
- Run the portfolio assembler against the existing Tower calibration summaries for at least two real AOIs, then use the portfolio JSON/Markdown as the first model-review handoff artifact before any further training or threshold promotion.
Sprint 138 Browser calibration evidence bundle smoke (2026-07-08)
Changed:
- Added
scripts/smoke_detection_calibration_evidence_bundle.shas a local operator smoke for the Detection Labdetection-calibration-summary.jsonto QA evidence bundle path. - The smoke creates a temporary browser-style calibration summary, injects a temporary mock
curlfor canonical QA evidence endpoint responses, runs the realscripts/export_detection_calibration_evidence.shexporter and validates the generated GeoJSON, summary JSON and HTML review artifacts. - Added readiness syntax coverage for the smoke script.
- Updated
scripts/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint138_calibration_evidence_bundle_smoke.py.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint138_calibration_evidence_bundle_smoke.py -qfailed whilescripts/smoke_detection_calibration_evidence_bundle.shwas absent. python -m pytest backend\tests\test_sprint138_calibration_evidence_bundle_smoke.py -q(1 passed)python -m pytest backend\tests\test_sprint138_calibration_evidence_bundle_smoke.py backend\tests\test_sprint137_browser_calibration_summary_evidence_script.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py -q(3 passed)bash -n scripts/smoke_detection_calibration_evidence_bundle.shbash scripts/smoke_detection_calibration_evidence_bundle.sh --helppython -m compileall backend/appbash scripts/run_readiness_check.sh(417 passed; frontend typecheck/build passed; Alembic head202606120900; shell syntax gates passed)- Pushed commit
47d3587tomain. - Tower repo fast-forwarded to
47d3587;bash -n scripts/smoke_detection_calibration_evidence_bundle.shpassed on Tower. - Tower operator smoke passed:
bash scripts/smoke_detection_calibration_evidence_bundle.shwrote mocked evidence artifacts under/mnt/user/appdata/geointel/artifacts/detection-calibration-smoke/20260708T115724Z/evidencewith 4 evidence features across matched candidate, matched reference, false positive and false negative roles. - Tower runtime remained healthy on
0.0.0.0:1202->80/tcp; no app rebuild was required because this pass changed operator scripts/docs/tests only.
Open:
- None for this pass.
Limitations:
- This is local/operator evidence tooling only. It does not call live production data, mutate application data, add backend endpoints, change migrations, rerun inference, create QA metrics, promote thresholds, download models, add provider fetching or change frontend runtime behavior.
- The smoke uses mocked canonical evidence responses by design; real persisted QA evidence is still validated by running
export_detection_calibration_evidence.shagainst a live browser or sweep summary.
Next recommended pass:
- Add a real multi-AOI calibration evidence capture convention: one folder per AOI/model/threshold matrix with browser summary, evidence bundle and operator notes, so model promotion decisions are based on comparable persisted artifacts rather than isolated runs.
Sprint 137 Browser calibration summary evidence bundle handoff (2026-07-08)
Changed:
- Extended
scripts/export_detection_calibration_evidence.shso it can consume Detection Labdetection-calibration-summary.jsonbrowser exports as well as the existing operatorcalibration_summary.jsonformat. - Added summary normalization for browser-exported
rows, rootproject_id, persistedquality_check_idvalues andCALIBRATION_EVIDENCE_MODE=bestfallback selection. - Updated
scripts/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint137_browser_calibration_summary_evidence_script.py.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint137_browser_calibration_summary_evidence_script.py -qfailed while browser summary support was absent. python -m pytest backend\tests\test_sprint137_browser_calibration_summary_evidence_script.py backend\tests\test_sprint136_calibration_summary_export_ui.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py -q(3 passed)bash -n scripts/export_detection_calibration_evidence.shpython -m compileall backend/appbash scripts/run_readiness_check.sh(416 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy from commit
673f6c6completed withGEOINTEL_INSTALL_AI=true; the all-in-one container is healthy and published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 4; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon after one readiness retry.
- Live container check passed:
docker ps --filter name=geointelreportedgeointelas healthy on0.0.0.0:1202->80/tcp. - Live YOLO preflight passed with local model configured, dependencies available,
torch_version=2.12.1,ultralytics_version=8.4.90,will_download_models=false,will_run_inference=falseandstatus=manifest_unavailablebecause no tile manifest was supplied.
Open:
- None for this pass.
Limitations:
- This is operator evidence tooling only. It does not add backend endpoints, change migrations, rerun inference, create new QA metrics, promote thresholds, mutate model configuration, download models, add provider fetching or change frontend runtime behavior.
Next recommended pass:
- Add a tiny local fixture smoke for the evidence bundle script that uses a saved browser-style summary plus mocked canonical evidence responses, so the bundle renderer itself is tested beyond static contract checks.
Sprint 136 Guided calibration summary export (2026-07-08)
Changed:
- Added a
Download calibration summaryaction to the guided Detection Lab calibration progress table. - The client-side JSON export includes calibration thresholds, persisted
analysis_run_id,job_id,quality_check_id, metric values and QA evidence GeoJSON URLs. - Added compact action-row styling and regression coverage in
backend/tests/test_sprint136_calibration_summary_export_ui.py. - Updated
CHANGELOG.mdanddocs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint136_calibration_summary_export_ui.py -qfailed while the summary export helpers and button were absent. python -m pytest backend\tests\test_sprint136_calibration_summary_export_ui.py backend\tests\test_sprint135_calibration_evidence_handoff.py backend\tests\test_sprint134_guided_detection_calibration_runner.py -q(3 passed)python -m compileall backend/appcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(415 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy from commit
8089df3completed withGEOINTEL_INSTALL_AI=true; the all-in-one container is published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live bundle check passed:
Download calibration summaryis present inassets/index-5CClxMR_.js. - Live YOLO preflight passed with local model configured, dependencies available,
will_download_models=false,will_run_inference=falseandstatus=manifest_unavailablebecause no tile manifest was supplied.
Open:
- None for this pass.
Limitations:
- This is a browser-side summary export only. It does not create server-side export records, rerun inference, create new QA metrics, promote thresholds, mutate model configuration, download models, add provider fetching or change API/database contracts.
Next recommended pass:
- Add a small import/consume path for downloaded calibration summaries in the existing operator evidence bundle script, so browser-exported summary JSON can be used directly from an operator workstation.
Sprint 135 Calibration evidence handoff (2026-07-08)
Changed:
- Added an
Open evidence mapaction to successful guided detection calibration rows. - Wired the Detection Lab action to the existing
openQualityEvidenceOnMapflow, which loads persisted QA/QC evidence GeoJSON and opens the Map workspace overlay. - Added compact table action styling and regression coverage in
backend/tests/test_sprint135_calibration_evidence_handoff.py. - Updated
CHANGELOG.mdanddocs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint135_calibration_evidence_handoff.py -qfailed while the Detection Lab evidence handoff prop was absent. python -m pytest backend\tests\test_sprint135_calibration_evidence_handoff.py backend\tests\test_sprint134_guided_detection_calibration_runner.py backend\tests\test_sprint133_detection_threshold_calibration_ux.py backend\tests\test_sprint112_qa_evidence_overlay.py -q(7 passed)python -m compileall backend/appcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(414 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy from commit
0c826efcompleted withGEOINTEL_INSTALL_AI=true; the all-in-one container is published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
Open:
- None for this pass.
Limitations:
- This pass adds review handoff only. It does not create new QA metrics, promote thresholds, mutate model configuration, download models, add provider fetching or change API/database contracts.
Next recommended pass:
- Add an operator-facing calibration evidence summary/export shortcut once the map handoff has been used on real AOI runs.
Sprint 134 External remote-sensing YOLO candidate benchmark (2026-07-07)
Changed:
- Added no production code and no repository-stored model weights.
- Evaluated the Hugging Face
agademer/yolo-remote-sensing-photovoltaicmodel card as a candidate because it explicitly targets remote-sensing imagery and includesbuildingas a class. - Downloaded the YOLOv8l detection checkpoint manually as an operator/runtime asset:
- source model:
agademer/yolo-remote-sensing-photovoltaic - source file:
yolo-remote-sensing-photovoltaic-v8l-solar-farms-and-cities-v20260331-detect-1000_epochs.pt - runtime file:
/app/models/yolo-remote-sensing-photovoltaic-v8l-detect-1000.pt - catalog asset:
yolo-remote-sensing-photovoltaic-v8l-detect-1000-pt - SHA256:
242ff4ab889569278f0eb9fcd22eb2c4bf2a52e48d05d89cc7cfa7941165d203
- source model:
- Updated
scripts/README.md,docs/TODO.md,docs/CODEX_EXECUTION_LOG.mdandCHANGELOG.mdwith benchmark evidence and the decision not to promote this model.
Tested:
- Live API preflight passed for
yolo-remote-sensing-photovoltaic-v8l-detect-1000-ptwithstatus=ready,model_load_ok=true,manifest_valid=true,tile_paths_exist=true,will_download_models=falseandwill_run_inference=false. - Live 45-run multi-sample QA matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/remote-sensing-v8l1000-live/multi_sample_quality_summary.json - command compared
yolo-remote-sensing-photovoltaic-v8l-detect-1000-pt,geointel-building-yolov8n-expanded160e50-ptandgeointel-building-yolov8n-hardneg160r8e40-ptover Geel, Mol, Turnhout, Retie and Kasterlee-bos with tile640, overlap64, thresholds0.25/0.15/0.05. - dense-sample results for the external candidate:
- Geel: best F1
0.0 - Mol: best F1
0.010582010582010581 - Turnhout: best F1
0.019070321811680575 - Retie: best F1
0.0
- Geel: best F1
- Kasterlee-bos sparse result: best F1
0.25with 1 detection, 1 match and 0 false positives at thresholds0.25/0.15. - dense-sample winner remained
geointel-building-yolov8n-expanded160e50-pt.
- output:
- Live 27-run hard-negative matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/remote-sensing-v8l1000-live/hard_negative_matrix_summary.json - Postel-bos: external candidate produced 0/1/3 detections at thresholds
0.25/0.15/0.05. - Lommel-heide: external candidate produced 0/0/0 detections.
- Kasterlee-bos: external candidate produced 1/2/5 detections, cleaner than expanded160e50 and hardneg160r8e40 on that sparse AOI.
- output:
Open:
- None for this benchmark pass.
Limitations:
- The external model is very conservative on the current Kempen orthophoto/GRB benchmark and misses most dense buildings.
- It may be useful as evidence for a high-precision/sparse-review mode, but it is not a viable V1 default extraction model.
- The runtime
.ptremains outside Git and must be managed as an operator asset.
Next recommended pass:
- Train a higher-capacity local detector from a stronger base model using the existing operator tile dataset, then gate it with both dense QA and hard-negative matrices before any model default changes.
Sprint 133 Hard-negative-balanced YOLO candidate (2026-07-07)
Changed:
- Hardened
scripts/export_operator_yolo_tile_dataset.pywith deterministic train-only background-negative repetition through--background-negative-repeatandOPERATOR_YOLO_BACKGROUND_NEGATIVE_REPEAT. - Background-negative repetition applies only when
is_negative=true,sample_role=background_candidateandsplit=train; validation tiles, positive tiles and normal reference samples are not duplicated. - Added tile-level provenance fields
sample_role,repeat_indexandis_repeated_background_negative. - Added regression coverage in
backend/tests/test_sprint130_operator_yolo_tile_dataset.py. - Updated
scripts/README.md,docs/TODO.md,docs/CODEX_EXECUTION_LOG.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py -qfailed before--background-negative-repeatandbackground_negative_repeat_countexisted. python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py -qpassed.python -m py_compile scripts\export_operator_yolo_tile_dataset.pypassed.python scripts\export_operator_yolo_tile_dataset.py --helppassed.- Live Tower hard-negative-balanced tile export passed:
- dataset:
/app/storage/operator-data/yolo-building-tile-hardneg160r8 - source samples: 10
- tile size:
160 - stride:
80 - negative keep ratio:
1.0 - background negative repeat:
8 - exported tiles:
864 - positive tiles:
260 - negative tiles:
604 - labels:
11213 - train tiles:
756 - validation tiles:
108
- dataset:
- Live Tower 40-epoch CPU training passed:
- output model:
/app/models/geointel-building-yolov8n-hardneg160r8e40.pt - catalog asset:
geointel-building-yolov8n-hardneg160r8e40-pt - SHA256:
7a77bd9f68e4c3927ffc8a8cd978a81067b02f42cffe77ada5334b5f8dbb6b50 - final validation: precision
0.403, recall0.378, mAP500.301, mAP50-950.0944
- output model:
- Live API preflight passed for
geointel-building-yolov8n-hardneg160r8e40-ptwithstatus=ready,model_load_ok=true,manifest_valid=true,tile_paths_exist=true,will_download_models=falseandwill_run_inference=false. - Live 60-run multi-sample QA matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/hardneg160r8e40-live/multi_sample_quality_summary.json - command compared
geointel-building-yolov8n-hardneg160r8e40-pt,geointel-building-yolov8n-expanded160e50-pt,geointel-building-yolov8n-tile30-ptandyolov8s-building-segmentation-ptover Geel, Mol, Turnhout, Retie and Kasterlee-bos with tile640, overlap64, thresholds0.25/0.15/0.05. - best overall score and recall remained Geel with
geointel-building-yolov8n-expanded160e50-pt, precision0.30333333333333334, recall0.14748784440842788, F10.1984732824427481. - hardneg160r8e40 dense F1 lagged expanded160e50 on Geel (
0.14394765539803708vs0.1984732824427481), Mol (0.11572700296735906vs0.1651651651651652), Turnhout (0.14911463187325258vs0.1938490214352283) and Retie (0.10538116591928251vs0.1569506726457399).
- output:
- Live 36-run hard-negative matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/hardneg160r8e40-live/hard_negative_matrix_summary.json - Postel-bos: hardneg160r8e40 produced 0/0/0 detections at thresholds
0.25/0.15/0.05; expanded160e50 produced 0/0/1. - Lommel-heide: hardneg160r8e40 produced 0/0/0 detections; expanded160e50 produced 0/0/10.
- Kasterlee-bos: hardneg160r8e40 produced 5/9/25 detections; expanded160e50 produced 38/46/76.
- output:
Open:
- None for the hard-negative-balanced tile export contract itself.
Limitations:
geointel-building-yolov8n-hardneg160r8e40-ptreduced false-positive pressure but regressed dense-AOI recall/F1. It should not become the V1 default.- This remains operator tooling only. It does not add Training Studio, browser training controls, provider fetching, fake detections, model auto-provisioning or API contract changes.
Next recommended pass:
- Train or import a materially stronger aerial/Kempen building model candidate, then benchmark it against the same dense QA and hard-negative matrices before changing default model selection.
Sprint 132 Operator hard-negative detection matrix (2026-07-07)
Changed:
- Added
scripts/run_operator_hard_negative_detection_matrix.sh. - The script reads
operator_samples_manifest.json, selects samples markedbackground_candidateorallow_empty_reference, uploads only the raster, generates a tile manifest, checks configured-YOLO preflight, runsPOST /api/v1/detection/runand counts persisted detections. - It intentionally does not upload reference vectors and does not call detection QA/QC endpoints, because background AOIs have no meaningful reference target.
- Added readiness shell-syntax coverage for the new script.
- Added regression coverage in
backend/tests/test_sprint132_operator_hard_negative_matrix.py. - Updated
scripts/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint132_operator_hard_negative_matrix.py -qfailed whilescripts/run_operator_hard_negative_detection_matrix.shdid not exist. python -m pytest backend\tests\test_sprint132_operator_hard_negative_matrix.py -qpassed.bash -n scripts/run_operator_hard_negative_detection_matrix.shpassed.- Live Tower 27-run hard-negative matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/expanded160e50-live/hard_negative_matrix_summary.json - samples: Postel-bos, Lommel-heide and Kasterlee-bos
- models:
geointel-building-yolov8n-expanded160e50-pt,geointel-building-yolov8n-tile30-pt,yolov8s-building-segmentation-pt - tile size:
640 - overlap:
64 - thresholds:
0.25,0.15,0.05
- output:
- Live false-positive pressure results:
- Postel-bos: expanded160e50 produced 0 detections at
0.25/0.15, 1 at0.05; tile30 produced 0/0/1; yolov8s produced 0/3/6. - Lommel-heide: expanded160e50 produced 0 detections at
0.25/0.15, 10 at0.05; tile30 produced 0/0/3; yolov8s produced 0/0/0. - Kasterlee-bos: expanded160e50 produced 38/46/76 detections at
0.25/0.15/0.05; tile30 produced 15/22/42; yolov8s produced 5/6/7.
- Postel-bos: expanded160e50 produced 0 detections at
Open:
- None for the hard-negative matrix tooling itself.
Limitations:
- Background matrix scores false-positive pressure from detection counts only. It does not calculate precision/recall/F1 because background candidates intentionally do not provide a full reference target.
- Kasterlee-bos still has 7 GRB features and is best interpreted as a sparse/hard-negative AOI, not a purely empty background tile.
geointel-building-yolov8n-expanded160e50-ptshould not be promoted to default model while Kasterlee-bos false-positive pressure remains high.
Next recommended pass:
- Train a hard-negative-balanced candidate: oversample sparse/background tiles, lower the dense-AOI max-detection bias, and rerun both dense QA matrix and hard-negative matrix before changing any default model selection.
Sprint 131 Operator sample expansion and negative-tile YOLO candidate (2026-07-07)
Changed:
- Extended
scripts/prepare_operator_real_data_samples.pywithsample_roleandallow_empty_reference. - Added reference AOIs for Herentals, Balen, Retie and Westerlo.
- Added background-candidate AOIs for Postel-bos, Lommel-heide and Kasterlee-bos. Background candidates can persist empty GRB FeatureCollections for negative-tile training, while normal reference samples still fail on empty GRB results.
- Added regression coverage in
backend/tests/test_sprint131_operator_sample_expansion.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint131_operator_sample_expansion.py -qfailed before the new sample metadata and background candidates existed. python -m pytest backend\tests\test_sprint131_operator_sample_expansion.py -qpassed.python -m py_compile scripts\prepare_operator_real_data_samples.pypassed.python scripts\prepare_operator_real_data_samples.py --helppassed.- Live Tower operator sample preparation passed:
- manifest:
/app/storage/operator-data/operator_samples_manifest.json - samples: Geel
617, Mol374, Turnhout773, Herentals665, Balen309, Retie592, Westerlo334, Postel-bos0, Lommel-heide0, Kasterlee-bos7reference features.
- manifest:
- Live Tower expanded tile export passed:
- dataset:
/app/storage/operator-data/yolo-building-tile-expanded160 - tile size:
160 - stride:
80 - exported tiles:
360 - positive tiles:
260 - negative tiles:
100 - labels:
11213 - train tiles:
252 - validation tiles:
108
- dataset:
- Live Tower 50-epoch CPU training passed:
- output model:
/app/models/geointel-building-yolov8n-expanded160e50.pt - catalog asset:
geointel-building-yolov8n-expanded160e50-pt - SHA256:
bf6a5e8d25a62d784ee53764ea11d7ce89c4e7aeeac7588010e497b8d7dafb2b - final validation: precision
0.428, recall0.389, mAP500.318, mAP50-950.106
- output model:
- Live API preflight passed for
geointel-building-yolov8n-expanded160e50-ptwithstatus=ready,model_load_ok=true,manifest_valid=true,tile_paths_exist=true,will_download_models=falseandwill_run_inference=false. - Live 45-run multi-sample QA matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/expanded160e50-live/multi_sample_quality_summary.json - command compared
geointel-building-yolov8n-expanded160e50-pt,geointel-building-yolov8n-tile30-ptandyolov8s-building-segmentation-ptover Geel, Mol, Turnhout, Retie and Kasterlee-bos with tile640, overlap64, thresholds0.25/0.15/0.05. - best overall score and recall: Geel,
geointel-building-yolov8n-expanded160e50-pt, tile640, threshold0.05, 300 detections, 91 matches, 209 false positives, 526 false negatives, precision0.30333333333333334, recall0.14748784440842788, F10.1984732824427481. - dense-sample score winners: Geel, Mol, Turnhout and Retie all selected
geointel-building-yolov8n-expanded160e50-pt. - hard-negative/sparse-sample winner: Kasterlee-bos selected
yolov8s-building-segmentation-pt, threshold0.25, F10.16666666666666666; the expanded local model produced too many false positives there.
- output:
Open:
- None for the sample-preparation and expanded-training runtime proof itself.
Limitations:
- This remains operator tooling only. It does not add Training Studio, browser training controls, provider fetching, fake detections, model auto-provisioning or API contract changes.
geointel-building-yolov8n-expanded160e50-ptis the best tested candidate on dense operator AOIs, but it is still experimental and should not become the V1 default until hard-negative false positives improve.- The next model pass should add more sparse/background AOIs, tune confidence/NMS/max-detection settings and compare a stronger architecture or longer run against the same persisted QA matrix.
Next recommended pass:
- Build a hard-negative model-quality pass: expand sparse/background AOIs, export a balanced tile dataset, train a stronger candidate, and rerun the multi-sample QA matrix with dense and background samples scored separately.
Sprint 130 Operator YOLO tile-level dataset tooling (2026-07-07)
Changed:
- Added
scripts/export_operator_yolo_tile_dataset.py. - The exporter reads
operator_samples_manifest.json, opens each raster/reference pair, creates overlapping tile windows, clips GRB building bounding boxes into tile-local YOLO labels, writesdataset.yaml, and reportsyolo_tile_dataset_summary.json. - Added deterministic negative tile retention through
negative_keep_ratio. - Added readiness compile coverage for the tile exporter.
- Added regression coverage in
backend/tests/test_sprint130_operator_yolo_tile_dataset.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py -qfailed whilescripts/export_operator_yolo_tile_dataset.pydid not exist. python -m pytest backend\tests\test_sprint130_operator_yolo_tile_dataset.py -qpassed.python scripts\export_operator_yolo_tile_dataset.py --helppassed without requiring local GIS dependencies.python -m py_compile scripts\export_operator_yolo_tile_dataset.pypassed.- Live Tower tile export passed:
- dataset:
/app/storage/operator-data/yolo-building-tile-dataset - samples: Geel, Mol and Turnhout
- tile size:
192 - stride:
96 - exported tiles:
75 - positive tiles:
75 - labels:
5321 - validation split: Turnhout
- dataset:
- Live Tower 30-epoch CPU tile training passed:
- output model:
/app/models/geointel-building-yolov8n-tile30.pt - catalog asset:
geointel-building-yolov8n-tile30-pt - SHA256:
b9e228202500d7c85836d12a72e320f4f2f0cef24cbb1b5bf7fa78a6778390af - final validation: precision
0.208, recall0.271, mAP500.122, mAP50-950.0308
- output model:
- Live API preflight passed for
geointel-building-yolov8n-tile30-ptwithstatus=ready,model_load_ok=true,manifest_valid=true,tile_paths_exist=true,will_download_models=falseandwill_run_inference=false. - Live 48-run multi-sample QA matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T190720Z/multi_sample_quality_summary.json - command compared
geointel-building-yolov8n-tile30-ptwithyolov8s-building-segmentation-ptover Geel, Mol and Turnhout, tile sizes512/640, overlap64, thresholds0.50/0.25/0.15/0.05. - best overall score: Mol,
geointel-building-yolov8n-tile30-pt, tile640, threshold0.15, 272 detections, 37 matches, 235 false positives, 337 false negatives, precision0.13602941176470587, recall0.09893048128342247, F10.11455108359133127. - best overall recall: Mol,
geointel-building-yolov8n-tile30-pt, tile512, threshold0.05, 544 detections, 44 matches, 500 false positives, 330 false negatives, precision0.08088235294117647, recall0.11764705882352941, F10.09586056644880174. - best overall precision: Turnhout,
yolov8s-building-segmentation-pt, tile640, threshold0.25, precision0.4, recall0.01034928848641656, F10.0201765447667087. - per-sample score winners: Geel
geointel-building-yolov8n-tile30-ptF10.09671179883945842; Molgeointel-building-yolov8n-tile30-ptF10.11455108359133127; Turnhoutyolov8s-building-segmentation-ptF10.09971777986829727.
- output:
Open:
- None for the tile exporter/training runtime proof itself.
Limitations:
- This remains operator tooling only. It does not add Training Studio, browser training controls, provider fetching, fake detections, model auto-provisioning or API contract changes.
geointel-building-yolov8n-tile30-ptis an experimental local candidate, not a V1 default. It improves the operator-trained baseline materially but still has low recall and many false positives on the current 3-sample corpus.- The current corpus is too small and all exported tiles were positive; the next model pass needs more AOIs and deliberate negative/background tiles.
Next recommended pass:
- Expand the operator sample corpus beyond Geel/Mol/Turnhout, include negative/background AOIs, regenerate the tile dataset, then train a longer/larger local model candidate and rerun the same persisted QA matrix.
Sprint 129 Operator YOLO training dataset tooling (2026-07-07)
Changed:
- Added
scripts/export_operator_yolo_dataset.pyto export prepared operator samples into a local YOLO detection dataset:- input manifest:
operator_samples_manifest.json - output:
dataset.yaml,images/train,labels/train,images/val,labels/val,yolo_dataset_summary.json - labels are derived from GRB building references with
source_name=grbandreference_layer_name=buildings.
- input manifest:
- Added
scripts/train_operator_yolo_detector.shas an explicit operator/runtime wrapper around a local Ultralytics training smoke:- requires
OPERATOR_YOLO_DATASET_DIR - requires an existing
YOLO_BASE_MODEL_PATH - writes a local
TRAIN_MODEL_OUTPUT_PATH - uses
PYTHON_BIN=python3by default for the all-in-one container - writes
training_summary.json.
- requires
- Added readiness coverage for exporter compile and train-wrapper shell syntax.
- Added regression coverage in
backend/tests/test_sprint129_operator_yolo_training_dataset.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint129_operator_yolo_training_dataset.py -qfailed while the exporter and training wrapper contracts were incomplete. python -m pytest backend\tests\test_sprint129_operator_yolo_training_dataset.py -qpassed.python scripts\export_operator_yolo_dataset.py --helppassed without requiring local GIS dependencies.python -m py_compile scripts\export_operator_yolo_dataset.pypassed.bash -n scripts/train_operator_yolo_detector.shpassed.- Live Tower export passed:
/app/storage/operator-data/yolo-building-datasetcontains 3 images and 1427 labels from the current Geel/Mol/Turnhout samples. - Live Tower training smoke passed with the existing
/app/models/yolov8n.ptbase model and wrote/app/models/geointel-building-yolov8n-smoke.pt. - The first live smoke showed Ultralytics fetching an auxiliary plot font. The wrapper now sets
plots=Falseand seedsArial.ttffrom an existing local system font before importing Ultralytics so the operator smoke path does not invoke plot/font network behavior. - Full local readiness passed after the final wrapper hardening:
bash scripts/run_readiness_check.shran 396 backend tests, frontend typecheck/build, Alembic head and smoke syntax checks. - Pushed commits through
3936768to Gitea and reset Tower/mnt/user/appdata/geointelto the same commit. - Live Tower no-font smoke passed after deleting
/app/storage/ultralytics/Ultralytics/Arial.ttf; the wrapper seeded the font locally and the 1-epoch run completed without the previous font fetch line. - Live Tower final 8-epoch training smoke passed:
- output model:
/app/models/geointel-building-yolov8n-operator8.pt - catalog asset:
geointel-building-yolov8n-operator8-pt - SHA256:
071d64c89a8fd28f915f7a5a553e2d164942721292693a1612c725284c6e2e1e - training summary:
/app/storage/training/operator-yolo/geointel-building-yolov8n-operator8/training_summary.json.
- output model:
- Live API preflight passed for
geointel-building-yolov8n-operator8-ptwithstatus=ready,model_load_ok=true,manifest_valid=true,tile_paths_exist=true,will_download_models=falseandwill_run_inference=false. - Live 36-run multi-sample QA matrix completed:
- command compared
geointel-building-yolov8n-operator8-ptwithyolov8s-building-segmentation-ptover Geel, Mol and Turnhout, tile sizes512/640, thresholds0.50/0.25/0.15. - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T033048Z/multi_sample_quality_summary.json. geointel-building-yolov8n-operator8-ptproduced zero detections for every sample/tile combination at thresholds0.15through0.50.- best overall remained
yolov8s-building-segmentation-pton Mol, tile640, threshold0.15: 55 detections, 9 matches, 46 false positives, 365 false negatives, precision0.16363636363636364, recall0.02406417112299465, F10.04195804195804196.
- command compared
- Live low-threshold operator8 matrix completed:
- output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T033230Z/multi_sample_quality_summary.json. - at threshold
0.05, operator8 still produced zero detections on all samples. - at threshold
0.01, operator8 produced many false positives and almost no matches; best case was Turnhout tile512with 280 detections, 2 matches, 278 false positives, precision0.007142857142857143, recall0.00258732212160414, F10.003798670465337132.
- output:
Open:
- None for the operator training/export tooling itself.
Limitations:
- This is operator tooling only. It does not add Training Studio, browser training controls, provider fetching, fake detections, model auto-provisioning or API contract changes.
- The 3-sample/8-epoch operator model is not production-useful and should not be activated as the default building detector.
Next recommended pass:
- Improve the training dataset before more model work: generate tile-level YOLO labels with enough positive/negative tiles, add more AOIs, then train a longer local model and rerun the same persisted QA matrix.
Sprint 128 Stronger building model runtime benchmark (2026-07-07)
Changed:
- Added
keremberke/yolov8s-building-segmentationas an explicit runtime model asset on Tower:- path:
/mnt/user/appdata/geointel/models/yolov8s-building-segmentation.pt - source:
https://huggingface.co/keremberke/yolov8s-building-segmentation/resolve/main/best.pt - SHA256:
a27af31654c6a4edbdc85581c33d93c13986b5919de7de410f8d85d801b3bb34
- path:
- Did not commit model weights to Git and did not add app-side model download behavior.
- Ran a stronger-candidate multi-sample matrix comparing:
yolov8n-building-segmentation-ptyolov8s-building-segmentation-pt- samples: Geel, Mol, Turnhout
- tile sizes:
512,640 - overlap:
64 - thresholds:
0.50,0.25,0.15
Tested:
- Hugging Face API metadata check showed
keremberke/yolov8s-building-segmentationis public, uses the Ultralytics library, exposesbest.pt, and reports validation mAP@0.5 values for thekeremberke/satellite-building-segmentationdataset. - Live model asset catalog reported
yolov8s-building-segmentation-pt,size_bytes=23814274,will_download_models=false, SHA256a27af31654c6a4edbdc85581c33d93c13986b5919de7de410f8d85d801b3bb34. - Live preflight passed with
model_asset_id=yolov8s-building-segmentation-pt,check_model_load=true,model_file_exists=true,model_load_ok=true,will_download_models=falseandwill_run_inference=false. - Tower 36-run matrix passed:
- command:
OPERATOR_SAMPLE_MANIFEST_PATH=storage/operator-data/operator_samples_manifest.json QUALITY_MODEL_ASSET_IDS="yolov8n-building-segmentation-pt yolov8s-building-segmentation-pt" QUALITY_TILE_SIZES="512 640" QUALITY_TILE_OVERLAPS="64" QUALITY_THRESHOLDS="0.50 0.25 0.15" bash scripts/run_multi_sample_detection_quality_matrix.sh http://192.168.10.150:1202 - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/multi_sample_quality_summary.json - best overall score: Mol,
yolov8s-building-segmentation-pt, tile640, threshold0.15, 55 detections, 9 matches, 46 false positives, 365 false negatives, precision0.16363636363636364, recall0.02406417112299465, F10.04195804195804196. - best overall recall: Mol,
yolov8s-building-segmentation-pt, tile512, threshold0.15, 77 detections, 9 matches, 68 false positives, 365 false negatives, precision0.11688311688311688, recall0.02406417112299465, F10.03991130820399113. - best overall precision: Turnhout,
yolov8s-building-segmentation-pt, tile640, threshold0.25, 20 detections, 8 matches, 12 false positives, 765 false negatives, precision0.4, recall0.01034928848641656, F10.0201765447667087. - best Geel score:
yolov8s-building-segmentation-pt, tile640, threshold0.15, F10.0187207488299532. - best Mol score:
yolov8s-building-segmentation-pt, tile640, threshold0.15, F10.04195804195804196. - best Turnhout score remained
yolov8n-building-segmentation-pt, tile512, threshold0.15, F10.03934426229508197.
- command:
- Best-score evidence export passed for every sample in the new matrix:
- Geel evidence:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/geel/calibration_evidence_review.html, 641 features, 611 false negatives, 18 false positives, 6 matched detections and 6 matched references. - Mol evidence:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/mol/calibration_evidence_review.html, 429 features, 365 false negatives, 46 false positives, 9 matched detections and 9 matched references. - Turnhout evidence:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025932Z/turnhout/calibration_evidence_review.html, 915 features, 755 false negatives, 124 false positives, 18 matched detections and 18 matched references.
- Geel evidence:
Open:
- None for adding and benchmarking the
yolov8scandidate.
Limitations:
yolov8simproves precision and F1 on Geel/Mol but still misses most reference buildings. Best recall is about 2.4%, which is not sufficient for a usable V1 building extraction default.- The model is a runtime artifact and remains outside Git.
Next recommended pass:
- Source or train a materially stronger aerial-building model. The GeoIntel pipeline is now good enough to benchmark candidates quickly, but the current public YOLO building-segmentation candidates are still too weak for the target Flemish orthophoto/GRB workflow.
Sprint 127 Multi-sample detection quality calibration tooling (2026-07-07)
Changed:
- Added
scripts/prepare_operator_real_data_samples.pyas an explicit operator/runtime helper for documented Geel, Mol and Turnhout real-data samples. - The helper downloads small Digitaal Vlaanderen OMWRGBMRVL WMS
OrthoGeoTIFFs and GRB OGC API FeaturesGBGbuilding GeoJSON references for the documented AOIs only. - The helper writes
operator_samples_manifest.json, sample metadata, source URLs and attribution under the runtime operator-data directory and reuses existing files by default. - Added
scripts/run_multi_sample_detection_quality_matrix.shto runscripts/run_detection_quality_matrix.shonce per manifest sample. - The multi-sample wrapper combines per-sample
quality_matrix_summary.jsonfiles intomulti_sample_quality_summary.jsonwithbest_overall_by_score,best_overall_by_recall,best_overall_by_precisionandbest_by_sample. - Added readiness checks for Python compile and shell syntax.
- Added regression coverage in
backend/tests/test_sprint127_operator_sample_quality_matrix.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py -qfailed because the sample-preparation and multi-sample scripts did not exist. - RED:
python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py::test_prepare_operator_real_data_samples_help_does_not_require_gis_dependencies -qfailed because--helprequired missing GIS dependencies. python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py -qpassed.python scripts\prepare_operator_real_data_samples.py --helppassed without requiring local GIS dependencies.python -m py_compile scripts\prepare_operator_real_data_samples.pypassed.bash -n scripts/run_multi_sample_detection_quality_matrix.shpassed.python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py backend\tests\test_sprint126_detection_quality_matrix.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py backend\tests\test_sprint124_detection_calibration_sweep.py -qpassed.python scripts\smoke_docs.pypassed.git diff --checkpassed.bash scripts/run_readiness_check.shpassed: 393 backend tests, frontend typecheck/build, Alembic head202606120900, live smoke syntax checks and the new sample/multi-sample checks.- Pushed commit
06dfc5fto Gitea and fast-forwarded Tower/mnt/user/appdata/geointelto the same commit. - Tower sample preparation passed by running the new helper in the live
geointelall-in-one container through stdin:- Geel reused existing runtime files: 617 GRB GBG reference features.
- Mol was newly prepared: 374 GRB GBG reference features.
- Turnhout was newly prepared: 773 GRB GBG reference features.
- Manifest:
/mnt/user/appdata/geointel/storage/operator-data/operator_samples_manifest.json.
- Tower multi-sample quality matrix passed:
- command:
OPERATOR_SAMPLE_MANIFEST_PATH=storage/operator-data/operator_samples_manifest.json QUALITY_MODEL_ASSET_IDS="yolov8n-building-segmentation-pt yolov8n-pt" QUALITY_TILE_SIZES="512 640" QUALITY_TILE_OVERLAPS="64" QUALITY_THRESHOLDS="0.50 0.15" bash scripts/run_multi_sample_detection_quality_matrix.sh http://192.168.10.150:1202 - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025303Z/multi_sample_quality_summary.json - run count: 24 real persisted workflows across 3 samples.
- best overall score/recall: Turnhout,
yolov8n-building-segmentation-pt, tile512, overlap64, threshold0.15, 142 detections, 18 matches, 124 false positives, 755 false negatives, precision0.1267605633802817, recall0.02328589909443726, F10.03934426229508197. - best overall precision: Geel,
yolov8n-building-segmentation-pt, tile640, overlap64, threshold0.50, 4 detections, 1 match, 3 false positives, 616 false negatives, precision0.25, recall0.0016207455429497568, F10.0032206119162640897. - best Geel score: tile
512, threshold0.15, 80 detections, 6 matches, 74 false positives, 611 false negatives, F10.017216642754662843. - best Mol score: tile
640, threshold0.15, 77 detections, 7 matches, 70 false positives, 367 false negatives, F10.03104212860310421. - best Turnhout score: tile
512, threshold0.15, 142 detections, 18 matches, 124 false positives, 755 false negatives, F10.03934426229508197. - generic
yolov8n-ptproduced zero building detections across every sample, tile size and threshold.
- command:
- Tower best-score evidence export passed for every sample:
- Geel:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025303Z/geel/calibration_evidence_review.html, 697 features, 611 false negatives, 74 false positives, 6 matched detections and 6 matched references. - Mol:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025303Z/mol/calibration_evidence_review.html, 451 features, 367 false negatives, 70 false positives, 7 matched detections and 7 matched references. - Turnhout:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/20260707T025303Z/turnhout/calibration_evidence_review.html, 915 features, 755 false negatives, 124 false positives, 18 matched detections and 18 matched references.
- Geel:
Open:
- None for multi-sample tooling.
Limitations:
- This is operator tooling only. It does not add a live GRB provider, live orthophoto provider, application endpoint, migration, frontend feature, model download or fixture inference path.
- The prepared sample files are runtime artifacts under appdata/storage and remain excluded from Git.
- The three-sample benchmark confirms the current building-segmentation evaluation model is not extraction-quality for V1: best recall is only about 2.3% and false negatives dominate every sample.
Next recommended pass:
- Replace or add a stronger aerial/building model candidate and rerun the same multi-sample matrix; optionally add IoU-threshold sweeps after a model produces materially better candidate detections.
Sprint 126 Detection quality matrix tooling (2026-07-07)
Changed:
- Added
scripts/run_detection_quality_matrix.shas an operator-facing model/tile/threshold matrix for the configured-YOLO real-data path. - The matrix reuses
scripts/verify_real_data_detection_qa_workflow.shfor each row so every result is backed by persisted Project, Dataset, AnalysisRun, Detection, QualityCheck, Metric and Export records. - The script accepts
QUALITY_MODEL_ASSET_IDS,QUALITY_TILE_SIZES,QUALITY_TILE_OVERLAPSandQUALITY_THRESHOLDS, writes per-run logs and producesquality_matrix_summary.json. - The summary reports model asset, tile size, overlap, confidence threshold, detection count, QA score, precision, recall, F1, mean IoU, matches, false positives and false negatives.
- Added
best_by_score,best_by_recallandbest_by_precisionrankings for operator model-quality decisions. - Added readiness syntax coverage and regression coverage in
backend/tests/test_sprint126_detection_quality_matrix.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- RED:
python -m pytest backend\tests\test_sprint126_detection_quality_matrix.py -qfailed becausescripts/run_detection_quality_matrix.shdid not exist. python -m pytest backend\tests\test_sprint126_detection_quality_matrix.py -qpassed.python -m pytest backend\tests\test_sprint126_detection_quality_matrix.py backend\tests\test_sprint124_detection_calibration_sweep.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py -qpassed.bash -n scripts/run_detection_quality_matrix.shpassed.bash scripts/run_detection_quality_matrix.sh --helppassed.python scripts\smoke_docs.pypassed.git diff --checkpassed.bash scripts/run_readiness_check.shpassed: 390 backend tests, frontend typecheck/build, Alembic head202606120900, live smoke syntax checks and the new matrix syntax check.- Pushed commit
e728f70to Gitea and fast-forwarded Tower/mnt/user/appdata/geointelto the same commit. - Tower live matrix passed against the Geel operator sample:
- command:
QUALITY_MODEL_ASSET_IDS="yolov8n-building-segmentation-pt yolov8n-pt" QUALITY_TILE_SIZES="512 640" QUALITY_TILE_OVERLAPS="64" QUALITY_THRESHOLDS="0.50 0.15" bash scripts/run_detection_quality_matrix.sh http://192.168.10.150:1202 - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/20260707T023000Z/quality_matrix_summary.json - run count: 8
- best by score and recall:
yolov8n-building-segmentation-pt, tile512, overlap64, threshold0.15, 80 detections, 6 matches, 74 false positives, 611 false negatives, precision0.075, recall0.009724473257698542, F10.017216642754662843. - best by precision:
yolov8n-building-segmentation-pt, tile640, overlap64, threshold0.50, 4 detections, 1 match, 3 false positives, 616 false negatives, precision0.25, recall0.0016207455429497568, F10.0032206119162640897. - generic
yolov8n-ptproduced zero building detections for all tested tile/threshold combinations.
- command:
- Tower best-run evidence export passed from the matrix summary:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/20260707T023000Z/calibration_evidence.geojson/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/20260707T023000Z/calibration_evidence_summary.json/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/20260707T023000Z/calibration_evidence_review.html- evidence features: 697 total, 611 false negatives, 74 false positives, 6 matched detections and 6 matched references.
Open:
- None for matrix tooling.
Limitations:
- This is operator benchmarking tooling only. It does not change inference behavior, add model downloads, seed fixture detections, fetch providers, change API contracts or change migrations.
- A single Geel sample is not enough to declare a production V1 building-extraction baseline; additional orthophoto/reference samples are still needed before picking defaults.
Next recommended pass:
- Add at least two more local orthophoto/reference samples and run the same quality matrix before choosing V1 defaults; the current Geel evidence says runtime plumbing works, but the active model is still not extraction-quality.
Sprint 125 Detection calibration evidence bundle (2026-07-07)
Changed:
- Added
scripts/export_detection_calibration_evidence.shto turn a persisted detection calibration summary into visual QA evidence artifacts. - The script reads
calibration_summary.json, fetches the existing project quality-check evidence GeoJSON endpoint for eachquality_check_id, enriches features with threshold/score/provenance and writes:calibration_evidence.geojsoncalibration_evidence_summary.jsoncalibration_evidence_review.html
- The HTML review artifact renders a simple SVG overview with distinct roles for
match_candidate,match_reference,false_positiveandfalse_negative. - Registered the script in
scripts/run_readiness_check.shas a syntax check. - Added regression coverage in
backend/tests/test_sprint125_detection_calibration_evidence_bundle.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Validation:
- RED:
python -m pytest backend/tests/test_sprint125_detection_calibration_evidence_bundle.py -qfailed becausescripts/export_detection_calibration_evidence.shdid not exist. python -m pytest backend/tests/test_sprint125_detection_calibration_evidence_bundle.py -qpassed.bash -n scripts/export_detection_calibration_evidence.shpassed.bash scripts/export_detection_calibration_evidence.sh --helppassed.- Missing-input guard printed usage and did not fetch evidence.
bash scripts/run_readiness_check.shpassed: 389 backend tests, Alembic head check, frontend typecheck/build and shell syntax checks.- Tower pulled commit
ea8dcb2withgit pull --ff-only origin main. - Tower evidence export passed against
/mnt/user/appdata/geointel/artifacts/detection-calibration/20260707T002103Z/calibration_summary.json. - Evidence artifacts written on Tower:
/mnt/user/appdata/geointel/artifacts/detection-calibration/20260707T002103Z/calibration_evidence.geojson/mnt/user/appdata/geointel/artifacts/detection-calibration/20260707T002103Z/calibration_evidence_summary.json/mnt/user/appdata/geointel/artifacts/detection-calibration/20260707T002103Z/calibration_evidence_review.html
- Evidence counts from the Geel calibration export:
- total evidence features: 2555
- false negatives: 2460
- false positives: 79
- matched detections: 8
- matched references: 8
- Copied
calibration_evidence_review.htmlandcalibration_evidence_summary.jsonto the local ignoredartifacts/detection-calibration/20260707T002103Z/directory for inspection. - Internal browser validation passed through a temporary local static server: the review page loaded with title
GeoIntel Detection Calibration Evidence, 1 SVG, 2555 SVG paths, 4 calibration table rows and 0 console errors.
Open:
- None for evidence export tooling.
Limitations:
- This is operator tooling only. It does not rerun inference, change API behavior, add UI behavior, fetch providers, seed demo data or download models.
- The SVG review is a lightweight geometry overview, not a replacement for full MapLibre evidence review in the workbench.
- The evidence distribution confirms the current active model misses most reference buildings on this sample. This points to model suitability and/or tiling strategy as the next bottleneck, not runtime plumbing.
Next recommended pass:
- Add a model-quality decision pass: compare the current evaluation model against another building/aerial model or adjusted tile/overlap settings on at least two additional local orthophoto/reference samples.
Sprint 124 Detection calibration sweep tooling (2026-07-07)
Changed:
- Added
scripts/run_detection_calibration_sweep.shas an operator-facing confidence-threshold sweep for the configured-YOLO real-data path. - The sweep reuses
scripts/verify_real_data_detection_qa_workflow.shonce per threshold, so each row is backed by persisted Project, Dataset, AnalysisRun, Detection, QualityCheck, Metric and export records. - The sweep fetches project
quality-checksafter each run and writes per-threshold summaries pluscalibration_summary.jsonwith detection count, QA score, precision, recall, F1, mean IoU, matches, false positives and false negatives. - Registered the sweep in
scripts/run_readiness_check.shas a syntax check. - Added regression coverage in
backend/tests/test_sprint124_detection_calibration_sweep.py. - Updated
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Validation:
- RED:
python -m pytest backend/tests/test_sprint124_detection_calibration_sweep.py -qfailed becausescripts/run_detection_calibration_sweep.shdid not exist. python -m pytest backend/tests/test_sprint124_detection_calibration_sweep.py -qpassed.bash -n scripts/run_detection_calibration_sweep.shpassed.bash scripts/run_detection_calibration_sweep.sh --helppassed.- Missing-input guard printed usage and did not start a live workflow.
bash scripts/run_readiness_check.shpassed: 388 backend tests, Alembic head check, frontend typecheck/build and shell syntax checks.- Tower pulled commit
590e597withgit pull --ff-only origin mainand ran the default Geel calibration sweep. - The first Tower sweep exposed that the summary script looked for
f1_scorewhile persisted metrics usef1; the script was patched with ametrics.get("f1")fallback and regression coverage. - RED:
python -m pytest backend/tests/test_sprint124_detection_calibration_sweep.py -qfailed while the script lacked thef1fallback. python -m pytest backend/tests/test_sprint124_detection_calibration_sweep.py -qpassed after the fallback.- Tower pulled commit
e8cd463and reran the Geel calibration sweep successfully:- output:
artifacts/detection-calibration/20260707T002103Z/calibration_summary.json - threshold
0.50: 4 detections, score/F10.0032206119162640897, precision0.25, recall0.0016207455429497568, 1 match, 3 false positives, 616 false negatives - threshold
0.35: 9 detections, score/F10.003194888178913738, precision0.1111111111111111, recall0.0016207455429497568, 1 match, 8 false positives, 616 false negatives - threshold
0.25: 20 detections, score/F10.0031397174254317113, precision0.05, recall0.0016207455429497568, 1 match, 19 false positives, 616 false negatives - threshold
0.15: 54 detections, score/F10.014903129657228018, precision0.09259259259259259, recall0.008103727714748784, 5 matches, 49 false positives, 612 false negatives - best by score for this sample: threshold
0.15
- output:
Open:
- None for calibration tooling.
Limitations:
- The sweep is intentionally mutating and creates one real workflow run per threshold.
- It is calibration tooling only; it does not change inference, add model downloads, fetch providers, seed demo detections or change API/UI behavior.
- The current active building model still performs poorly on the Geel validation sample. Threshold
0.15is best among the tested values, but recall remains under 1%; this is model/data-quality evidence, not a production-ready extraction baseline.
Next recommended pass:
- Inspect false-positive/false-negative evidence for the Geel runs, then add at least two more local orthophoto/reference samples before choosing V1 default confidence/IoU guidance.
Sprint 123 YOLO class and tile CRS normalization (2026-07-07)
Changed:
- Investigated the Geel real-data smoke that persisted zero detections despite the configured building model being available.
- Confirmed on Tower that
/app/models/yolov8n-building-segmentation.ptreports model classBuildingand returns 4 raw detections at confidence0.5on the same real Geel tile manifest. - Fixed configured-YOLO detection persistence so model class names are compared case-insensitively against
class_filter, persisted as canonical lowercase domain classes, and preserve the original model class name inproperties_json.model_class_name. - Found a second live GIS correctness issue: generated tile manifests carried Lambert bounds/transforms but no CRS, so detection GeoJSON could expose EPSG:31370 coordinates as if they were EPSG:4326.
- Fixed raster tile manifest generation to include
crs,source_crsanddataset_crson the manifest andcrson each tile entry when the source raster CRS is known. - Added regression coverage in
backend/tests/test_sprint8b_yolo_foundation.pyandbackend/tests/test_raster_operations_service.py.
Validation:
- RED:
python -m pytest backend/tests/test_sprint8b_yolo_foundation.py::test_yolo_class_filter_is_case_insensitive_and_persists_canonical_class -qfailed withdetection_count=0becauseBuildingdid not matchbuilding. python -m pytest backend/tests/test_sprint8b_yolo_foundation.py::test_yolo_class_filter_is_case_insensitive_and_persists_canonical_class -qpassed.python -m pytest backend/tests/test_sprint8b_yolo_foundation.py backend/tests/test_model_asset_catalog.py backend/tests/test_sprint121_real_data_detection_qa_smoke.py backend/tests/test_sprint122_raster_upload_metadata_mapping.py -qpassed: 20 tests.- RED:
python -m pytest backend/tests/test_raster_operations_service.py::test_raster_tile_returns_manifest_payload -qfailed because the tile manifest had nocrs. python -m pytest backend/tests/test_raster_operations_service.py::test_raster_tile_returns_manifest_payload -qpassed.python -m compileall backend/apppassed.bash scripts/run_readiness_check.shpassed: 387 backend tests, Alembic head check, frontend typecheck/build and shell syntax checks.- Tower deploy from commit
71c2cd9passed withGEOINTEL_INSTALL_AI=true. - Deploy-time live migration smoke passed; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202. - Real-data smoke after the class-normalization deploy passed and persisted 4 detections:
- project:
cb80638d-dbef-48ac-b19c-cec7c3efc96e - raster dataset:
ae0ff76d-70c0-404f-b777-54d14517179a - reference dataset:
8ac01b4f-bd6a-4d6a-b625-a0950ae0f3eb - analysis run:
7ba34274-411d-45e3-8f54-c37baec598b1 - quality check:
66907e6a-9ed7-4b0c-976f-5ad1ba9b8b7a - detection export:
516d37a3-2305-48a2-a3dd-b56f70eb055e - persisted detections used canonical
class_name=buildingand preservedmodel_class_name=Building.
- project:
- Tower deploy from commit
bc87681passed withGEOINTEL_INSTALL_AI=true. - Deploy-time live migration smoke passed; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202. - Real-data smoke after the tile-CRS deploy passed and persisted 4 detections:
- project:
6ced26f3-4486-451e-a05e-26a8f859e361 - raster dataset:
d54c3420-03d4-45a2-9501-bf1cce165a89 - reference dataset:
319dad51-15e9-4ae6-815b-8e39023ed962 - manifest:
/app/storage/tiles/6ced26f3-4486-451e-a05e-26a8f859e361/d54c3420-03d4-45a2-9501-bf1cce165a89/721c9557-5910-4994-b0ac-ba3418d12246/manifest.json - analysis run:
e99bcd07-ba48-4ebe-9ba9-24a94a8c1dcb - quality check:
32c8252b-fe60-4062-9639-125c62ca677f - detection export:
9d3a7f60-07a2-415c-9f75-a3c1988d0904
- project:
- Verified the new tile manifest now carries
crs=EPSG:31370,source_crs=EPSG:31370,dataset_crs=EPSG:31370and per-tilecrs=EPSG:31370. - Verified Detection GeoJSON now returns WGS84 coordinates around Geel instead of raw Belgian Lambert coordinates.
- Live detection QA persisted honest metrics for the Geel sample: 1 match, 3 false positives, 616 false negatives and score
0.0032206119162640897.
Open:
- None for availability, persistence and CRS propagation.
Limitations:
- This fixes class routing, persistence and future tile manifest CRS propagation. Existing tile manifests generated before this fix remain missing CRS and should be regenerated before AI runs.
- The active building model is operational but not calibrated for production-quality local Belgian/Kempen orthophoto extraction. The Geel sample proves end-to-end persistence and QA, while the 1/617 reference match result shows that confidence thresholds, tiling strategy, class mapping and IoU defaults still need model-quality calibration.
Next recommended pass:
- Run a detection calibration pass on several local orthophoto/reference samples: sweep confidence thresholds, inspect false positives/false negatives, tune tile size/overlap where needed and record a practical V1 baseline.
Sprint 122 Real operator data availability and raster metadata fix (2026-07-07)
Changed:
- Created real operator validation files on Tower under
/mnt/user/appdata/geointel/storage/operator-data. - Generated
/mnt/user/appdata/geointel/storage/operator-data/geel_orthophoto_wms_512.tiffrom the official Digitaal Vlaanderen OMWRGBMRVL WMSOrtholayer for a 500 m x 500 m AOI around Geel. - Generated
/mnt/user/appdata/geointel/storage/operator-data/geel_grb_gbg_buildings.geojsonfrom the official Digitaal Vlaanderen GRB OGC API FeaturesGBGbuilding collection for the same AOI; it contained 617 features. - Fixed
DatasetServiceraster upload metadata mapping so extractedbounds,resolutionanddtypepopulate persistedbounds_json,resolution_jsonandbands_json. - Added
backend/tests/test_sprint122_raster_upload_metadata_mapping.py.
Validation:
- RED:
python -m pytest backend/tests/test_sprint122_raster_upload_metadata_mapping.py -qfailed because uploaded rasterbounds_jsonwasNone. python -m pytest backend/tests/test_sprint122_raster_upload_metadata_mapping.py -qpassed.python -m compileall backend/apppassed.bash scripts/run_readiness_check.shpassed: 386 backend tests, Alembic head check, frontend typecheck/build and shell syntax checks.- Tower deploy from commit
2468945passed withGEOINTEL_INSTALL_AI=true. - Deploy-time live migration smoke passed; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202. - Real-data smoke passed:
- command:
REAL_RASTER_PATH=/mnt/user/appdata/geointel/storage/operator-data/geel_orthophoto_wms_512.tif REAL_REFERENCE_VECTOR_PATH=/mnt/user/appdata/geointel/storage/operator-data/geel_grb_gbg_buildings.geojson bash scripts/verify_real_data_detection_qa_workflow.sh http://192.168.10.150:1202 - project:
e1ec201b-bd83-4c95-be5a-f7225902d3c5 - raster dataset:
fca14d23-bc0c-4b1f-8bfa-ba968f2e05d0 - reference dataset:
5bb4a9b4-2a4e-4680-a729-777a75ecd51f - model asset:
yolov8n-building-segmentation-pt - manifest:
/app/storage/tiles/e1ec201b-bd83-4c95-be5a-f7225902d3c5/fca14d23-bc0c-4b1f-8bfa-ba968f2e05d0/0f29f110-951f-48eb-a2fb-636b587e31ee/manifest.json - analysis run:
c6798559-590c-42e3-a192-45a2409fa832 - detections:
0 - quality check:
cd0d13f9-f6ce-4acf-8859-7cb7aa666125 - detection export:
0081c230-1766-4ff3-8df0-e47236f529d1
- command:
Limitations:
- The workflow is operational against real operator data. A follow-up class-normalization pass found that the active evaluation model returned
Buildingwhile the workflow filtered onbuilding; see Sprint 123. - The prepared files are runtime artifacts on Tower, not repository fixtures.
Next recommended pass:
- Redeploy the class-normalization fix, rerun the real-data smoke and calibrate confidence/IoU thresholds against persisted detection and QA metrics.
Sprint 121 Real data detection and QA workflow smoke (2026-07-07)
Changed:
- Added
scripts/verify_real_data_detection_qa_workflow.shfor live-runtime validation with operator-provided real GIS inputs. - The smoke creates a project, uploads a real GeoTIFF-style raster as a source dataset, uploads a real reference-building GeoJSON/JSON as
dataset_role=reference, validates CRS/bounds/features, tiles the raster, selects a mounted local model asset, runs read-only YOLO preflight, runs configured YOLO detection, runs detection QA against persistedvector_features, and exports the detection run GeoJSON. - Registered the smoke in
scripts/run_readiness_check.shas a syntax check only, so normal readiness does not require real orthophotos, reference vectors, optional AI dependencies or model files. - Documented Tower usage and limitations in
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Validation:
- RED:
python -m pytest backend/tests/test_sprint121_real_data_detection_qa_smoke.py -qfailed whilescripts/verify_real_data_detection_qa_workflow.shdid not exist. python -m pytest backend/tests/test_sprint121_real_data_detection_qa_smoke.py -qpassed: 1 test.bash -n scripts/verify_real_data_detection_qa_workflow.shpassed.bash scripts/verify_real_data_detection_qa_workflow.sh --helppassed and printed requiredREAL_RASTER_PATHandREAL_REFERENCE_VECTOR_PATHusage.python -m compileall backend/apppassed.python scripts/smoke_docs.pypassed.bash scripts/run_readiness_check.shpassed: 385 backend tests, Alembic head check, frontend typecheck, frontend production build and shell syntax checks.cd backend && python -m alembic upgrade head --sqlpassed.- Missing-input guard passed:
bash scripts/verify_real_data_detection_qa_workflow.sh http://localhost:1202returned exit code 2 and printed usage. - Local
docker compose configcould not run in this Windows Codex environment because thedockercommand is not installed.
Limitations:
- The full real-data smoke was not executed in this Codex workspace because no operator-provided real GeoTIFF and reference GeoJSON were found locally.
- The script enforces real inputs and never seeds demo data, enables fixture detections, fetches live GRB/OSM/Sentinel data or downloads model weights.
Next recommended pass:
- Place a target orthophoto/GeoTIFF and matching reference-building GeoJSON under the Tower appdata path and run
REAL_RASTER_PATH=... REAL_REFERENCE_VECTOR_PATH=... bash scripts/verify_real_data_detection_qa_workflow.sh http://192.168.10.150:1202.
Sprint 120 Model asset detection workflow smoke (2026-07-06)
Changed:
- Added
scripts/verify_model_asset_detection_workflow.shto validate the configured-YOLO runtime path against a live Docker/Tower deployment. - The smoke seeds the explicit offline demo workflow, creates a raster tile manifest, selects the active local model asset from
GET /api/v1/detection/model-assets, verifies read-only YOLO preflight, submits the existing detection run endpoint and checks persisted AnalysisRun, Detection list and Detection GeoJSON outputs. - Registered the script in
scripts/run_readiness_check.shas a syntax check only, so ordinary readiness runs remain valid on machines without optional AI dependencies or mounted model files. - Documented the smoke in
scripts/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Validation:
- RED:
python -m pytest backend/tests/test_sprint120_model_asset_detection_workflow_smoke.py -qfailed becausescripts/verify_model_asset_detection_workflow.shdid not exist yet. python -m pytest backend/tests/test_sprint120_model_asset_detection_workflow_smoke.py -qpassed: 1 test.bash -n scripts/verify_model_asset_detection_workflow.shpassed.- Live Tower smoke passed:
bash scripts/verify_model_asset_detection_workflow.sh http://192.168.10.150:1202. - Live smoke selected
model_asset_id=yolov8n-building-segmentation-pt, generated manifest/app/storage/tiles/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/f9160f51-ee78-43b3-9353-d5390576fa1d/e9acd488-c376-45ed-b259-0dd79886f21e/manifest.json, persisted analysis run7f9e7ecb-c43d-4ed3-9f98-424bc0317805and returneddetection_count=0. python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 384 tests with the existing Pydanticmodel_*namespace warnings.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash scripts/run_readiness_check.shpassed: 384 backend tests, frontend typecheck/build, API contract audit, Alembic head and shell syntax checks.- Live browser/API smoke passed:
bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202. - Live GIS capability smoke passed:
bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202. - Live raster workflow smoke passed:
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202. - Live workbench default-state smoke passed:
bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202. - Live workbench backing-state smoke passed:
bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202. - Live demo/export workflow smoke passed:
bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202. bash scripts/verify_ai_handoff_interactions.sh http://192.168.10.150:1202could not run in this local Codex shell because Node cannot import Playwright; the script remains syntax-checked in readiness and the internal browser was used for live visual verification instead.- Internal browser validation passed on
http://192.168.10.150:1202: AI Labs rendered Detection Lab and Segmentation Lab, selectingyolo-configuredshowed the Local model assets selector withyolov8n-building-segmentation (active)andyolov8n, no-download copy was visible and no console errors were emitted. git push origin mainpushed commitb2fe7fa.- Tower deploy from commit
b2fe7facompleted withGEOINTEL_INSTALL_AI=true; the all-in-one container is published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202, API proxy and icon. - Post-deploy live model asset detection workflow smoke passed:
bash scripts/verify_model_asset_detection_workflow.sh http://192.168.10.150:1202selectedyolov8n-building-segmentation-pt, persisted analysis runf758c992-4fb8-4dca-ab29-5c216cb14078and returneddetection_count=0.
Limitations:
- The smoke proves the configured-YOLO runtime path, provenance and persistence. It does not prove production model quality because it runs against the synthetic demo raster.
- Real operational validation still requires uploading a georeferenced Kempen orthophoto/GeoTIFF, running the configured building model on that raster and comparing persisted detections against reference building vectors through QA/QC.
Next recommended pass:
- Create the real-data validation path for orthophoto upload, tile generation, configured building-model run and reference-vector QA/QC.
Sprint 118 Local model and reference catalog clarity (2026-07-06)
Changed:
- Added a read-only backend model asset catalog through
GET /api/v1/detection/model-assets. - Added
YOLO_MODELS_DIRto backend settings, Compose, Unraid env examples and all-in-one runtime startup so/app/modelsis the explicit model catalog directory. - Extended configured YOLO preflight and detection runs with optional
model_asset_id, resolved server-side against the model asset catalog. - Detection jobs and analysis runs now persist selected model asset ID, path and SHA-256 in parameters for reproducibility.
- Detection Lab now loads local model assets, selects the active model by default and lets operators choose a cataloged local model file for
yolo-configured. - Provider Capabilities now distinguishes GRB/OSM/manual/fixture reference-data sources from AI model choices.
- Updated
docs/API_CONTRACTS.md,docs/AI_PIPELINES.md,backend/README.md,frontend/README.md,deploy/unraid/README.md,scripts/README.md,docs/TODO.mdandCHANGELOG.md. - Added design/plan documents under
docs/superpowers/.
Validation:
- RED:
python -m pytest backend/tests/test_model_asset_catalog.py -qfailed before implementation becauseapp.services.model_asset_catalog_servicedid not exist. python -m pytest backend/tests/test_model_asset_catalog.py -qpassed: 5 tests.- RED:
python -m pytest backend/tests/test_sprint118_yolo_preflight_ui.py -qfailed before frontend wiring because the model asset types/API/hook/UI were absent. python -m pytest backend/tests/test_sprint118_yolo_preflight_ui.py -qpassed: 2 tests.- RED: runtime config tests failed before
YOLO_MODELS_DIRwas added to env examples, Unraid runtime andscripts/configure_yolo_model.py. python -m pytest backend/tests/test_docker_runtime_config.py::test_env_example_uses_runtime_env_names_read_by_backend_and_frontend backend/tests/test_docker_runtime_config.py::test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env backend/tests/test_sprint119_yolo_model_configuration.py -qpassed: 6 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 383 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.python scripts/audit_api_contracts.pypassed: 81 implemented routes match docs; 2 explicit non-envelope endpoints tracked.bash scripts/run_readiness_check.shpassed: 383 backend tests plus frontend typecheck/build, API contract audit, Alembic head and shell syntax checks.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.sh; bash -n deploy/unraid/run-dockerman-container.sh; bash -n deploy/unraid/all-in-one-start.sh; bash -n scripts/deploy_tower.shpassed.- Local
docker compose configcould not run because Docker is not installed in this Windows Codex environment; Tower deploy validation remains required. git push origin mainpassed and pushed commits through6e2a8cb.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1withGEOINTEL_INSTALL_AI=truepassed and redeployed Tower from commit6e2a8cb.- Deploy-time live migration smoke passed on Tower; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202, API proxy and icon. - Live
GET http://192.168.10.150:1202/api/v1/detection/model-assetsreturned two cataloged local assets:yolov8n-building-segmentation-ptactive with SHA-256152d6a9c5c76c9f2fd2fd5cc167efaed7c8c02e31002b15415899710f1d71f98, andyolov8n-pt. - Live
GET /api/v1/detection/yolo/preflight?model_asset_id=yolov8n-ptresolved/app/models/yolov8n.pt, reported dependencies available, no downloads and no inference. - Live
GET /api/v1/detection/yolo/preflight?model_asset_id=yolov8n-building-segmentation-pt&check_model_load=truepassed model load smoke withmodel_load_ok=true,torch_version=2.12.1,ultralytics_version=8.4.89, no downloads and no inference. - Internal browser validation passed on
http://192.168.10.150:1202: Detection Lab showedLocal model assets, listedyolov8n-building-segmentation (active)andyolov8n, auto-selected the active asset, showed no-download copy, and emitted no console errors. - Internal browser validation passed for System/Provider Capabilities:
Official reference sources, GRB, OSM andnot AI model choicescopy were visible with no console errors.
Limitations:
- The catalog is intentionally filesystem-backed and read-only. It does not download, validate semantic class metadata, train models or manage model lifecycle records in the database.
- GRB/OSM remain provider capabilities only; no live external fetching was added.
Next recommended pass:
- Redeploy Tower, verify
/api/v1/detection/model-assets, confirm Detection Lab shows the local model picker, then continue with real raster/model workflow validation on non-synthetic imagery.
Sprint 117 Reusable GIS run and AI runtime opt-in (2026-07-05)
Changed:
- Added a Map workspace full-run mode selector with
Create new dataset/exportandReuse latest saved dataset for QA. - Reuse mode runs QA/QC against the latest saved derived map-selection dataset without creating another derived dataset/export pair.
- Added opt-in Docker and Unraid AI build support through
GEOINTEL_INSTALL_AI=true; default builds still install only the GIS runtime. - Passed YOLO runtime environment variables and a
/app/modelsvolume into the all-in-one Unraid container so local PyTorch/Ultralytics models can be mounted explicitly. - Hardened the AI image path after Tower validation showed
torchimported butultralyticsfailed on a missing OpenCV native library. The Dockerfiles now include the required OpenCV runtime shared libraries and YOLO dependency detection performs real imports instead offind_specchecks. - Added a writable
YOLO_CONFIG_DIRdefault under application storage after Tower validation showed Ultralytics otherwise falls back to/tmpbecause root config is not writable in the container. - Added YOLO preflight runtime diagnostics so operators can see dependency assumption state, model directory,
YOLO_CONFIG_DIR, installedtorch/ultralyticspackage versions and CUDA availability without loading a model, running inference or downloading weights. - Added a read-only
GET /api/v1/detection/yolo/preflightendpoint and Detection Lab YOLO runtime preflight panel so browser operators can inspect live AI runtime readiness without loading a model, running inference or downloading weights. - Updated
.env.example,backend/README.md,frontend/README.md,scripts/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md. - Added regression coverage in
backend/tests/test_sprint116_operational_gis_map_workflow.py,backend/tests/test_sprint8b_yolo_foundation.pyandbackend/tests/test_docker_runtime_config.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py backend\tests\test_docker_runtime_config.py -qfailed before implementation becausefullWorkflowMode, AI build args and YOLO runtime env wiring were absent. python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py backend\tests\test_docker_runtime_config.py -qpassed: 22 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.python -m compileall backend/apppassed.python -m py_compile scripts\yolo_preflight.py backend\scripts\yolo_preflight.pypassed.python -m pytest backend\tests\test_sprint31_unraid_template.py backend\tests\test_docker_runtime_config.py -qpassed: 27 tests.- RED:
python -m pytest backend\tests\test_sprint8b_yolo_foundation.py backend\tests\test_docker_runtime_config.py -qfailed before the runtime hardening because YOLO dependency detection still usedfind_specand the Dockerfiles lacked OpenCV native runtime libraries. python -m pytest backend\tests\test_sprint8b_yolo_foundation.py backend\tests\test_docker_runtime_config.py -qpassed: 30 tests.- RED:
python -m pytest backend\tests\test_docker_runtime_config.py -qfailed beforeYOLO_CONFIG_DIRwiring because the Compose, Unraid and startup paths did not define a writable Ultralytics config directory. python -m pytest backend\tests\test_docker_runtime_config.py -qpassed: 21 tests.python -m compileall backend/apppassed after the AI runtime hardening.cd backend && python -m pytest -qpassed: 367 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 367 backend tests plus frontend typecheck/build.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.sh; bash -n scripts/deploy_tower.sh; bash -n deploy/unraid/run-dockerman-container.shpassed.- Local Codex host could not run
docker compose configbecause Docker is not installed in this Windows environment; Tower Docker validation is required after push/deploy. powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1withGEOINTEL_INSTALL_AI=truepassed after the AI runtime hardening and redeployed Tower from commit9cad8d4.- Deploy-time live migration smoke passed on Tower; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202, API proxy and icon. - Tower container check passed:
torchimported as2.12.1+cu130,torch.cuda.is_available()returnedFalse,ultralyticsimported as8.4.87, andscripts/yolo_preflight.py --enabled --jsonreturneddependencies_available=true,status=not_configured,will_download_models=false,will_run_inference=falsebecause no local model path is configured yet. - Tower runtime
YOLO_CONFIG_DIRis/app/storage/ultralytics; the directory exists, is writable and Ultralytics writes settings there instead of root config. - Internal browser validation passed against
http://192.168.10.150:1202: the live shell and Map workspace rendered without console errors, with database layer selection, Operational GIS controls, and both full-run modes visible. - RED:
python -m pytest backend\tests\test_sprint13_yolo_preflight.py -qfailed before runtime diagnostics were implemented becauseruntimewas absent from preflight output. python -m pytest backend\tests\test_sprint13_yolo_preflight.py -qpassed: 8 tests.python -m pytest backend\tests\test_sprint13_yolo_preflight.py backend\tests\test_sprint8b_yolo_foundation.py backend\tests\test_docker_runtime_config.py -qpassed: 39 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 369 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 369 backend tests plus frontend typecheck/build and Alembic head.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.sh,bash -n scripts/deploy_tower.sh,bash -n deploy/unraid/run-dockerman-container.shandbash -n deploy/unraid/all-in-one-start.shpassed.- Local Codex host still cannot run
docker compose configbecause Docker is not installed in this Windows environment; Tower Docker validation is required after push/deploy. powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1withGEOINTEL_INSTALL_AI=truepassed and redeployed Tower from commit7a29e78.- Deploy-time live migration smoke passed on Tower; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202, API proxy and icon. - Tower container check passed: remote checkout is
7a29e78,geointelis healthy on0.0.0.0:1202->80/tcp, andscripts/yolo_preflight.py --enabled --jsonreportsdependencies_available=true,torch_version=2.12.1,ultralytics_version=8.4.88,cuda_available=false,yolo_config_dir=/app/storage/ultralytics,status=not_configured,will_download_models=falseandwill_run_inference=false. - RED:
python -m pytest backend\tests\test_sprint13_yolo_preflight.py::test_yolo_preflight_api_returns_canonical_envelope backend\tests\test_sprint118_yolo_preflight_ui.py -qfailed before implementation because/api/v1/detection/yolo/preflightreturned 404 and the Detection Lab did not surface a YOLO runtime preflight panel. python -m pytest backend\tests\test_sprint13_yolo_preflight.py::test_yolo_preflight_api_returns_canonical_envelope backend\tests\test_sprint118_yolo_preflight_ui.py -qpassed: 2 tests.cd frontend && npm run typecheckpassed after adding the preflight API client and Detection Lab panel.python -m pytest backend\tests\test_sprint13_yolo_preflight.py backend\tests\test_sprint118_yolo_preflight_ui.py backend\tests\test_sprint48_api_contract_audit.py -qpassed: 13 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 371 tests.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 371 backend tests plus frontend typecheck/build and API contract audit for 80 documented routes.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shandbash -n scripts/deploy_tower.shpassed.git pushpassed after Tower/Gitea became reachable again and pushed commit7aa9382.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1withGEOINTEL_INSTALL_AI=truepassed and redeployed Tower from commit7aa9382.- Deploy-time live migration smoke passed on Tower; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for
http://192.168.10.150:1202, API proxy and icon. - Live API check passed for
GET http://192.168.10.150:1202/api/v1/detection/yolo/preflight: it returned the canonicaldataenvelope,status=not_configured,YOLO_ENABLED=false,torch_version=2.12.1,ultralytics_version=8.4.89,yolo_config_dir=/app/storage/ultralytics,will_download_models=falseandwill_run_inference=false. - Tower container check passed with explicit CLI
--enabled:dependencies_available=true,torch_version=2.12.1,ultralytics_version=8.4.89,cuda_available=false,status=not_configured,will_download_models=falseandwill_run_inference=falsebecause no local model path is configured yet.
Limitations:
GEOINTEL_INSTALL_AI=trueinstalls optional PyTorch/Ultralytics dependencies but still requires a user-provided local model file; GeoIntel does not download weights.- Reuse mode intentionally reuses only the latest saved map-selection dataset for QA/QC. It does not delete or mutate older derived datasets/exports.
Next recommended pass:
- Run full readiness, deploy Tower, and browser-verify both Map run modes plus configured-YOLO preflight status in the live container.
Sprint 116 Operational GIS map workflow (2026-07-04)
Changed:
- Switched the default MapLibre basemap to an OpenStreetMap road raster style with visible attribution while preserving
VITE_MAP_STYLE_URLas the override for managed/production map styles. - Added a persisted database layer selector to the Map workspace so ready vector datasets can be opened directly from stored project data.
- Added an Operational GIS run panel that reuses the selected AOI bbox or active layer bbox and calls the existing persisted
vector_featuresbbox selection workflow. - Added a visible basemap policy notice when the public OpenStreetMap fallback is active.
- Added a guided operational workflow that brings query, derived dataset save, GeoJSON export, reference selection, QA/QC run and evidence handoff into the Map workspace.
- Added a one-click full GIS workflow action that runs persisted selection, saves the derived dataset, saves a GeoJSON export and optionally runs QA/QC against the selected reference dataset.
- Updated
.env.example,CHANGELOG.md,docs/TODO.md,docs/ENVIRONMENT_SPEC.mdandfrontend/README.md. - Added regression coverage in
backend/tests/test_sprint116_operational_gis_map_workflow.py.
Validation:
cd frontend && npm run typecheckpassed.python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py backend\tests\test_sprint85_map_workspace_density.py backend\tests\test_sprint106_map_bbox_extract.py backend\tests\test_sprint107_map_selection_export.py backend\tests\test_sprint108_map_selection_derived_dataset.py -qpassed: 18 tests.python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py backend\tests\test_sprint109_map_selection_qa_shortcut.py backend\tests\test_sprint107_map_selection_export.py backend\tests\test_sprint108_map_selection_derived_dataset.py -qpassed: 11 tests.python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py -qpassed: 2 tests after aligning.env.examplewith the managed-style override policy.- RED:
python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py -qfailed before implementation becauseRun full GIS workflow,runFullGisWorkflowandfullWorkflowStatuswere not present. python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py -qpassed: 2 tests after adding the full GIS workflow action.python -m pytest backend\tests\test_sprint116_operational_gis_map_workflow.py backend\tests\test_sprint106_map_bbox_extract.py backend\tests\test_sprint107_map_selection_export.py backend\tests\test_sprint108_map_selection_derived_dataset.py backend\tests\test_sprint109_map_selection_qa_shortcut.py backend\tests\test_sprint110_map_qa_evidence_drilldown.py -qpassed: 18 tests.cd frontend && npm run buildpassed.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 364 tests.bash scripts/run_readiness_check.shpassed: 364 backend tests plus frontend typecheck/build.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commit350d50a.- Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Internal Codex browser validation passed against
http://192.168.10.150:1202: the Map workspace rendered a nonblank road basemap, persisted vector layer selector, operational GIS run panel and bbox query action with no console errors. powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed again after the guided workflow update; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commit14b66e6.- Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Internal Codex browser validation passed: the Map workspace showed the basemap policy notice, database layer selector, guided operational GIS steps/actions and nonblank map canvas with no console errors.
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed after aligning.env.example; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commitfc88ceb.- Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Tower runtime check passed after the one-click GIS workflow update: remote checkout is commit
5331358, thegeointelall-in-one container is healthy and published on0.0.0.0:1202->80/tcp. LIVE_SMOKE_CONTAINER=geointel bash scripts/live_migration_smoke.shpassed on Tower; PostGIS reported3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900.bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202passed on Tower for frontend, API proxy and icon.- Internal Codex browser validation passed against
http://192.168.10.150:1202: the Map workspace rendered without console warnings/errors or horizontal overflow, theRun full GIS workflowaction was present, and a live run produced the persisted query/save/export statusDataset/export complete. Select a reference dataset to add QA/QC.
Limitations:
- The default OpenStreetMap tile service is appropriate for local V1 testing and demos, but production or heavier deployments should set
VITE_MAP_STYLE_URLto a managed tile/style provider. - This pass does not add live GRB/OSM fetching, new API routes, new migrations or fake data.
- The one-click workflow can still create a new derived dataset/export each time it is clicked; a future polish pass should add explicit reuse/replace behavior for repeated operator runs.
Next recommended pass:
- Add reuse/replace behavior for repeated map workflow runs and make reference selection for QA/QC more guided in the Map workspace.
Sprint 115 QA/QC and Exports usability layout pass (2026-07-04)
Changed:
- Added a QA/Exports usability layer to the frontend shell CSS to reduce evidence/history density without changing behavior.
- Rebalanced QA/QC and Exports workspace columns for review-first usage.
- Made QA/QC summary, handoff, drilldown, feature evidence, metric history and raw provenance surfaces more compact.
- Reduced raw QA provenance height so JSON evidence remains available but no longer dominates the page.
- Made export handoff cards, latest-artifact cards, action cards and export history controls denser and easier to scan.
- Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md. - Added regression coverage in
backend/tests/test_sprint115_quality_export_usability_layout.py.
Validation:
cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.python -m pytest backend\tests\test_sprint115_quality_export_usability_layout.py backend\tests\test_sprint86_quality_workspace_density.py backend\tests\test_sprint89_export_system_density.py backend\tests\test_sprint70_quality_handoff_polish.py backend\tests\test_sprint78_export_preview_readability.py -qpassed: 15 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 362 tests.bash scripts/run_readiness_check.shpassed: 362 backend tests plus frontend typecheck/build.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commit915b34c.- Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
Limitations:
- This pass is visual/layout only; it does not change API contracts, persistence, export generation, QA metrics or map behavior.
- Live Tower redeploy has been run; the QA/QC and Exports usability layout pass is available at
http://192.168.10.150:1202.
Next recommended pass:
- Run a live visual audit after redeploy, then refine AI Labs/System or address any remaining visual rough edges found in the browser.
Sprint 114 Data and Map usability layout pass (2026-07-04)
Changed:
- Added a Data/Map usability layer to the frontend shell CSS to improve the core select-and-extract workflow without changing behavior.
- Rebalanced the Data workspace columns and made dataset upload, role summaries, catalog cards, metrics and actions more compact.
- Made the Map workspace more map-first by ordering the MapLibre frame before dense controls and increasing desktop map height.
- Compressed map context, provenance, layer controls, bbox selection, selected-feature extraction and inspector surfaces.
- Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md. - Added regression coverage in
backend/tests/test_sprint114_data_map_usability_layout.py.
Validation:
cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.python -m pytest backend\tests\test_sprint113_calm_workbench_layout.py backend\tests\test_sprint114_data_map_usability_layout.py backend\tests\test_sprint74_data_map_mobile_polish.py backend\tests\test_sprint85_map_workspace_density.py -qpassed: 10 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 360 tests.bash scripts/run_readiness_check.shpassed: 360 backend tests plus frontend typecheck/build.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commit9721937.- Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
Limitations:
- This pass is visual/layout only; it does not change API contracts, persistence, map query behavior, exports or QA logic.
- Live Tower redeploy has been run; the Data and Map usability layout pass is available at
http://192.168.10.150:1202.
Next recommended pass:
- Run a live visual audit after redeploy and then refine QA/QC and Exports in the same quieter style.
Sprint 113 calm workbench layout pass (2026-07-04)
Changed:
- Added a calm-density layer to the frontend shell CSS to reduce visual pressure without changing workflows.
- Softened the base palette, borders and shadows.
- Made the top context bar, left workspace navigation, main heading, readiness tiles and inspector surfaces more compact.
- Hid the duplicated workspace command bar because the sidebar remains the primary persistent navigation.
- Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md. - Added regression coverage in
backend/tests/test_sprint113_calm_workbench_layout.py.
Validation:
cd frontend && npm run typecheckpassed.python -m pytest backend\tests\test_sprint49_workbench_shell_refactor.py backend\tests\test_sprint62_frontend_visual_polish.py backend\tests\test_sprint82_shell_density_polish.py backend\tests\test_sprint83_workspace_panel_hierarchy.py -qpassed: 10 tests.cd frontend && npm run buildpassed.python -m pytest backend\tests\test_sprint113_calm_workbench_layout.py -qpassed: 2 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 358 tests.bash scripts/run_readiness_check.shpassed: 358 backend tests plus frontend typecheck/build.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commit0355a3d.- Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
Limitations:
- This pass improves visual density and hierarchy only; no API, persistence, workflow or map behavior changed.
- Live Tower redeploy has been run; the calmer layout is available at
http://192.168.10.150:1202.
Next recommended pass:
- Do a live visual audit after redeploy and then tune individual workspaces, starting with Data and Map, based on actual screenshots.
Sprint 112 QA evidence map overlay (2026-06-25)
Changed:
- Added
QualityEvidenceServiceto resolve persisted QA/QC evidence ids back to stored geometries. - Added
GET /api/v1/projects/{project_id}/quality-checks/{quality_check_id}/evidence/geojson. - The endpoint returns a canonical envelope with
quality_check_id, dataset/run provenance, warnings and a GeoJSON FeatureCollection. - Evidence resolution supports candidate dataset
vector_features, candidate persisteddetections/segmentationsfor analysis-run QA, and referencevector_features. - Added QA/QC panel actions to show selected or latest evidence on the Map workspace.
- Added a MapLibre QA evidence source/layers with distinct match candidate, match reference, false-positive and false-negative styling.
- Added map overlay loading/error/clear state and a compact legend.
- Updated
docs/API_CONTRACTS.md,frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint112_qa_evidence_overlay.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint112_qa_evidence_overlay.py -qfailed before implementation becauseapp.services.quality_evidence_servicedid not exist. - RED: after backend implementation, the same test failed until frontend
qaEvidenceData/API wiring existed. python -m pytest backend\tests\test_sprint112_qa_evidence_overlay.py -qpassed: 4 tests.cd frontend && npm run typecheckpassed after making the MapLibre expression type explicit.python -m pytest backend\tests\test_sprint112_qa_evidence_overlay.py backend\tests\test_qa_service.py backend\tests\test_sprint8c_detection_visualization_qa.py backend\tests\test_sprint9_segmentation_foundation.py -qpassed: 25 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 356 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash scripts/run_readiness_check.shpassed: 356 backend tests plus frontend typecheck/build.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202from commitb9674a0.- Deploy-time live migration smoke passed against the container database after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live QA evidence API smoke passed:
GET /api/v1/projects/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/quality-checks/2a291f88-5ed1-4110-ba6b-d200ec722098/evidence/geojsonreturned a GeoJSON FeatureCollection with 4 persisted evidence features and 0 warnings. - Internal Codex browser validation passed against
http://192.168.10.150:1202: the QA/QC evidence drilldown rendered,Show evidence overlayopened the Map workspace, MapLibre canvas was present, the QA/QC evidence overlay reported 4 rendered features, and the mobile viewport had no horizontal overflow.
Limitations:
- The overlay is generated read-only from existing persisted evidence and geometries; no new evidence table or migration was introduced.
- Missing evidence ids are reported as warnings and do not create fake geometries.
- No provider fetching, AI dependency, real model behavior or new product domain was added.
Next recommended pass:
- Consider a small export/handoff action for the evidence overlay GeoJSON or a reusable browser smoke script that verifies the QA evidence overlay after deploy.
Sprint 111 QA feature evidence persistence (2026-06-25)
Changed:
- Added feature-level evidence extraction to the shared QA IoU matcher.
- Dataset QA now returns and persists
match_evidence,false_positive_evidenceandfalse_negative_evidence. - Detection QA and segmentation QA now use the same evidence-aware matcher and persist the same evidence keys in
quality_checks.findings_json. - Extended the QA/QC drilldown with compact matched, false-positive and false-negative feature id lists before the raw findings JSON.
- Updated
docs/API_CONTRACTS.md,frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added/extended regression coverage in
backend/tests/test_qa_service.py,backend/tests/test_sprint7a_persistence_foundation.pyandbackend/tests/test_sprint111_qa_feature_evidence.py.
Validation:
- RED:
python -m pytest backend\tests\test_qa_service.py -qfailed before implementation becauseQaProviderComparisonResulthad nomatch_evidence. - RED:
python -m pytest backend\tests\test_sprint111_qa_feature_evidence.py -qfailed before docs were updated becausedocs/API_CONTRACTS.mddid not document the evidence keys. python -m pytest backend\tests\test_qa_service.py -qpassed: 3 tests.python -m pytest backend\tests\test_sprint8c_detection_visualization_qa.py backend\tests\test_sprint9_segmentation_foundation.py -qpassed: 18 tests.python -m pytest backend\tests\test_sprint111_qa_feature_evidence.py -qpassed: 2 tests.python -m pytest backend\tests\test_qa_service.py backend\tests\test_sprint7a_persistence_foundation.py -qpassed: 10 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 352 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash scripts/run_readiness_check.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202.- Deploy-time live migration smoke passed against the container database, including PostGIS/version/schema checks.
- Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live QA API smoke passed:
POST /api/v1/qa/detections-vs-referencereturnedmatch_evidence,false_positive_evidenceandfalse_negative_evidence. - Live persisted quality-check smoke passed:
GET /api/v1/projects/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/quality-checksreturned the evidence arrays infindings_json.
Limitations:
- Feature-level evidence is persisted as ids/IoU metadata in
quality_checks.findings_json; noquality_check_itemstable or first-class evidence geometry table was introduced. - Evidence map overlays can now be built from persisted ids, but overlay generation remains future work.
- No migration, provider fetching, AI dependency, real model behavior or new product domain was added.
Next recommended pass:
- Add QA evidence overlay generation by resolving persisted evidence ids back to candidate/reference geometries and rendering false positives/false negatives as MapLibre layers.
Sprint 110 Map QA evidence drilldown (2026-06-25)
Changed:
- Extended
QaComparisonResultfrontend typing with optionalquality_check_id, matching the existing backend QA result payload. - Updated
useMapSelectionQato keep the latest persisted map-selection quality-check id after a successful QA/QC comparison. - Extended the Map workspace QA/QC result state with inline evidence: quality-check id, matches, false positives, false negatives, mean IoU and QA warnings.
- Added
Open QA/QC evidencehandoff from Map workspace to the existing QA/QC workspace drilldown, avoiding a parallel QA detail system. - Added compact styling for the Map QA evidence and warning surface.
- Updated
frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint110_map_qa_evidence_drilldown.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint110_map_qa_evidence_drilldown.py -qfailed before implementation because the hook/evidence wiring was absent. python -m pytest backend\tests\test_sprint110_map_qa_evidence_drilldown.py -qpassed: 2 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 349 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash scripts/run_readiness_check.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202.- Deploy-time live migration smoke passed against the container database, including PostGIS/version/schema checks.
- Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live API proxy smoke passed:
GET http://192.168.10.150:1202/api/v1/projectsreturned the demo project envelope.
Limitations:
- The Map evidence handoff opens the existing QA/QC workspace; selecting a specific historical check inside that workspace remains governed by the QA/QC panel's own latest-check behavior.
- False-positive and false-negative geometries are summarized by persisted metrics/findings; dedicated map overlays for unmatched evidence remain future work.
- No backend API contract, migration, provider fetching, AI dependency, real model behavior or new product domain was added.
Next recommended pass:
- Add optional unmatched-evidence map overlays once the QA persistence model stores explicit matched/unmatched feature ids or geometries.
Sprint 109 Map selection QA shortcut (2026-06-25)
Changed:
- Added
useMapSelectionQato keep Map workspace QA/QC orchestration out ofApp.tsx. - Added a Map workspace QA/QC shortcut after
Save as dataset, allowing the latest derived map selection dataset to be compared against a selected reference dataset. - The shortcut reuses the existing
qaApi.runQaflow and refreshes persisted quality checks/project data after completion. - Added inline precision, recall, F1 and quality-check status feedback in the Map workspace.
- Added compact styling for the Map selection QA surface.
- Updated
frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint109_map_selection_qa_shortcut.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint109_map_selection_qa_shortcut.py -qfailed before implementation because the hook and wiring were absent. python -m pytest backend\tests\test_sprint109_map_selection_qa_shortcut.py -qpassed: 2 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 347 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash scripts/run_readiness_check.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202.- Deploy-time live migration smoke passed against the container database, including PostGIS/version/schema checks.
- Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live API QA smoke passed:
POST /api/v1/qa/detections-vs-referencecompared derived map selection dataset266aa1de-908e-4bc4-987e-996374ad747bagainst reference dataset21dd968a-2ba4-4798-89d4-f3af91f9d24c, returnedprecision=0.5,recall=0.5,f1_score=0.5,mean_iou=0.8339768339652592and persisted quality check1730c270-6dee-4000-8813-12aa91df6b33. - Live quality-check list smoke passed:
GET /api/v1/projects/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/quality-checksreturned the persisted map-selection QA check with precision, recall, F1, mean IoU, false-positive and false-negative metrics.
Limitations:
- The Map shortcut currently uses the existing QA comparison defaults with IoU threshold
0.5. - QA results are summarized inline; detailed false-positive/false-negative evidence remains in the QA/QC workspace.
- No backend API contract, migration, provider fetching, AI dependency, real model behavior or new product domain was added.
Next recommended pass:
- Add a QA result drilldown/handoff from the Map workspace so operators can inspect persisted false-positive and false-negative evidence directly after running selection QA/QC.
Sprint 108 Map selection derived datasets (2026-06-25)
Changed:
- Added
POST /api/v1/projects/{project_id}/datasets/{dataset_id}/vector/select/derive. - Added
VectorSelectionDeriveRequestfor bbox selection-to-derived-dataset requests. - Added
VectorOperationsService.derive_selection_dataset, which selects persisted PostGISvector_features, writes a derived GeoJSON dataset artifact, stores source provenance and re-indexes the derived features intovector_features. - Added
Save as datasetto the Map workspace selection result state with loading/error/latest-dataset feedback. - Updated frontend dataset API typing and wiring for selection-derived datasets.
- Updated
docs/API_CONTRACTS.md,backend/README.md,frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint108_map_selection_derived_dataset.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint108_map_selection_derived_dataset.py -qfailed before implementation because the service, route and frontend contracts were absent. python -m pytest backend\tests\test_sprint108_map_selection_derived_dataset.py -qpassed: 4 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 345 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash scripts/run_readiness_check.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202.- Deploy-time live migration smoke passed against the container database, including PostGIS/version/schema checks.
- Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live API smoke passed:
POST /api/v1/projects/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/datasets/6e5a3926-1a15-4136-b54f-ba5de9ec0e84/vector/select/derivecreated derived dataset266aa1de-908e-4bc4-987e-996374ad747bwithdataset_role="derived",source_name="map_selection"and 2 features. - Live API content smoke passed:
GET /api/v1/projects/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/datasets/266aa1de-908e-4bc4-987e-996374ad747b/contentreturned a GeoJSONFeatureCollectionwith 2 features. - Live PostGIS query smoke passed:
POST /api/v1/projects/c0b00f1f-80bf-4992-be94-f5e5e6f6bf63/datasets/266aa1de-908e-4bc4-987e-996374ad747b/vector/selectreturned 2 features from the derived dataset's persistedvector_features.
Limitations:
- Selection-derived datasets are bbox-only and use EPSG:4326 coordinates.
- Empty selections are rejected with
VECTOR_OPERATION_EMPTY_RESULT. - No migrations, live provider fetching, AI dependency, real model behavior or new product domain were added.
Next recommended pass:
- Add an explicit QA/QC shortcut from a selected derived map dataset to compare it against a reference dataset without leaving the Map workspace.
Sprint 107 Map selection export handoff (2026-06-25)
Changed:
- Added
vector_selectionto the GeoJSON export contract. - Added
ExportService.export_vector_selection_geojson, which queries persisted PostGISvector_featuresthroughVectorFeatureService.select_features_by_bbox, writes the selected FeatureCollection and persists anexportsrow withexport_type="vector_selection_geojson". - Extended
POST /api/v1/exports/geojsonto acceptexport_kind="vector_selection"with EPSG:4326 bbox and feature limit. - Added frontend export API typing for bbox/limit and
useExportWorkflow.exportMapSelectionGeoJson. - Added
Save area exportto the Map workspace selection result state with loading/error/latest-path feedback. - Updated
docs/API_CONTRACTS.md,backend/README.md,frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint107_map_selection_export.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint107_map_selection_export.py -qfailed before implementation because the selection export service, route contract and frontend wiring were absent. python -m pytest backend\tests\test_sprint107_map_selection_export.py -qpassed: 3 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 341 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash scripts/run_readiness_check.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed; rebuilt and redeployed the all-in-one container onhttp://192.168.10.150:1202.- Deploy-time live migration smoke passed against the container database, including PostGIS/version/schema checks.
- Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live API smoke passed:
POST /api/v1/exports/geojsonwithexport_kind="vector_selection"created export1d16c78b-7e8c-4081-8edc-5be38811b50ewithexport_type="vector_selection_geojson",feature_count=2andsource_table="vector_features". - Live API content smoke passed:
GET /api/v1/exports/1d16c78b-7e8c-4081-8edc-5be38811b50e/contentreturned a GeoJSONFeatureCollectionwith 2 persisted vector features.
Limitations:
- Selection exports are bbox-only and reuse the same EPSG:4326 constraints as the Map area selection endpoint.
- Saving a selection creates an export artifact, not a derived dataset.
- No migrations, live provider fetching, AI dependency, real model behavior or new product domain were added.
Next recommended pass:
- Add a live browser smoke that exercises
Save area export, confirms the export appears in Export Center history and previews/downloads the persistedvector_selection_geojsonartifact.
Sprint 106 Map area selection extract (2026-06-25)
Changed:
- Added
POST /api/v1/projects/{project_id}/datasets/{dataset_id}/vector/selectfor read-only bbox selection over persisted PostGISvector_features. - Added
VectorSelectionBBox,VectorSelectionRequestandVectorSelectionResponseschemas and exported them through the backend schema module. - Added
VectorFeatureService.select_features_by_bbox, including EPSG:4326 bbox validation, feature limit capping, PostGISST_Intersectsquery and GeoJSON FeatureCollection conversion from persisted geometries. - Added frontend
selectVectorFeaturesAPI client support anduseMapSelectionExtract. - Extended the Map workspace with an
Area selectionpanel, two-click map bbox selection, manual bbox inputs, selected-feature/AOI/active-layer bbox shortcuts, area GeoJSON download/copy actions and a compact selected-feature table. - Extended
GeoMapwithselection-bboxandselection-resultMapLibre GeoJSON overlays. - Updated
docs/API_CONTRACTS.md,frontend/README.md,backend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added regression coverage in
backend/tests/test_sprint106_map_bbox_extract.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint106_map_bbox_extract.py -qfailed before implementation because the vector selection service, route and frontend contracts were absent. python -m pytest backend\tests\test_sprint106_map_bbox_extract.py -qpassed: 5 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 338 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed commit851d722to Tower on port 1202.- Deploy-time live migration smoke passed after database readiness attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed with demo project, AOI, 3/3 ready datasets and seeded QA/QC.- Live API smoke passed against
POST /api/v1/projects/{project_id}/datasets/{dataset_id}/vector/select: demo vector dataset returned 2 persisted features as a GeoJSON FeatureCollection. - Internal browser validation passed against
http://192.168.10.150:1202: Map workspace renderedArea selection,Start map bboxandRun area extract;Use layer bboxfilled EPSG:4326 bbox values;Run area extractreturned 2 features, showedvector_featuressource plusDownload area GeoJSONandCopy area GeoJSON; console warnings/errors were empty.
Limitations:
- Selection shape is bbox-only in EPSG:4326. Polygon/lasso selection remains future work.
- The endpoint is read-only and does not create exports or derived datasets; operators can download the selected GeoJSON client-side.
- No migrations, live provider fetching, AI dependency, real model behavior or new product domain were added.
Next recommended pass:
- Add a browser/live smoke around the area selection panel after deploy, then consider export-center handoff for persisted selection artifacts if V1 needs server-side audit retention.
Sprint 105 Map feature extract (2026-06-25)
Changed:
- Added a
Selection & extractsurface tofrontend/src/components/map/MapWorkspace.tsx. - Clicking a visible map feature now gives operators a focused extraction panel with geometry type, coordinate count, EPSG:4326 bbox, property count and property table.
- Added client-side
Download selected GeoJSON,Copy selected propertiesandClear selectionactions for the clicked feature. - Added a dedicated
selected-featureMapLibre source with fill/line/circle highlight layers infrontend/src/components/GeoMap.tsx. - Wired the selected feature highlight through
frontend/src/App.tsx. - Added responsive selection/extract CSS in
frontend/src/styles/app.css. - Updated
frontend/README.md,CHANGELOG.mdanddocs/TODO.md. - Added
backend/tests/test_sprint105_map_feature_extract.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint105_map_feature_extract.py -qfailed before implementation because the extract panel, selected-feature highlight layer and CSS contracts were absent. python -m pytest backend\tests\test_sprint105_map_feature_extract.py backend\tests\test_sprint19_map_workbench.py backend\tests\test_sprint85_map_workspace_density.py -qpassed: 9 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -qpassed: 333 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed commit561304cto Tower on port 1202.- Deploy-time live migration smoke passed after database readiness attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Internal browser live check confirmed the Map workspace renders the
Selection & extractpanel and empty selection guidance athttp://192.168.10.150:1202. - Live frontend bundle check confirmed
Selection & extract,selected-featureandDownload selected GeoJSONmarkers in/assets/index-DVYT-JPu.js.
Limitations:
- This pass extracts the single currently clicked and loaded map feature only.
- Rectangle, lasso or polygon selection over persisted PostGIS
vector_featuresstill requires a backend spatial query endpoint and drawing workflow. - Internal browser canvas clicks did not reliably hit the small demo polygon features during validation; static regression tests, TypeScript build and live bundle markers verify the MapLibre selection wiring, and the live UI panel is present.
- No backend API contract, migration, provider fetching, AI dependency or persistence behavior changed.
Next recommended pass:
- Add map area/rectangle selection backed by a PostGIS spatial-query endpoint for multi-feature extraction, then expose export handoff for the selected result set.
Sprint 100 raster tile Segmentation Lab handoff (2026-06-24)
Changed:
- Added
segmentationTileManifestPathstate tofrontend/src/hooks/useSegmentationWorkflow.ts. - Sent
tile_manifest_pathin existing segmentation run requests when the field is populated. - Added a
Tile manifestinput tofrontend/src/components/segmentation/SegmentationLab.tsx. - Added a
Use in Segmentation Labhandoff beside the existing Detection Lab handoff infrontend/src/components/datasets/RasterControls.tsx. - Wired the handoff through
frontend/src/components/datasets/DatasetDetailPanel.tsxandfrontend/src/App.tsx. - Updated
frontend/README.mdandCHANGELOG.md. - Added
backend/tests/test_sprint100_segmentation_manifest_handoff.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint100_segmentation_manifest_handoff.py -qfailed before implementation because segmentation manifest state and handoff wiring did not exist. python -m pytest backend\tests\test_sprint100_segmentation_manifest_handoff.py -qpassed.cd frontend && npm run typecheckpassed.python -m pytest backend\tests\test_sprint100_segmentation_manifest_handoff.py backend\tests\test_sprint99_raster_ui_handoff.py backend\tests\test_sprint88_ai_lab_density.py backend\tests\test_sprint9_segmentation_foundation.py -qpassed: 17 tests.cd frontend && npm run buildpassed.python -m compileall backend/apppassed.python -m pytest -qfrombackend/passed: 323 tests.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed140314ato Tower on port 1202.- Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202passed: inspect, preview, stats andraster.tile.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed with3/3 readydatasets.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed.- Live frontend bundle check confirmed
Latest tile manifest,Use in Detection Lab,Use in Segmentation LabandRaster tile manifest pathmarkers in/assets/index-DygxAZpB.js.
Limitations:
- Frontend handoff only; no backend route, migration, provider fetching, AI dependency or model behavior changes.
- Segmentation remains governed by the existing model registry and explicit-run controls.
Next recommended pass:
- Add a real browser interaction smoke for clicking both raster manifest handoff buttons into AI Labs, then continue with small usability polish around AI model readiness.
Sprint 99 raster tile Detection Lab handoff (2026-06-23)
Changed:
- Added latest raster tile manifest tracking to
frontend/src/hooks/useDatasetWorkflow.tsfrom persistedraster.tilejob results and direct tile generation responses. - Surfaced the latest manifest path in
frontend/src/components/datasets/RasterControls.tsx. - Added a
Use in Detection Labhandoff that fills the selected raster dataset and tile manifest path in the existing Detection Lab state. - Updated
frontend/src/components/datasets/DatasetDetailPanel.tsx,frontend/src/App.tsx,frontend/README.mdandCHANGELOG.md. - Added
backend/tests/test_sprint99_raster_ui_handoff.py.
Validation:
- RED:
python -m pytest backend\tests\test_sprint99_raster_ui_handoff.py -qfailed before implementation because the raster tile manifest state and handoff wiring did not exist. python -m pytest backend\tests\test_sprint99_raster_ui_handoff.py -qpassed.cd frontend && npm run typecheckpassed.python -m pytest backend\tests\test_sprint99_raster_ui_handoff.py backend\tests\test_sprint95_raster_pipeline_hardening.py backend\tests\test_sprint28_dataset_workflow_hook.py -qpassed: 6 tests.cd frontend && npm run buildpassed.python -m compileall backend/apppassed.python -m pytest -qfrombackend/passed: 322 tests.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployedaa41dfato Tower on port 1202.- Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202passed: inspect, preview, stats andraster.tile.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed with3/3 readydatasets.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed.- Live frontend bundle check confirmed
Latest tile manifestandUse in Detection Labmarkers in/assets/index-gJWV1CAi.js.
Limitations:
- Frontend handoff only; no API contract, migration, provider fetching, AI inference or model behavior changes.
- The Detection Lab still follows the existing model availability and explicit-run constraints.
Next recommended pass:
- Add a browser interaction smoke for clicking the raster manifest handoff into Detection Lab, or continue with segmentation tile-manifest prefill parity.
Sprint 98 demo raster workflow smoke (2026-06-23)
Changed:
- Added
scripts/verify_demo_raster_workflow.sh, a browser-facing runtime smoke for the seededdemo_context_raster.tiffixture. - Added the new smoke to readiness syntax checks.
- Hardened
RasterOperationsService.tileso tile manifest bounds accept both Rasterio tuple bounds and object bounds. - Updated
backend/tests/test_raster_operations_service.pyto cover tuple-based window bounds. - Added
backend/tests/test_sprint98_raster_workflow_smoke.py. - Updated
scripts/README.mdandCHANGELOG.md.
Validation:
- RED:
python -m pytest backend\tests\test_sprint98_raster_workflow_smoke.py -qfailed before implementation becausescripts/verify_demo_raster_workflow.shdid not exist. python -m pytest backend\tests\test_sprint98_raster_workflow_smoke.py backend\tests\test_readiness_gate.py -qpassed: 14 tests.bash -n scripts/verify_demo_raster_workflow.shpassed.- Live diagnostic run of
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202showed inspect, preview and stats passed, then raster tile failed with HTTP 500. - Tower backend logs identified the root cause:
rasterio.windows.bounds(...)returned a tuple, while tile manifest generation expected.left/.bottom/.right/.topattributes. - RED:
python -m pytest backend\tests\test_raster_operations_service.py::test_raster_tile_returns_manifest_payload -qreproduced the liveAttributeErrorafter updating the fixture to tuple bounds. python -m pytest backend\tests\test_raster_operations_service.py::test_raster_tile_returns_manifest_payload backend\tests\test_sprint98_raster_workflow_smoke.py -qpassed: 2 tests.python -m compileall backend/apppassed.python -m pytest -qfrombackend/passed: 321 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed7b093c0to Tower on port 1202.bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202initially proved the tile fix but exposed the existing job terminal status convention assuccessrather thancompleted; the smoke now acceptssuccessandcompleted.bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202passed after the smoke status fix: inspect, preview, stats and raster tile manifest all succeeded.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed after redeploy.bash scripts/run_readiness_check.shpassed again after the smoke status update.
Limitations:
- The raster smoke creates a small tile set each run. It is appropriate for local/runtime validation, not high-volume benchmarking.
- The smoke intentionally does not run AI inference or external imagery/provider fetching.
Next recommended pass:
- Run full readiness, redeploy, then verify the raster smoke live against
http://192.168.10.150:1202.
Sprint 97 demo raster fixture workflow (2026-06-23)
Changed:
- Added
raster_dataset_idto the demo workflow response contract. - Extended
DemoWorkflowServicewith a deterministic in-memorydemo_context_raster.tifGeoTIFF fixture persisted throughStorageServiceand the existingdatasetstable as a readyraster/fixturesource dataset. - Updated the frontend demo workflow hook so Detection and Segmentation Labs receive the seeded raster dataset while the candidate vector remains selected for Data, Map and Export review.
- Updated default-state and interaction smokes to require candidate vector, reference vector and raster fixture datasets as
3/3 ready. - Updated
scripts/README.md,frontend/README.mdandCHANGELOG.md.
Validation:
- RED:
python -m pytest backend\tests\test_sprint97_demo_raster_fixture.py -qfailed before implementation because the demo schema/service and frontend hook did not expose or select a raster fixture. python -m pytest backend\tests\test_sprint97_demo_raster_fixture.py -qpassed: 2 tests.python -m compileall backend/apppassed.python -m pytest backend\tests\test_sprint97_demo_raster_fixture.py backend\tests\test_sprint15_demo_workflow.py backend\tests\test_sprint21_demo_workflow_smoke.py backend\tests\test_readiness_gate.py -qpassed: 21 tests.bash -n scripts/verify_workbench_default_state.shpassed.bash -n scripts/verify_workbench_interactions.shpassed.cd frontend && npm run typecheckpassed.python -m pytest backend\tests\test_sprint96_useful_default_context.py backend\tests\test_sprint39_frontend_orchestration_hooks.py -qpassed: 11 tests.python -m pytest -qfrombackend/passed: 320 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployedca730edto Tower on port 1202.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed and reportedDatasets: 3/3 ready.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed and verified candidate, reference and raster fixture datasets.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202passed.- Live API check confirmed
demo_context_raster.tifasraster/fixture/readywithEPSG:4326. - Chrome headless screenshot of
http://192.168.10.150:1202showed the populated Overview workspace, selected demo context and no obvious desktop horizontal overflow.
Limitations:
- The raster fixture is a tiny generated local GeoTIFF for V1 workflow validation only. It does not represent external imagery and does not enable real AI inference.
- No migrations, provider fetching, real YOLO/SAM behavior or product scope beyond the existing offline demo workflow changed.
- Optional
scripts/capture_workbench_screenshots.shcould not run in this Windows runner because Playwright is not installed; Chrome headless was used for the live visual check instead.
Next recommended pass:
- Continue with a focused raster operation happy-path smoke against the seeded raster fixture: inspect, preview, stats and tiling through the browser-facing API.
Sprint 48 Backend API contract audit (2026-06-17)
Changed:
- Added
scripts/audit_api_contracts.pyto import the FastAPI app, enumerate the implementedGET/POST/PATCH/DELETEroute surface and compare it with active### METHOD routeheadings indocs/API_CONTRACTS.md. - Added the API contract audit to
scripts/run_readiness_check.sh. - Corrected contract drift in
docs/API_CONTRACTS.md:- documented
GET/PATCH /api/v1/projects/{project_id}/areas/{area_id}; - corrected vector stats from
POSTto implementedGET; - documented
GET /api/v1/projects/{project_id}/datasets/{dataset_id}/content; - changed non-implemented building-stats, legacy analysis object-detection/segmentation and YOLO export entries from active route headings to future-route notes.
- documented
- Added
backend/tests/test_sprint48_api_contract_audit.py. - Updated
scripts/README.md,docs/TODO.mdandCHANGELOG.md.
Validation:
- RED:
cd backend && python -m pytest tests/test_sprint48_api_contract_audit.py -qfailed before implementation because the audit script, readiness integration and route docs were missing. - RED:
python scripts/audit_api_contracts.pyreported missing docs for 4 implemented routes and 5 stale documented routes. python scripts/audit_api_contracts.pypassed: 76 implemented routes matched docs and 2 explicit non-envelope endpoints were tracked.cd backend && python -m pytest tests/test_sprint48_api_contract_audit.py tests/test_readiness_gate.py -qpassed: 12 tests.python -m py_compile scripts/audit_api_contracts.pypassed.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 201 tests.bash scripts/run_readiness_check.shpassed and includedAPI contract audit OK.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed the all-in-one container to Tower on port 1202.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed after redeploy.
Limitations:
- This pass audits route documentation presence, implemented/stale route drift and explicit non-envelope exceptions. It does not yet exercise every error path response body at runtime.
- No API behavior, migrations, provider fetching, AI behavior or product capabilities changed.
Next recommended pass:
- Add an error-envelope runtime audit for representative invalid/missing-resource paths across projects, datasets, providers, detection, segmentation, QA and exports.
Sprint 47 Workbench interaction smoke (2026-06-17)
Changed:
- Added stable
data-testidanchors to the existing project, area, map, dataset, QA/QC and export controls so browser checks can target real controls instead of brittle text/layout selectors. - Added
scripts/verify_workbench_interactions.sh, a dependency-light runtime smoke that verifies the backing state for project switching, AOI/map selection, dataset selection, QA refresh and export refresh through the browser-facing API proxy. - Added the script syntax check to
scripts/run_readiness_check.sh. - Added
backend/tests/test_sprint47_workbench_interaction_smoke.pyto keep the UI anchors, readiness gate and interaction smoke contract in place. - Updated
scripts/README.md,docs/TODO.mdandCHANGELOG.md.
Validation:
- RED:
cd backend && python -m pytest tests/test_sprint47_workbench_interaction_smoke.py -qfailed before implementation because the UI anchors, readiness script reference and interaction smoke script were missing. cd backend && python -m pytest tests/test_sprint47_workbench_interaction_smoke.py -qpassed: 3 tests.cd frontend && npm run typecheckpassed.bash -n scripts/verify_workbench_interactions.shpassed.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed against the pre-deploy runtime API surface.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 198 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed the all-in-one container to Tower on port 1202.bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed after redeploy.- Live browser check against
http://192.168.10.150:1202passed using the new anchors: project, map, dataset, QA/QC and export panels were present; QA refresh and export metadata actions worked; latest export updated; no horizontal overflow was detected.
Limitations:
- The shell smoke validates the state behind the controls but does not click rendered controls by itself. The added
data-testidanchors are intended for Codex/browser click checks and future browser artifact automation. - No API contracts, migrations, provider fetching, AI behavior or product capabilities changed.
Next recommended pass:
- Add persisted screenshot artifact automation for the anchored browser pass, or move to a backend service contract audit if UI stabilization is sufficient.
Sprint 46 Workbench default-state smoke (2026-06-17)
Changed:
- Added
scripts/verify_workbench_default_state.sh, a dependency-light runtime smoke for the browser-facing workbench default demo state. - The smoke calls the offline demo workflow, then verifies
GeoIntel Demo - Building QA,Demo AOI - Geel buildings,2/2 readydatasets and a persisted QA/QC result through canonicaldata.itemsenvelopes. - Added the script syntax check to
scripts/run_readiness_check.sh. - Extended
backend/tests/test_readiness_gate.pyso the readiness gate and script keep covering the default-state smoke contract. - Updated
scripts/README.mdandCHANGELOG.md.
Validation:
- RED:
cd backend && python -m pytest tests/test_readiness_gate.py -qfailed before implementation becauseverify_workbench_default_state.shwas missing and readiness did not reference it. cd backend && python -m pytest tests/test_readiness_gate.py -qpassed: 9 tests.bash -n scripts/verify_workbench_default_state.shpassed.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 195 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed the all-in-one container to Tower on port 1202.bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed after redeploy.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed after redeploy.- Live browser check against
http://192.168.10.150:1202passed at 1280x720: selected projectGeoIntel Demo - Building QA, status showed1 area,2/2 readydatasets and2 checks, map workspace rendered and no horizontal overflow was detected.
Limitations:
- The committed smoke validates the connected default workbench state through HTTP/API contracts, not pixel layout. Browser screenshot and overflow validation remain a Codex/browser verification step.
- No API contracts, migrations, provider fetching, AI behavior or product capabilities changed.
Next recommended pass:
- Add a deeper browser interaction smoke for core controls, starting with project switching, area selection and map layer opacity.
Sprint 45 Default demo selection polish (2026-06-17)
Changed:
- Updated
frontend/src/hooks/useProjectWorkspace.tsso cold-start project selection preserves an existing selected project, honors an explicit preferred project and otherwise prefers a populated demo/workbench project over an empty first project. - New project creation now selects the newly created project immediately after creation.
- Updated
frontend/src/hooks/useDemoWorkflow.tsso demo seed refresh passes the seeded project id toloadProjects. - Extended orchestration tests to cover preferred demo selection and project creation selection behavior.
Validation:
cd backend && python -m pytest tests/test_sprint39_frontend_orchestration_hooks.py tests/test_sprint21_demo_workflow_smoke.py -qpassed: 11 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 194 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Browser check against local Vite preview with live backend passed after async settle: selected project
GeoIntel Demo - Building QA, status showed1 area,2/2 readydatasets and2 checks. powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployed the all-in-one container to Tower on port 1202.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.- Live browser check against
http://192.168.10.150:1202passed after async settle: selected projectGeoIntel Demo - Building QA, status showed1 area,2/2 readydatasets and2 checks, with no horizontal overflow.
Limitations:
- No API contracts, migrations, provider fetching, AI behavior or product capabilities changed.
- The heuristic probes up to eight project candidates on cold start; a future backend list endpoint with area/dataset counts would make this cleaner.
Next recommended pass:
- Add a lightweight browser regression script for the demo start page once the UI state is stable enough to automate end to end.
Sprint 44 Workbench UI polish pass (2026-06-17)
Changed:
- Reworked
frontend/src/styles/app.cssfrom a minimal browser-default stylesheet into a compact GIS workbench skin with modern controls, restrained neutral/green accents, scroll-contained long panels and responsive layout rules. - Promoted
MapWorkspaceabove the dense workflow grid infrontend/src/App.tsxso GIS context is visible before lower-detail provider, AI, QA and export panels. - Moved
DatasetPanelinto the first workflow row beside project/area/provider setup. - Added a static layout regression test in
backend/tests/test_sprint30_workbench_components.pyfor map-first ordering and scroll-contained workflow panels. - Updated frontend README and changelog.
Validation:
- Browser visual check against local Vite preview passed at desktop width: map-first layout visible, workflow panels scroll-contained, page height reduced from roughly 14.9k px to roughly 3.2k px.
- Browser responsive check at 390px width passed with no horizontal overflow.
python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 194 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployedgeointel-all-in-one:latestto Tower on port 1202.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.- Live browser check against
http://192.168.10.150:1202passed: map-first layout rendered, scroll height roughly 3.2k px and no desktop horizontal overflow detected.
Limitations:
- No API contracts, migrations, provider fetching, AI behavior or product capabilities changed.
- This is still a dense operational workbench rather than a designed product shell with navigation or tabs.
- The live default selected project can still be an empty project with the demo name; project selection polish remains a separate follow-up.
Next recommended pass:
- Add UI browser regression coverage for the map-first demo workflow and polish the default project/demo selection state.
Sprint 43 Workbench bootstrap hook decomposition (2026-06-17)
Changed:
- Moved frontend bootstrap, project-change reload/reset and detection/segmentation result reload effects from
frontend/src/App.tsxintofrontend/src/hooks/useWorkbenchBootstrap.ts. - Kept
App.tsxas a composition root that wires hook outputs into panels; it no longer importsuseEffect. - Extended orchestration tests so lifecycle side effects stay in the bootstrap hook.
- Updated frontend README, changelog and TODO status.
Validation:
cd backend && python -m pytest tests/test_sprint39_frontend_orchestration_hooks.py -qpassed: 9 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 193 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployedgeointel-all-in-one:latestto Tower on port 1202.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.App.tsxsize audit after extraction: 621 lines;useWorkbenchBootstrap.ts: 81 lines.
Limitations:
- No UX behavior, API contracts, migrations, provider fetching or AI behavior changed.
App.tsxline count remains high because it explicitly wires many panel props; the remaining size is primarily composition.
Next recommended pass:
- Pick the next V1 stabilization focus: UI browser regression coverage, backend service contract audit, or golden dataset expansion.
Sprint 42 App entrypoint cleanup (2026-06-17)
Changed:
- Removed the stale
FormEvent/useStateReact imports fromfrontend/src/App.tsx. - Removed the UTF-8 BOM from
App.tsxso patches and static checks use normal UTF-8 text. - Added a regression test that verifies the clean entrypoint encoding and React import set.
- Recorded the current
App.tsxsize audit: 622 lines after the orchestration hook decomposition passes.
Validation:
cd backend && python -m pytest tests/test_sprint39_frontend_orchestration_hooks.py -qpassed: 8 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 192 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployedgeointel-all-in-one:latestto Tower on port 1202.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.
Limitations:
- No UX behavior, API contracts, migrations, provider fetching or AI behavior changed.
App.tsxremains a large composition root; the remaining size is primarily panel wiring and hook outputs.
Next recommended pass:
- Optional bootstrap-effect extraction if another no-behavior size reduction is useful.
Sprint 41 Demo workflow hook decomposition (2026-06-17)
Changed:
- Moved offline demo workflow orchestration from
frontend/src/App.tsxintofrontend/src/hooks/useDemoWorkflow.ts. - Preserved the existing backend fixture seed flow and all cross-module selection updates for project, candidate/reference datasets, map AOI, QA/QC, detection, segmentation and exports.
- Extended static frontend orchestration tests so
demoApi.seedWorkflowis owned by the new hook and notApp.tsx. - Updated frontend README, changelog and TODO status.
Validation:
cd backend && python -m pytest tests/test_sprint21_demo_workflow_smoke.py tests/test_sprint39_frontend_orchestration_hooks.py -qpassed: 9 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 191 tests.bash scripts/run_readiness_check.shpassed.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.cd backend && python -m alembic headspassed:202606120900 (head).cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1passed and redeployedgeointel-all-in-one:latestto Tower on port 1202.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.
Limitations:
- No UX behavior, API contracts, migrations, provider fetching or AI behavior changed.
App.tsxstill has a UTF-8 BOM and a stale React import cleanup opportunity; TypeScript build is unaffected.
Next recommended pass:
- Do a final
App.tsxsize/import cleanup pass.
Sprint 40 Project workspace hook decomposition (2026-06-17)
Changed:
- Moved project list/create state, area create state and project-scoped area/dataset loading into
frontend/src/hooks/useProjectWorkspace.ts. - Kept demo workflow orchestration in
App.tsxbecause it coordinates project, dataset, QA/QC, detection, segmentation and export selections across multiple hooks. - Moved default clip-area fallback selection into
frontend/src/hooks/useDatasetWorkflow.ts. - Moved default map-area fallback selection into
frontend/src/hooks/useMapWorkspaceState.ts. - Extended static frontend orchestration tests to lock these ownership boundaries.
- Updated frontend README, changelog and TODO status.
Validation:
cd backend && python -m pytest tests/test_sprint39_frontend_orchestration_hooks.py -qpassed: 6 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 190 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic heads && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the all-in-one Tower container athttp://192.168.10.150:1202.- Tower live migration smoke passed and reported
Database collation version: ok. - Tower browser runtime verification passed.
bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.
Open:
- None for this pass.
Limitations:
- No UX behavior, API contracts, migrations, provider fetching or AI behavior changed.
- Demo workflow orchestration remains in
App.tsxuntil it can be safely split without obscuring cross-module state updates.
Next recommended pass:
- Run full readiness and Tower deploy verification, then consider extracting the demo workflow coordinator into a dedicated hook.
Sprint 39 Frontend orchestration decomposition (2026-06-17)
Changed:
- Moved provider capability loading state and
externalApi.listProviderscalls intofrontend/src/hooks/useProviderCapabilities.ts. - Moved change-detection state, validation and
analysisApi.runChangeDetectioncalls intofrontend/src/hooks/useChangeDetectionWorkflow.ts. - Moved map-layer derived state, area GeoJSON feature construction and selected-feature reset behavior into
frontend/src/hooks/useMapWorkspaceState.ts. - Kept
App.tsxas the cross-module composition layer without changing panel props, API contracts, migrations or product behavior. - Added static regression tests for the extracted orchestration hooks.
- Updated frontend README, changelog and TODO status.
Validation:
cd backend && python -m pytest tests/test_sprint39_frontend_orchestration_hooks.py -qpassed: 4 tests.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 188 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic heads && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the all-in-one Tower container athttp://192.168.10.150:1202.- Tower live migration smoke passed and reported
Database collation version: ok. - Tower browser runtime verification passed.
bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.
Open:
- None for this pass.
Limitations:
- Project/area/dataset cross-load orchestration still lives in
App.tsx; it is a good next low-risk decomposition target.
Next recommended pass:
- Run full readiness and Tower deploy verification, then extract project/area loading into a dedicated hook if behavior remains stable.
Sprint 38 Export Center preview hardening (2026-06-17)
Changed:
- Hardened the export content preview path so HTML report artifacts return
EXPORT_CONTENT_UNSUPPORTEDinstead of a generic JSON parse failure. - Updated the frontend Export Center to offer JSON preview only for JSON/GeoJSON artifacts.
- HTML project report artifacts now display as download-only in the export list.
- Extracted export preview rendering from
frontend/src/App.tsxintofrontend/src/components/exports/ExportPreview.tsx. - Updated API/frontend docs, changelog and TODO status.
Validation:
cd backend && python -m pytest tests/test_sprint17_export_foundation.py -qpassed: 10 tests.cd frontend && npm run typecheckpassed.python -m compileall backend/apppassed.cd backend && python -m pytest -W error::DeprecationWarningpassed: 184 tests.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed.cd backend && python -m alembic heads && python -m alembic upgrade head --sqlpassed.powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the all-in-one Tower container athttp://192.168.10.150:1202.- Tower live migration smoke passed and reported
Database collation version: ok. bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.
Open:
- None for this pass.
Limitations:
- This pass does not add new export formats, PDF reports, provider fetching, AI inference or migrations.
Next recommended pass:
- Run the full readiness gate, frontend build and Tower deploy smoke; then continue with shared workbench orchestration decomposition or export cleanup/history filtering.
Sprint 37 Tower PostgreSQL collation maintenance (2026-06-17)
Changed:
- Performed the manual PostgreSQL collation maintenance action reported by the live migration smoke on the Tower all-in-one runtime.
- Created a pre-maintenance custom-format database backup at
backups/geointel-before-collation-refresh-20260617-065707.dump. - Ran
REINDEX DATABASE geointel;followed byALTER DATABASE "geointel" REFRESH COLLATION VERSION;. - Confirmed the database collation metadata now matches the runtime collation version:
geointel stored=2.36 actual=2.36.
Validation:
LIVE_SMOKE_CONTAINER=geointel bash scripts/live_migration_smoke.shpassed on Tower and reportedDatabase collation version: ok.bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202passed.bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202passed.
Notes:
- An initial SSH script attempt was interrupted by PowerShell BOM/stdin handling before reindex or refresh executed; the subsequent base64-delivered script ran without
docker exec -istdin interference. - Earlier backup attempts were left in
backups/alongside the final validated backup. - No code, API contracts, migrations, product features, provider fetching or AI behavior changed.
Next recommended pass:
- Continue with export/download polish or frontend export center hardening, using the now-clean Tower runtime as the validation target.
Sprint 32 Unraid all-in-one runtime (2026-06-17)
Changed:
- Added
docker-compose.unraid.ymlfor a single editablegeointelcontainer on Unraid. - Added
deploy/unraid/Dockerfile.all-in-oneto build one image containing embedded PostGIS, backend GIS runtime, nginx and frontend static assets. - Added
deploy/unraid/all-in-one-start.shto start embedded PostGIS, apply Alembic migrations, start FastAPI on internal localhost and serve nginx on container port 80. - Added
deploy/unraid/nginx-all-in-one.confso/apiand/healthproxy to127.0.0.1:8000inside the same container. - Updated
deploy/unraid/geointel.env.example, Unraid XML template and README for one-container operation and editable web/storage/database paths. - Updated Tower deploy scripts to stop the old multi-container stack without deleting volumes and start
docker-compose.unraid.yml. - Updated
scripts/live_migration_smoke.shto support both all-in-onegeointeland legacybackendCompose services. - Added root
.dockerignorefor all-in-one builds. - Updated Sprint 31 tests to cover the all-in-one Dockerfile, startscript, nginx config, deploy scripts and template metadata.
Validation:
python -m pytest backend/tests/test_sprint31_unraid_template.py backend/tests/test_live_migration_smoke_script.py backend/tests/test_docker_runtime_config.pypassed: 26 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.python -m compileall backend/apppassed.cd backend && python -m pytestpassed: 179 tests.bash scripts/run_readiness_check.shpassed: 179 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.cd backend && python -m alembic headspassed: single head202606120900.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.bash -n deploy/unraid/all-in-one-start.shpassed.
Notes:
- No API contracts, migrations, product features, provider fetching or AI behavior changed.
- Local Windows environment does not have
dockerin PATH; Tower deployment should provide the live all-in-one Docker validation.
Sprint 31 Unraid deployment template (2026-06-17)
Changed:
- Made
docker-compose.ymlconfigurable through.envdefaults for frontend port, backend port, storage path, PostGIS database/user/password, CORS origins and upload limit. - Added
deploy/unraid/geointel.env.examplefor Unraid/Tower runtime configuration. - Added
deploy/unraid/geointel-unraid-template.xmlas Unraid/DockerMan-style metadata for the editable Compose stack settings. - Added
deploy/unraid/geointel-icon.svganddeploy/unraid/geointel-icon.png, served through matchingfrontend/publicassets. - Added the frontend favicon link for the GeoIntel icon.
- Added Sprint 31 tests for Unraid template coverage, compose variable coverage, docs and icon availability.
- Updated root README, TODO and changelog docs.
Validation:
python -m pytest backend/tests/test_sprint31_unraid_template.py backend/tests/test_docker_runtime_config.pypassed: 22 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.python -m compileall backend/apppassed.cd backend && python -m pytestpassed: 177 tests.bash scripts/run_readiness_check.shpassed: 177 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.cd backend && python -m alembic headspassed: single head202606120900.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Tower deploy via
scripts/deploy_tower.ps1passed after commit3a8b82f. - Tower Docker Compose config/build/up passed with the env-default compose file.
- Tower live migration smoke passed with PostGIS 3.4 and Alembic head
202606120900. - Tower browser runtime verification passed on
http://192.168.10.150:1202. - Additional HTTP smoke passed for frontend HTML,
GET /api/v1/projects,/geointel-icon.svgand/geointel-icon.png.
Notes:
- Local Windows environment does not have
dockerin PATH, so localdocker compose configcould not be run from this machine. - Tower deployment validated Docker Compose config and live runtime after commit.
- No API contracts, backend behavior, migrations, product features, provider fetching or AI behavior changed.
Sprint 30 workbench component decomposition (2026-06-17)
Changed:
- Moved persisted QA/QC result rendering from
frontend/src/App.tsxintofrontend/src/components/quality/QualityResultsPanel.tsx. - Moved map layer controls, MapLibre composition and feature inspector rendering into
frontend/src/components/map/MapWorkspace.tsx. - Updated map/workbench and QA regression tests for the new component boundaries.
- Added Sprint 30 component wiring tests to keep QA and map markup out of
App.tsx. - Updated frontend README, TODO and changelog docs.
Validation:
python -m pytest backend/tests/test_sprint30_workbench_components.py backend/tests/test_sprint27_frontend_workflow_hooks.py backend/tests/test_sprint19_map_workbench.pypassed: 9 tests.python -m compileall backend/apppassed.cd backend && python -m pytestpassed: 173 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 173 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.cd backend && python -m alembic headspassed: single head202606120900.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Tower deploy via
scripts/deploy_tower.ps1passed after commitacf9590. - Tower live migration smoke passed with PostGIS 3.4 and Alembic head
202606120900. - Tower browser runtime verification passed on
http://192.168.10.150:1202. - Additional HTTP smoke passed for frontend HTML and
GET /api/v1/projectsthrough the frontend proxy.
Notes:
- No API contracts, backend behavior, migrations, product features, provider fetching, AI behavior or UI redesign changed.
- Next maintainability pass should split export preview and remaining shared workbench orchestration into focused components/hooks.
Sprint 29 dataset component decomposition (2026-06-17)
Changed:
- Moved dataset upload/list rendering from
frontend/src/App.tsxintofrontend/src/components/datasets/DatasetPanel.tsx. - Moved dataset detail and job-list rendering into
frontend/src/components/datasets/DatasetDetailPanel.tsx. - Split raster controls and vector controls into
frontend/src/components/datasets/RasterControls.tsxandfrontend/src/components/datasets/VectorControls.tsx. - Updated Sprint 28 regression tests for the new component boundary and added Sprint 29 component wiring tests.
- Updated frontend README, TODO and changelog docs.
Validation:
python -m pytest backend/tests/test_sprint29_dataset_components.py backend/tests/test_sprint28_dataset_workflow_hook.py backend/tests/test_sprint27_frontend_workflow_hooks.pypassed: 10 tests.python -m compileall backend/apppassed.cd backend && python -m pytestpassed: 170 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 170 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.cd backend && python -m alembic headspassed: single head202606120900.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Tower deploy via
scripts/deploy_tower.ps1passed after commit1cbb356. - Tower live migration smoke passed with PostGIS 3.4 and Alembic head
202606120900. - Tower browser runtime verification passed on
http://192.168.10.150:1202. - Additional HTTP smoke passed for frontend HTML and
GET /api/v1/projectsthrough the frontend proxy.
Notes:
- No API contracts, backend behavior, migrations, product features, provider fetching, AI behavior or UI redesign changed.
- Next maintainability pass should split change detection, QA/QC results and map workspace controls into focused presentational components.
Sprint 28 dataset workflow hook hardening (2026-06-17)
Changed:
- Moved dataset selection, upload form state, dataset detail loading, dataset jobs and raster/vector operation orchestration from
frontend/src/App.tsxintofrontend/src/hooks/useDatasetWorkflow.ts. - Kept project dataset listing in
App.tsxso project/area loading remains the shared workbench boundary. - Added regression tests to verify App uses the dataset workflow hook and still wires dataset, raster and vector callbacks.
- Updated frontend README, TODO and changelog docs.
Validation:
python -m pytest backend/tests/test_sprint28_dataset_workflow_hook.py backend/tests/test_sprint27_frontend_workflow_hooks.py backend/tests/test_sprint26_frontend_workflow_hooks.pypassed: 11 tests.python -m compileall backend/apppassed.cd backend && python -m pytestpassed: 167 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 167 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.cd backend && python -m alembic headspassed: single head202606120900.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Initial Tower rebuild hit Docker btrfs storage exhaustion; safely reclaimed build cache only with
docker builder prune -afwithout pruning volumes. - Tower Docker storage recovered from
/var/lib/docker94% used to 58% used after cleanup and rebuild. - Tower deploy via
scripts/deploy_tower.ps1passed after commit361776c. - Tower live migration smoke passed with PostGIS 3.4 and Alembic head
202606120900. - Tower browser runtime verification passed on
http://192.168.10.150:1202. - Additional HTTP smoke passed for frontend HTML and
GET /api/v1/projectsthrough the frontend proxy.
Notes:
- No API contracts, backend behavior, migrations, product features, provider fetching, AI behavior or UI redesign changed.
- Next maintainability pass should split dataset detail, raster controls and vector controls into presentational components fed by the hook state.
Sprint 27 export and QA workflow hook hardening (2026-06-17)
Changed:
- Moved Export Center orchestration state and API calls from
frontend/src/App.tsxintofrontend/src/hooks/useExportWorkflow.ts. - Moved QA/QC comparison state and persisted quality-check listing from
frontend/src/App.tsxintofrontend/src/hooks/useQualityWorkflow.ts. - Added regression tests to verify App uses export/quality hooks and still wires QA/QC results plus ExportCenter callbacks.
- Updated frontend README, TODO and changelog docs.
Validation:
python -m pytest backend/tests/test_sprint27_frontend_workflow_hooks.py backend/tests/test_sprint26_frontend_workflow_hooks.pypassed: 8 tests.python -m compileall backend/apppassed.cd backend && python -m pytestpassed: 164 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 164 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.cd backend && python -m alembic headspassed: single head202606120900.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Tower deploy via
scripts/deploy_tower.ps1passed after commitfd0000f. - Tower live migration smoke passed with PostGIS 3.4 and Alembic head
202606120900. - Tower browser runtime verification passed on
http://192.168.10.150:1202. - Additional HTTP smoke passed for frontend HTML and
GET /api/v1/projectsthrough the frontend proxy.
Notes:
- No API contracts, backend behavior, migrations, product features, provider fetching, AI behavior or UI redesign changed.
- Local Windows Docker CLI was unavailable (
dockercommand not found); Tower deployment remains handled throughscripts/deploy_tower.ps1. - Next maintainability pass should extract dataset/raster/vector operation workflows from
App.tsx.
Sprint 26 frontend workflow hook hardening (2026-06-17)
Changed:
- Moved Detection Lab orchestration state and API calls from
frontend/src/App.tsxintofrontend/src/hooks/useDetectionWorkflow.ts. - Moved Segmentation Lab orchestration state and API calls from
frontend/src/App.tsxintofrontend/src/hooks/useSegmentationWorkflow.ts. - Added shared frontend
formatErrorhelper underfrontend/src/lib/formatError.ts. - Added regression tests to verify App uses workflow hooks and still wires DetectionLab/SegmentationLab callbacks.
- Updated frontend README, TODO and changelog docs.
Validation:
python -m pytest backend/tests/test_sprint26_frontend_workflow_hooks.py backend/tests/test_sprint22_workbench_status_strip.pypassed: 6 tests.cd frontend && npm run typecheckpassed.cd frontend && npm run buildpassed.bash scripts/run_readiness_check.shpassed: 160 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.python -m compileall backend/apppassed.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Tower deploy/live migration/browser runtime passed after commit
6c32f29. - In-app browser check passed on
http://192.168.10.150:1202: workbench, status strip, Detection Lab, Segmentation Lab and Export Center visible with no console error logs.
Notes:
- No API contracts, backend behavior, migrations, product features, provider fetching, AI behavior or UI redesign changed.
Sprint 25 YOLO compatibility smoke hardening (2026-06-17)
Changed:
- Added explicit
--check-model-loadsupport toscripts/yolo_preflight.py,backend/scripts/yolo_preflight.pyandYoloPreflightService. - The model-load smoke requires real optional AI dependencies, loads only an existing local model file, runs no inference and does not download weights.
- The CLI rejects
--check-model-loadwith--assume-dependenciesto avoid false-positive AI readiness. - Added regression tests for mocked successful load, load failure reporting and CLI guard behavior.
- Added Python compile validation for both YOLO preflight entrypoints to the readiness gate.
- Updated AI pipeline, scripts, backend, TODO and changelog docs, including Docker runtime usage.
Validation:
python -m py_compile scripts/yolo_preflight.pypassed.python -m pytest backend/tests/test_sprint13_yolo_preflight.py backend/tests/test_readiness_gate.pypassed: 14 tests.bash scripts/run_readiness_check.shpassed: 156 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.python -m compileall backend/apppassed.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shpassed.- Tower deploy/live migration/browser runtime passed after commit
6c32f29. - In-app browser check passed on
http://192.168.10.150:1202: workbench, status strip, Detection Lab, Segmentation Lab and Export Center visible with no console error logs. - Tower deploy/live migration/browser runtime passed after commit
382dcad. - Backend-container YOLO preflight sanity passed: default status
not_configured,will_download_models=false,will_run_inference=false. - Backend-container CLI guard passed:
--check-model-loadwith--assume-dependenciesis rejected.
Notes:
- No base dependencies, API contracts, migrations, product features, provider fetching or detection persistence behavior changed.
Sprint 24 demo/export artifact cleanup tooling (2026-06-17)
Changed:
- Added
scripts/cleanup_demo_artifacts.pyfor dry-run-first cleanup of old offline demo export artifacts. - Added
backend/scripts/cleanup_demo_artifacts.pyso the same cleanup can run inside the backend Docker container. - Cleanup is constrained to an exact demo project name by default, keeps the newest exports per project and refuses file deletion outside
STORAGE_ROOT. - Added regression tests for cleanup selection, path safety, dry-run candidate reporting and readiness gate coverage.
- Added Python compile validation for the cleanup script to
scripts/run_readiness_check.sh. - Documented cleanup usage in
scripts/README.md,docs/STORAGE_ARCHITECTURE.md,backend/README.md,docs/TODO.mdandCHANGELOG.md.
Validation:
python -m py_compile scripts/cleanup_demo_artifacts.pypassed.python -m pytest backend/tests/test_sprint24_cleanup_demo_artifacts.py backend/tests/test_readiness_gate.pypassed: 10 tests.bash scripts/run_readiness_check.shpassed twice after adding the backend container entrypoint: 152 backend tests, frontend typecheck/build, Alembic head check and script syntax checks.python -m compileall backend/apppassed.cd backend && python -m alembic upgrade head --sqlpassed.bash -n scripts/live_migration_smoke.shandbash -n scripts/verify_demo_export_workflow.shpassed.- Local
docker compose configcould not run because the Windows Docker CLI is not installed in this Codex environment. - Tower deploy/live migration/browser runtime passed after final commit
2d4e6bd. - Live backend-container cleanup dry-run exposed and then fixed confusing dry-run labeling so candidates are reported as
candidate_files, notdeleted_files; final dry-run reported 2 candidate files, 0 deleted files and 0 deleted export rows.
Notes:
- No API contracts, migrations, product features, provider fetching, AI inference or source dataset cleanup behavior changed.
Sprint 23 V1 report handoff summary (2026-06-17)
Changed:
- Added V1 readiness summary data to project metadata exports.
- Added V1 Readiness Summary and Known Limitations sections to lightweight HTML project report exports.
- Included persisted AOI, dataset readiness, QA/QC and export-history counts in the handoff summary.
- Updated export tests, API contract docs, frontend README, TODO and changelog.
Tested:
- Passed: backend compile, export tests through full readiness, full backend pytest, frontend typecheck/build, Alembic heads, Alembic SQL upgrade, live smoke syntax check, Tower deploy, live migration smoke and live project report smoke.
Known limitations:
- Report export remains a lightweight HTML artifact, not a PDF designer or custom report builder.
Next recommended pass:
- Add optional cleanup tooling for stale demo/export artifacts if repeated smoke runs keep accumulating local artifacts.
Sprint 22 V1 workbench status strip (2026-06-17)
Changed:
- Added
frontend/src/components/WorkbenchStatusStrip.tsxto summarize existing V1 state for project, AOI, datasets, active map layer, QA/QC and exports. - Wired the status strip into
frontend/src/App.tsxusing existing orchestration state only. - Added compact status-strip styling and regression tests for the frontend wiring contract.
n- Hardenedfrontend/src/components/GeoMap.tsxso MapLibre source/layer updates wait for style readiness before adding sources.n- Hardened demo project lookup so duplicate historical demo projects prefer complete fixture state before repairing incomplete state. - Updated frontend README, TODO and changelog.
Tested:
- Passed: backend compile, focused pytest, full backend pytest with DeprecationWarning as error, frontend typecheck/build, Alembic heads, Alembic SQL upgrade, readiness via Git Bash and live smoke syntax check via Git Bash.
Known limitations:
- The strip is a read-only operator summary; it intentionally does not add new backend status APIs or product workflows.
Next recommended pass:
- Add a compact project handoff summary in exports/report output if the browser-facing V1 workflow remains green.
Sprint 21 V1 demo workflow smoke hardening (2026-06-17)
Changed:
- Hardened
scripts/verify_demo_export_workflow.shso the explicit offline demo smoke validates area GeoJSON, fixture datasets, vector FeatureCollection content, vector feature summaries, persisted QA/QC metrics and export downloads through the frontend proxy. - Updated the frontend demo workflow action to open the candidate vector fixture dataset after seeding/loading the demo, so the Map Workbench is populated without a manual dataset click.
- Added regression tests for the strengthened smoke script and frontend demo loading contract.
- Updated scripts/frontend documentation, changelog and TODO status.
Tested:
- Passed: backend compile, backend pytest with DeprecationWarning as error, readiness, frontend typecheck/build, Alembic heads, Alembic SQL upgrade, Tower deploy, live migration smoke, browser-runtime smoke and expanded demo/export workflow smoke.
Known limitations:
- The demo smoke intentionally seeds fixture demo data when run; it should be used as an explicit verification command, not as an implicit healthcheck.
Next recommended pass:
- Add a compact V1 dashboard/status strip for project, AOI, datasets, QA and exports so operators can see readiness at a glance after opening a project.
Sprint 20 V1 selected area map overlay (2026-06-17)
Changed:
- Added GeoJSON geometry serialization for project areas so persisted AOIs can be displayed by the map workbench.
- Added a dedicated MapLibre area overlay layer with separate visibility and opacity controls.
- Added area list actions and map workspace controls to select the active AOI.
- Updated API/frontend docs, changelog and TODO status for selected area display.
Tested:
- Passed: backend compile, backend pytest with DeprecationWarning as error, readiness, frontend typecheck/build, Alembic heads, Alembic SQL upgrade, Tower deploy, live migration smoke, browser-runtime smoke and browser UI audit.
Known limitations:
- Area geometry is displayed as a simple filled/outlined GeoJSON overlay; no drawing/editing workflow is introduced in this pass.
Next recommended pass:
- Add a small V1 workflow polish pass for richer dataset/area empty states and a fixture-driven end-to-end browser smoke once the new build is deployed.
Sprint 19 V1 map workbench controls (2026-06-17)
Changed:
- Added active MapLibre layer visibility and opacity controls.
- Added click-to-inspect feature property display for the active GeoJSON workbench layer.
- Added active layer label and feature count to the Map workspace panel.
- Updated the app header from the stale Sprint 9 label to the GeoIntel Kempen V1 Workbench identity.
- Added regression tests for the frontend map control and feature inspection wiring.
Limitations:
- The current workbench still shows one active GeoJSON overlay at a time; multi-layer stack ordering remains a later UI enhancement.
- Raster preview display still remains metadata/path-oriented unless the backend exposes a browser-safe raster image/tile URL.
- No API contracts, migrations, backend behavior, provider fetching, AI inference or new dependencies were introduced.
Validation planned:
python -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shvia Git Bash on Windows- Tower redeploy through
scripts/deploy_tower.ps1
Sprint 18 vector change detection foundation (2026-06-16)
Changed:
- Added
POST /api/v1/analysis/change-detectionfor comparing two vector datasets in the same project through the existing synchronous job envelope. - Added
ChangeDetectionServicewith persistedvector_featuresas the primary source of comparable geometries and explicit stored-GeoJSON fallback warnings for older datasets. - Added frontend Change Detection controls, summary counts and MapLibre overlay styling for
added,removedandunchangedfeature properties. - Added nginx no-cache headers for frontend HTML/assets after browser verification exposed stale cached modules on the LAN deployment.
- Added backend tests for persisted-vector comparison and canonical API envelope behavior.
Limitations:
- The foundation classifies
added,removedandunchangedonly. It does not emit fakechangedobjects without durable object ids/versioning. - No migrations, live GRB/OSM/Sentinel fetching, AI inference, new dependencies, LiDAR, Copilot, Training Studio or separate Reports module were introduced.
Validation:
python -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shvia Git Bash on Windowscd backend && python -m alembic heads && python -m alembic upgrade head --sql
Codex Execution Log
This file must be updated by Codex after each implementation pass.
Format
## Pass X — Title
Date:
### Completed
- ...
### Files changed
- ...
### Tests run
- ...
### Known limitations
- ...
### Next recommended pass
- ...
Initial status
Specification phase completed through M0. No code foundation has been implemented yet.
M2 Engineering Package
- Add ADR decision records.
- Add RFC placeholders for future modules.
- Add API/database/event contracts.
- Add model registry and class catalogs.
- Add queue architecture.
- Add acceptance matrix and test catalog.
- Add Codex M2 build prompts.
- Start Codex Pass 01 backend foundation.
M8 preparation
Added the tomorrow execution layer for Codex autonomy: Day 1 master prompt, pass prompts, failure recovery, quality gates, operator checklist and smoke script scaffold.
Sprint 1 readiness hardening (2026-06-11)
Date: 2026-06-11
Completed
- Hardened backend dependency declarations for Sprint 1 runtime modules in
backend/pyproject.toml. - Normalized helper scripts for backend/frontend install/test/dev/readiness across
python/python3interpreter availability. - Fixed PostGIS/geospatial stack compatibility issues (
geojson_serviceimport path, package config). - Updated backend/frontend/docs/readme commands for import smoke, setup, and readiness verification.
- Fixed frontend shell script line-ending parsing failures and added
npmavailability checks. - Added missing frontend type path fixes and TypeScript typing corrections.
- Added/verified minimal Sprint 1 tests for health and GeoJSON parsing/rejection behaviors.
Files changed
backend/pyproject.tomlbackend/app/core/config.pybackend/app/services/geojson_service.pybackend/tests/test_health.pybackend/tests/test_geojson_dataset_service.pybackend/README.mdfrontend/package.jsonfrontend/tsconfig.jsonfrontend/src/components/GeoMap.tsxfrontend/src/services/api/areas.tsfrontend/src/services/api/projects.tsfrontend/src/services/api/datasets.tsfrontend/src/App.tsxfrontend/README.mdscripts/run_readiness_check.shscripts/backend_install.shscripts/backend_test.shscripts/backend_dev.shscripts/codex_pass_end_check.shscripts/smoke_backend_import.shscripts/frontend_install.shscripts/frontend_typecheck.shscripts/frontend_build.shscripts/frontend_dev.shREADME.md.env.exampleCHANGELOG.mdMakefile
Tests run
python -m compileall backend/app(pass)cd backend; python -m pytest(pass, 5 tests)cd backend; python -c "from app.main import app; print(app.title)"(pass)bash scripts/run_readiness_check.sh(pass)bash scripts/smoke_backend_import.sh(pass)bash scripts/frontend_install.sh(pass)bash scripts/frontend_typecheck.sh(pass)bash scripts/frontend_build.sh(pass)make-based targets not runnable in this environment (makecommand missing)docker compose confignot runnable in this environment (dockercommand missing)python3commands fail in this environment becausepython3maps to Microsoft Store stub; usepythoninstead.
Known limitations
dockerandmakeare not installed in the current local shell environment.python3is not a usable interpreter in this environment;pythonmust be used for all backend runtime/tests.
Next recommended pass
- Run
docker composevalidation and DB-backed migration checks in an environment with Docker + PostGIS service available.
Pass 12 — Sprint 2 Foundation
Date: 2026-06-11
Completed
- Added vector/raster dataset typing and lifecycle states (
uploaded,validating,ready,failed) in dataset service. - Added vector metadata extraction details (feature counts, geometry types, bounds, area, CRS assumptions).
- Added raster metadata service with dependency-aware unavailable behavior and explicit
RASTER_PROCESSING_UNAVAILABLEhandling. - Added dataset vector inspect/summary and raster metadata endpoints for project-scoped datasets.
- Persisted deterministic storage metadata for uploads (original/stored filename, MIME, size, checksum).
- Extended frontend dataset manager details panel with type/status/file metadata/feature counts and raster summary readiness.
- Added minimal Sprint 2 tests for vector metadata, legacy
geojsoncompatibility, storage metadata persistence, and raster dependency fallback.
Files changed
backend/app/services/dataset_service.pybackend/app/services/raster_service.pybackend/app/services/geojson_service.pybackend/app/schemas/dataset.pybackend/app/api/routes/datasets.pybackend/app/services/storage_service.pybackend/tests/test_geojson_dataset_service.pybackend/tests/test_raster_service.pybackend/tests/test_storage_service.pybackend/README.mdfrontend/src/App.tsxfrontend/src/services/api/datasets.tsfrontend/src/types.tsdocs/API_CONTRACTS.mddocs/CODEX_EXECUTION_LOG.md.env.examplebackend/README.mdfrontend/README.mdCHANGELOG.mdREADME.md
Tests run
- Sprint 2 tests to be executed via readiness commands (see below).
Known limitations
rasteriois not required by default; raster metadata extraction is unavailable until installed in the environment.- Docker and PostGIS validation still depends on local availability of Docker/DB runtime.
Next recommended pass
- Keep Sprint 1/2 architecture; implement raster clipping/tiling APIs and status jobs before Detection/Segmentation modules.
Pass 13 — Sprint 2 validation and legacy compatibility hardening
Date: 2026-06-11
Completed
- Verified Sprint 2 readiness commands in current environment (where tools are available).
- Revalidated backend tests and frontend typecheck/build after a Sprint 2 compatibility patch.
- Added frontend vector-detail compatibility for legacy
geojsondataset rows in Sprint 1 records. - Confirmed backend import smoke and dataset/raster/vector service behavior remain intact.
Files changed
frontend/src/App.tsxdocs/CODEX_EXECUTION_LOG.md
Tests run
python -m compileall backend/app(pass)cd backend && python -m pytest(pass, 11 tests)bash scripts/run_readiness_check.sh(pass)bash scripts/smoke_backend_import.sh(pass)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass)cd backend; python3 -m compileall backend/app(fails: python3 shim unavailable in this shell)cd backend; python3 -c "from app.main import app; print(app.title)"(fails: python3 shim unavailable in this shell)docker compose config(fails: docker command unavailable in this shell)
Known limitations
python3is not available in the current environment; usepythoncommands for verification.dockeris not available in the current environment.
Next recommended pass
- Run the same sprint verification commands in an environment with
python3anddockerinstalled.
Pass 14 — Sprint 3 operations + job foundation
Date: 2026-06-11
Completed
- Added lightweight job model/migration and service layer with statuses
queued,running,success,failed. - Added job API endpoints for create/list/read/status under project scope.
- Added vector operation service foundation:
- inspect
- bbox
- stats
- clip by area
- buffer
- intersect
- Added raster operation foundation:
- inspect
- metadata
- preview readiness
- clip placeholder (dependency-aware)
- tile placeholder (dependency-aware)
- Added job-based execution wrappers for vector/raster operation endpoints.
- Updated dataset detail UI with available operations, job list/status, and derived output navigation.
- Added/updated Sprint 3 API contract and backend/frontend documentation updates.
Files changed
backend/app/schemas/operations.pybackend/app/schemas/__init__.pybackend/app/services/vector_operations_service.pybackend/app/services/raster_operations_service.pybackend/app/services/job_service.pybackend/app/api/routes/jobs.pybackend/app/models/entities.pybackend/app/models/__init__.pybackend/alembic/versions/20260611212435_add_jobs_table.pybackend/tests/test_vector_operations_service.pybackend/tests/test_raster_operations_service.pybackend/tests/test_storage_service.pyfrontend/src/App.tsxfrontend/src/services/api/datasets.tsfrontend/src/services/api/jobs.tsfrontend/src/types.tsbackend/README.mdfrontend/README.mddocs/API_CONTRACTS.mddocs/CODEX_EXECUTION_LOG.mdCHANGELOG.md
Tests run
python -m compileall backend/app(pass)cd backend && python -m pytest(pass)bash scripts/run_readiness_check.sh(pass)bash scripts/smoke_backend_import.sh(pass)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass)
Known limitations
- Raster processing beyond readiness/metadata is intentionally dependency-aware placeholder in Sprint 3.
dockerremains unavailable in this environment.python3still resolves to Windows Store stub; usepythonfor verification.
Next recommended pass
- Install rasterio/GDAL for real raster clipping/tile implementations.
- Add queue-backed worker (Redis/RQ) behind existing synchronous job facade.
- Add deeper operation acceptance tests for output dataset geometry correctness and persisted metadata.
Pass 15 — Sprint 4 raster foundation
Date: 2026-06-11
Completed
- Finalized dependency-aware raster processing behavior for clip/tile/preview and improved metadata enrichment.
- Ensured raster metadata and preview responses include deterministic file metadata (
size_bytes,checksum_sha256,path) where available. - Added raster tile manifest generation with deterministic storage paths and returned manifest payload.
- Updated API contracts and execution documentation from placeholder wording to actual raster-op foundations.
- Added targeted Sprint 4 tests for missing-area clip behavior and tile manifest payload shape.
Files changed
backend/app/services/raster_operations_service.pybackend/app/api/routes/health.pybackend/tests/test_raster_operations_service.pydocs/API_CONTRACTS.mddocs/CODEX_EXECUTION_LOG.mdbackend/README.mdfrontend/README.mdREADME.mdCHANGELOG.md
Tests run
python -m compileall backend/appcd backend && python -m pytestbash scripts/run_readiness_check.shbash scripts/smoke_backend_import.shcd frontend && npm run typecheckcd frontend && npm run build
Known limitations
- Raster dependency packages remain optional and will report
RASTER_PROCESSING_UNAVAILABLEif absent. - Raster clip/tile remain synchronous under the current in-process job wrapper.
Next recommended pass
- Run full raster end-to-end tests with real GeoTIFF fixtures and validate output dataset metadata persistence.
Pass 16 � Sprint 4 raster operations foundation hardening
Date: 2026-06-11
Completed
- Realized the Sprint 4 raster foundation readiness in implementation and docs alignment:
- metadata extraction now returns real raster profile fields when rasterio is available
- preview generation writes deterministic PNG artifacts and reuses cached previews
- clip and tile operations persist deterministic outputs and manifest structure
- all raster processing paths now use explicit dependency-aware errors when rasterio/numpy/pillow are missing
- Fixed remaining frontend render/type issues introduced during raster path handling.
- Strengthened raster tests for tile manifest minimum size and dependency-aware behavior.
- Updated sprint milestone docs to reflect Sprint 4 status:
backend/README.mdfrontend/README.md
Files changed
backend/app/services/raster_operations_service.pybackend/tests/test_raster_operations_service.pybackend/app/api/routes/datasets.pybackend/app/schemas/operations.pyfrontend/src/App.tsxbackend/README.mdfrontend/README.mddocs/CODEX_EXECUTION_LOG.md
Tests run
python -m compileall backend/app(pass)cd backend && python -m pytest(pass, 26 tests)bash scripts/run_readiness_check.sh(pass)bash scripts/smoke_backend_import.sh(pass)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass)
Known limitations
dockercommand is unavailable in this environment, sodocker compose configcould not be executed.python3command is unavailable as an alias in this environment; usepythoninstead.- Full raster dependency stack may be unavailable in some dev environments; those cases intentionally return structured
RASTER_PROCESSING_UNAVAILABLEresponses.
Next recommended pass
- Sprint 5: add end-to-end RasterOps coverage for CRS-preserving re-projection, export-quality metadata policy, and tile set artifact cleanup lifecycle.
Pass 17 — Sprint 5 raster analytics hardening
Date: 2026-06-11
Completed
- Implemented Sprint 5 raster analytics foundation:
- band statistics endpoint and service with dependency-aware unavailable mode.
- reproject operation with CRS validation and reprojection metadata persistence.
- clip/tile hardening for missing/invalid geometry and empty clip output handling.
- enriched tile manifest fields (
tile_set_id,tile_size,overlap,source_dataset_id,source_raster_id,bounds,count,tile_paths,ai_inference,tile_server,created_at, parameters).
- Updated raster stats/job error tests:
- dependency-aware stats failure coverage.
- invalid CRS request validation for reproject.
- persisted derived dataset assertions for reproject and clip.
- failure persistence test for failed raster jobs (
_run_job_sync).
- Strengthened raster frontend detail panel rendering:
- job result JSON is visible for raster/vector operations.
- clearer raster metadata/status visibility retained for CRS/bounds/resolution display.
- Updated docs:
- backend/README Sprint 5 section.
- frontend/README Sprint 5 section.
- CHANGELOG entry for Sprint 5.
Files changed
backend/app/services/raster_operations_service.py(final reproject and manifest hardening alignment)backend/tests/test_raster_operations_service.pyfrontend/src/App.tsxbackend/README.mdfrontend/README.mddocs/API_CONTRACTS.mddocs/RASTER_OPERATIONS_SPEC.mddocs/CODEX_EXECUTION_LOG.mdCHANGELOG.md
Tests run
python -m compileall backend/app(pass)cd backend && python -m pytest(pass)bash scripts/run_readiness_check.sh(pass)bash scripts/smoke_backend_import.sh(pass)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass)
Known limitations
- Raster statistics and reproject operations still depend on environment availability of
rasterio/numpy. - Raster dependency checks and operation errors remain dependency-aware when libraries are unavailable.
Next recommended pass
- Sprint 6: add raster index/mask workflows (NDVI/NDWI/NDBI), tile serving or export packaging, and AI-ready dataset linking.
Pass 18 - Sprint 6 spectral indices
Completed
- Added local raster index operations (
ndvi,ndwi,ndbi) under the existing raster operation architecture. - Added typed band payload validation and explicit
INVALID_PARAMETERShandling for missing/invalid band indexes. - Implemented dependency-aware failure behavior for index execution (
RASTER_PROCESSING_UNAVAILABLE) whenrasterioornumpyare unavailable. - Implemented local index output generation with float32 raster derivation and persisted provenance metadata on derived datasets.
- Extended dataset detail UI with spectral index controls (NDVI/NDWI/NDBI), run actions, and output dataset navigation from jobs.
- Updated API contracts, raster operation spec, and project documentation for Sprint 6 behavior.
Files changed
backend/app/schemas/operations.pybackend/app/services/raster_operations_service.pybackend/app/api/routes/datasets.pybackend/tests/test_raster_operations_service.pyfrontend/src/services/api/datasets.tsfrontend/src/App.tsxfrontend/src/types.tsdocs/API_CONTRACTS.mddocs/RASTER_OPERATIONS_SPEC.mdbackend/README.mdfrontend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Tests run
python -m compileall backend/appcd backend && python -m pytestbash scripts/run_readiness_check.shbash scripts/smoke_backend_import.shcd frontend && npm run typecheckcd frontend && npm run build
Known limitations
- Raster dependency checks remain optional; missing raster packages return explicit
RASTER_PROCESSING_UNAVAILABLEresults. - Job execution remains synchronous under current Sprint 3 job facade.
dockerandpython3availability still depend on developer environment.
Next recommended pass
- Keep operation architecture stable, then add threshold/mask workflows and output export packaging in a follow-up pass.
Pass 19 - RC-2 stabilization
Date: 2026-06-12
Completed
- Fixed backend compile/import blockers identified in RC-1:
- corrected dataset upload parameter ordering.
- corrected schema package re-exports for area schemas.
- Fixed frontend typecheck/build blockers in
App.tsx. - Added Alembic migration for dataset reference/provenance metadata columns required by current ORM models.
- Fixed QA comparison runtime crash and added focused QA service coverage.
- Corrected envelope response-model mismatches for vector inspect and raster stats endpoints.
- Strengthened
scripts/run_readiness_check.shso readiness runs backend compile, backend tests, frontend typecheck and frontend build. - Improved readiness Python interpreter selection so it chooses an interpreter capable of running pytest.
Files changed
backend/app/services/dataset_service.pybackend/app/schemas/__init__.pybackend/app/api/routes/datasets.pybackend/app/services/qa_service.pybackend/alembic/versions/202606120001_add_dataset_reference_metadata.pybackend/tests/test_qa_service.pyfrontend/src/App.tsxscripts/run_readiness_check.shdocs/CODEX_EXECUTION_LOG.md
Tests run
python -m compileall backend\\app(pass)cd backend && python -m pytest(pass, 40 tests)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass; bundle-size warning only)bash scripts/run_readiness_check.sh(pass)cd backend && python -m alembic heads(pass, single head202606120001)cd backend && python -m alembic upgrade head --sql(pass, generated SQL includes required dataset metadata columns)docker compose confignot runnable in this environment becausedockeris not installed.
Known limitations
- Fresh online database migration was validated only as generated Alembic SQL in this environment; run
cd backend && python -m alembic upgrade headagainst a live PostgreSQL/PostGIS database on a machine with Docker or Postgres available. - Existing non-RC architecture limitations from RC-1 remain intentionally unfixed: synchronous job facade, file-first vector outputs, monolithic frontend component, and incomplete future AI/storage architecture.
Next recommended pass
- Do not start Sprint 7 until RC-2 verification is repeated against a live Docker/PostGIS environment.
Pass 20 - Sprint 7A persistence and QA foundation
Date: 2026-06-12
Completed
- Added first-class
vector_featuresORM model and Alembic migration with dataset and GiST geometry indexes. - Persisted uploaded vector GeoJSON features into PostGIS-backed
vector_featureswhile keeping original file storage intact. - Added first-class
quality_checksandmetricsORM models and Alembic migration indexes. - Added
QualityServicefor persisted QA/QC domain records and metric rows. - Updated QA candidate-vs-reference route so successful QA jobs also persist a
QualityCheckand metrics, and returnquality_check_idinresult_json. - Hardened provider capability contracts for GRB and OSM as
not_configuredstubs with supported layers, geometry types and query modes. - Added Sprint 7A tests for vector feature persistence, quality check persistence, metrics persistence, dataset role validation, provider contracts, migration integrity and QA route persistence.
- Updated database/API documentation for Vector Features Architecture, Quality Check Architecture, Metrics Architecture and Provider Architecture.
Files changed
backend/app/models/entities.pybackend/app/models/__init__.pybackend/app/services/dataset_service.pybackend/app/services/vector_feature_service.pybackend/app/services/quality_service.pybackend/app/api/routes/qa.pybackend/app/providers/base.pybackend/app/providers/grb.pybackend/app/providers/osm.pybackend/app/schemas/health.pybackend/alembic/versions/202606120700_sprint7a_persistence_foundation.pybackend/tests/test_sprint7a_persistence_foundation.pydocs/DATABASE_IMPLEMENTATION_PLAN.mddocs/API_CONTRACTS.mddocs/CODEX_EXECUTION_LOG.mdCHANGELOG.md
Tests run
python -m compileall backend/app(pass)python -m pytest backend -q(pass, 47 tests)
Known limitations
- Sprint 7A intentionally does not implement GRB downloads, OSM downloads, Detection Lab, Segmentation Lab, LiDAR, AI Copilot, Training Studio or Reports.
- Job execution remains the existing synchronous facade.
- Live database migration still needs validation against a running PostgreSQL/PostGIS service in an environment with Docker or Postgres available.
Next recommended pass
- Complete full release validation commands, including Alembic heads/SQL generation, readiness script, frontend typecheck/build and Docker config if Docker is available.
Validation addendum
Date: 2026-06-12
Additional Sprint 7A validation completed after migration index cleanup:
python -m compileall backend/app(pass)cd backend && python -m pytest(pass, 47 tests)bash scripts/run_readiness_check.sh(pass)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass; Vite chunk-size warning only)cd backend && python -m alembic heads(pass, single head202606120700)cd backend && python -m alembic upgrade head --sql(pass; generated SQL includesvector_features,quality_checks,metricsand the named GiST indexix_vector_features_geometry)docker compose configcould not run because Docker is not installed in this shell.
Pass 21 - Sprint 7B provider integration skeleton (2026-06-12)
- Implemented central provider registry for
grb,osm,manualandfixture. - Added provider capability, layer, status and future import-contract endpoints using the existing response envelope style.
- Preserved GRB and OSM as explicit
not_configuredproviders; no live WFS, Overpass, download or fake provider data was introduced. - Documented and tested provider-to-dataset mapping rules; future provider output must flow through
DatasetService/VectorFeatureServicerather than directvector_featureswrites. - Added frontend Provider Capabilities panel without live import buttons for GRB/OSM.
- Added opt-in
scripts/live_migration_smoke.shfor real PostGIS migration smoke checks. - Added Sprint 7B tests for provider registry, API envelopes, invalid provider handling, import contract and smoke script presence.
Pass 22 - Sprint 8 Detection Lab foundation (2026-06-12)
Completed
- Added first-class
detectionsORM model and Alembic migration with project, dataset, analysis run, class and GiST geometry indexes. - Hardened
analysis_runswith dataset, job, model, result and created-at fields while keeping jobs conceptually separate from analysis lifecycle. - Added model registry capability service for
yolo-placeholder(not_configured) andmanual-fixture-detector(explicit fixture/demo only). - Added
DetectionServiceboundary for model listing, request validation, analysis run creation, job creation, unavailable model responses and explicit fixture persistence. - Added Detection Lab API endpoints under
/api/v1/detectionusing the existing response envelope style. - Added minimal frontend Detection Lab panel for model capability status, raster dataset selection, confidence threshold and run result/error display.
- Updated database, API, AI pipeline, backend/frontend README, TODO and changelog docs.
Known limitations
- Real YOLO/PyTorch inference is not enabled and no model downloads are performed.
- Fixture detector requires
fixture_mode=trueand explicit fixture detections; it is not production inference. - Segmentation, LiDAR, AI Copilot, Training Studio and Reports remain out of scope.
Next recommended pass
- Verify Sprint 8 with full backend/frontend/readiness/Alembic gates, then perform a Sprint 8 verification audit before Sprint 8B real YOLO integration.
Pass 23 - Sprint 8B configured YOLO foundation (2026-06-12)
Completed
- Added optional backend
aidependency group forultralyticsandtorch; normal backend startup remains import-safe without those packages. - Added YOLO configuration settings:
YOLO_ENABLEDYOLO_MODEL_PATHYOLO_MODEL_IDYOLO_MODEL_DISPLAY_NAMEYOLO_MODEL_VERSIONYOLO_DEVICEYOLO_IMAGE_SIZEYOLO_MAX_TILESYOLO_BATCH_SIZE
- Added
yolo-configuredmodel registry capability with honestnot_configured,dependency_unavailableandconfiguredstates. - Added
YoloDetectionAdapterthat imports Ultralytics only in the load path and refuses missing local model files before model construction. - Added raster tile manifest validation and configured tile-limit enforcement for real YOLO runs.
- Added pixel bbox to EPSG:4326 polygon georeferencing from tile transform or bounds metadata.
- Routed configured YOLO outputs through existing
DetectionService,Job,AnalysisRunand first-classDetectionpersistence. - Added Detection Lab tile manifest path input for the configured YOLO model.
- Added mocked Sprint 8B tests for model registry status, dependency-unavailable behavior, tile manifest validation, georeferencing and persisted detections.
- Updated API, AI pipeline, backend/frontend README and changelog documentation.
Known limitations
- Sprint 8B does not add workers/queues; configured YOLO runs remain synchronous behind the existing job abstraction.
- Real model loading is validated at execution time. The registry reports configured when dependencies and local model path are present.
- No model weights are downloaded by GeoIntel.
- Detection visualization/map overlays are deferred.
- Segmentation, LiDAR, AI Copilot, Training Studio and Reports remain out of scope.
Next recommended pass
- Run full Sprint 8B validation and then perform a Sprint 8B verification audit before advancing to detection visualization/QA or segmentation planning.
Pass 24 - Sprint 8C detection visualization and QA integration (2026-06-12)
Completed
- Added detection result review endpoints for listing runs, listing detections by run/dataset, retrieving detection detail and returning persisted detections as GeoJSON FeatureCollections.
- Added lightweight detection filters for class name and minimum confidence.
- Added detection QA against persisted reference
vector_featuresusing the existingQualityService,quality_checksandmetricspersistence path. - Added frontend Detection Lab run selection, detection table, class/confidence filters and MapLibre detection GeoJSON overlay via the existing map component.
- Added frontend detection QA controls and metric summary display.
- Added Sprint 8C tests for GeoJSON output, list/filter behavior, detection detail, API envelope shape, QA persistence and no-match QA behavior.
- Added direct Sprint 8B tests for missing and invalid tile manifest files.
- Updated API, AI pipeline, backend/frontend README and changelog documentation.
Known limitations
- Detection QA requires reference datasets to have persisted
vector_features; unsupported references return a clear error instead of fake metrics. - Detection overlays reuse the existing single GeoJSON map layer styling; complex class-based map styling is deferred.
- Segmentation, LiDAR, AI Copilot, Training Studio and Reports remain out of scope.
Next recommended pass
- Run full Sprint 8C validation and perform a Sprint 8C verification audit before starting Sprint 9 Segmentation Lab.
Pass 25 - Sprint 9 Segmentation Lab foundation (2026-06-12)
Completed
- Added first-class
segmentationsORM model and Alembic migration with project, dataset, job, analysis run, class and GiST geometry indexes. - Added segmentation model registry capabilities for
segmentation-placeholder,fixture-segmenter,yolo-seg-configuredandsam-configured. - Added
SegmentationServiceboundary for raster validation, job/analysis-run lifecycle, unavailable model responses and explicit fixture-only persistence. - Added segmentation adapter placeholder module with no SAM, YOLO-seg, torch or ultralytics imports.
- Added persisted segmentation GeoJSON output generated from PostGIS geometry and provenance properties.
- Added segmentation QA against persisted reference
vector_featuresusing existingquality_checksandmetrics. - Added minimal frontend Segmentation Lab panel for model states, raster selection, runs/results, GeoJSON map overlay and QA metric display.
- Updated API, AI pipeline, storage, database, backend/frontend README and changelog documentation.
Files changed
backend/app/models/entities.pybackend/app/models/__init__.pybackend/alembic/versions/202606120900_sprint9_segmentation_foundation.pybackend/app/schemas/segmentation.pybackend/app/schemas/__init__.pybackend/app/services/model_registry_service.pybackend/app/services/segmentation_adapter.pybackend/app/services/segmentation_service.pybackend/app/api/routes/segmentation.pybackend/app/main.pybackend/tests/test_sprint9_segmentation_foundation.pyfrontend/src/types.tsfrontend/src/services/api/segmentation.tsfrontend/src/services/api/index.tsfrontend/src/App.tsxdocs/API_CONTRACTS.mddocs/AI_PIPELINES.mddocs/STORAGE_ARCHITECTURE.mddocs/DATABASE_IMPLEMENTATION_PLAN.mdbackend/README.mdfrontend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Tests run
python -m pytest backend/tests/test_sprint9_segmentation_foundation.py -q(red first: missingSegmentationimport, then pass)cd backend && python -m pytest(pass, 88 tests)cd frontend && npm run typecheck(pass)
Known limitations
- Sprint 9 intentionally does not implement real SAM, real YOLO-seg, model downloads, new AI dependencies or production-scale async inference.
- Fixture segmenter requires explicit
fixture_mode=trueand explicit fixture segmentations; it is not production inference. - Metric area is only persisted when provided by the fixture/output payload; Sprint 9 does not compute authoritative area from masks.
Next recommended pass
- Run full Sprint 9 validation and then perform Sprint 9 Verification Audit before considering future real SAM/YOLO-seg integration.
Validation addendum
python -m compileall backend/app(pass)cd backend && python -m pytest(pass, 88 tests)bash scripts/run_readiness_check.sh(pass)cd frontend && npm run typecheck(pass)cd frontend && npm run build(pass; existing Vite chunk-size warning only)cd backend && python -m alembic heads(pass, single head202606120900)cd backend && python -m alembic upgrade head --sql(pass; generated SQL includessegmentationsand GiST index)bash -n scripts/live_migration_smoke.sh(pass)docker compose configcould not run because Docker is not installed in this shell.
Pass 26 - Sprint 10 release hardening and frontend modularization (2026-06-13)
Completed
- Extracted Provider Capabilities, Detection Lab and Segmentation Lab sections from
frontend/src/App.tsxinto focused frontend components. - Preserved existing workbench state ownership, API client calls, map overlay behavior and UI copy.
- Hardened
scripts/run_readiness_check.shwith Alembic head verification and live migration smoke script syntax validation. - Updated frontend README and changelog documentation for Sprint 10 maintainability work.
Files changed
frontend/src/App.tsxfrontend/src/components/providers/ProviderPanel.tsxfrontend/src/components/detection/DetectionLab.tsxfrontend/src/components/segmentation/SegmentationLab.tsxscripts/run_readiness_check.shfrontend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Sprint 10 intentionally does not add new backend capabilities, migrations, product features, AI dependencies or live provider fetching.
App.tsxstill owns shared workbench state orchestration; further extraction can be considered in a later maintainability pass if needed.
Sprint 10 addendum - additional frontend extraction
- Extracted
frontend/src/components/project/ProjectPanel.tsxandfrontend/src/components/project/AreaPanel.tsxfromfrontend/src/App.tsx. - Kept project and area form state owned by
App.tsx; extracted components receive state and callbacks only. cd frontend && npm run typecheckpassed after the additional extraction.
Pass 27 - Sprint 11 Live Docker/PostGIS Runtime Validation (2026-06-13)
Completed
- Hardened
scripts/live_migration_smoke.shso it runsSELECT 1, appliesalembic upgrade head, then checksPostGIS_Version(). - Added migrated schema-object checks for core tables and geometry indexes after the live migration step.
- Added
backend/tests/test_live_migration_smoke_script.pyto lock the smoke-script ordering and schema-check contract. - Documented the Docker/PostGIS validation command sequence, expected local
DATABASE_URLand cleanup commands inbackend/README.md.
Files changed
scripts/live_migration_smoke.shbackend/tests/test_live_migration_smoke_script.pybackend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Runtime status
- Docker is not installed or not available in this shell, so
docker compose config,docker compose up -d dband the live container-backed smoke could not be completed here. - On a Docker-enabled machine, run:
docker compose configdocker compose up -d dbDATABASE_URL=postgresql+psycopg://geointel:geointel@localhost:5432/geointel bash scripts/live_migration_smoke.sh
Known limitations
- Sprint 11 did not add product behavior, API contracts, migrations, AI dependencies or provider fetching.
- Live runtime validation is partially blocked until Docker/PostGIS is available in the execution environment.
Pass 28 - Sprint 12 QA/QC golden dataset and benchmarking (2026-06-15)
Completed
- Added deterministic golden QA/QC fixtures for reference and predicted building polygons.
- Added
fixtures/golden/expected_qa_metrics.jsonwith the expected partial-match baseline. - Added
scripts/run_golden_qa_benchmark.pyto run existingQaServicelogic and verifyQualityServicepersistence output. - Added backend tests for expected golden metrics, benchmark command output and persisted metric keys.
- Updated QA/QC specification, backend README and changelog documentation.
Files changed
fixtures/golden/reference_buildings.geojsonfixtures/golden/predicted_buildings.geojsonfixtures/golden/expected_qa_metrics.jsonscripts/run_golden_qa_benchmark.pybackend/tests/test_sprint12_golden_qa_benchmark.pydocs/QA_QC_SPECIFICATION.mdbackend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Expected benchmark metrics
- precision:
0.5 - recall:
0.5 - F1:
0.5 - mean IoU:
0.8339768339761133 - false positives:
1 - false negatives:
1
Known limitations
- The benchmark uses explicit fixture/demo data and an in-memory persistence session; it does not replace the pending Docker/PostGIS live smoke.
- Sprint 12 does not add product features, API contracts, migrations, live providers, AI model execution or new dependencies.
Pass 29 - Sprint 13 Real YOLO operational hardening (2026-06-15)
Completed
- Added
YoloPreflightServicefor local configured-YOLO readiness checks without model loading, inference or downloads. - Added
scripts/yolo_preflight.pyfor CLI checks of enabled state, dependencies, local model file, tile manifest validity, tile limit and tile paths. - Added Sprint 13 backend tests for disabled, dependency-unavailable and ready preflight states plus CLI JSON output.
- Updated AI pipeline, backend README and changelog documentation.
Files changed
backend/app/services/yolo_preflight_service.pyscripts/yolo_preflight.pybackend/tests/test_sprint13_yolo_preflight.pydocs/AI_PIPELINES.mdbackend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Preflight does not prove model compatibility or inference correctness; it intentionally avoids loading YOLO models.
- Optional AI dependencies are still not installed by default.
- Docker/PostGIS live validation remains pending until Docker is available.
Pass 30 - Release hardening audit pass (2026-06-15)
Completed
- Audited release-readiness signals after Sprint 13, including timestamp warnings, frontend bundle output, migration SQL rendering and readiness coverage.
- Replaced backend
datetime.utcnow()calls with timezone-aware UTC timestamps in service paths. - Verified the affected backend tests with
DeprecationWarningpromoted to errors. - Split frontend production output into app, React vendor and MapLibre vendor chunks, with an explicit chunk warning threshold for the known MapLibre GIS runtime.
- Updated backend/frontend README, TODO and changelog documentation.
Files changed
backend/app/services/dataset_service.pybackend/app/services/geojson_service.pybackend/app/services/job_service.pybackend/app/services/qa_service.pybackend/app/services/quality_service.pyfrontend/vite.config.tsbackend/README.mdfrontend/README.mddocs/TODO.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- This pass does not add product features, migrations, API contracts, AI dependencies, provider fetching or model execution.
- Docker/PostGIS live validation still requires a Docker-enabled machine.
- Larger frontend architectural decomposition remains a separate low-risk planning item; this pass only hardened build output.
Pass 31 - Extended release hardening sweep (2026-06-15)
Completed
- Promoted the backend readiness gate to run
pytestwith-W error::DeprecationWarning. - Added backend tests that verify readiness and pass-end scripts keep the stricter release checks in place.
- Hardened
scripts/codex_pass_end_check.shso placeholder scans skipnode_modules,distand__pycache__folders. - Updated
docs/TODO.mdwith a current implementation status layer while preserving older planning context. - Re-ran pass-end checks and strict backend warning checks.
Files changed
scripts/run_readiness_check.shscripts/codex_pass_end_check.shbackend/tests/test_readiness_gate.pybackend/README.mddocs/TODO.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- This pass still does not add API contracts, migrations, product features, provider fetching, AI dependencies or model execution.
- Docker/PostGIS live validation remains blocked in this local environment because Docker is unavailable.
Pass 32 - Readiness contract gate hardening (2026-06-15)
Completed
- Added API contract smoke validation to
scripts/run_readiness_check.sh. - Added a regression test that requires the readiness gate to keep running
scripts/smoke_contracts.py. - Re-ran the full readiness gate after the change.
Files changed
scripts/run_readiness_check.shbackend/tests/test_readiness_gate.pybackend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Docker/PostGIS live validation remains blocked in this local environment because Docker is unavailable.
Pass 33 - Docker runtime build hardening (2026-06-15)
Completed
- Investigated Unraid/Tower Docker build failure from pasted server output.
- Fixed backend Docker build ordering so
README.mdandapp/exist beforepip install .. - Removed mandatory root
.envreferences from Compose; default local runtime now uses checked-in environment values. - Added PostGIS healthcheck and backend
depends_onhealth condition. - Made the backend container run
python -m alembic upgrade headbefore starting Uvicorn. - Added backend and frontend
.dockerignorefiles to reduce Docker build context and exclude dependency/build/cache outputs. - Added regression tests for Dockerfile package-source ordering, Compose env behavior, DB health/migration startup and Docker ignore coverage.
Files changed
backend/Dockerfiledocker-compose.ymlbackend/.dockerignorefrontend/.dockerignorebackend/tests/test_docker_runtime_config.pyREADME.mdbackend/README.mddocs/TODO.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Docker commands still cannot be executed in this local Codex environment because Docker is unavailable here.
- The server should rerun
docker compose build --no-cache && docker compose up -dto verify the real Docker runtime.
Pass 34 - Docker browser port 1202 (2026-06-15)
Completed
- Changed Docker Compose frontend host publishing from
5173:5173to1202:5173. - Added backend Docker CORS defaults for
http://localhost:1202andhttp://127.0.0.1:1202. - Updated
.env.exampleand local/Docker documentation to point browser users tohttp://localhost:1202for Docker Compose. - Added a regression assertion to Docker runtime config tests.
Files changed
docker-compose.yml.env.examplebackend/tests/test_docker_runtime_config.pyREADME.mdbackend/README.mdfrontend/README.mddocs/LOCAL_DEVELOPMENT_RUNBOOK.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Docker commands still cannot be executed in this local Codex environment because Docker is unavailable here.
Pass 35 - Docker backend database startup retry (2026-06-16)
Completed
- Investigated Tower runtime logs showing backend Alembic startup failed with
connection refusedeven after the db container reported healthy. - Added
backend/docker_start.shto retry a real SQLAlchemySELECT 1connection before migrations. - Updated Compose to run
sh /app/docker_start.shfor backend startup. - Added regression tests that require the Docker start script and SQL readiness retry before migrations.
Files changed
backend/docker_start.shdocker-compose.ymlbackend/tests/test_docker_runtime_config.pybackend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Docker commands still cannot be executed in this local Codex environment because Docker is unavailable here.
Pass 36 - Alembic Docker log formatting fix (2026-06-16)
Completed
- Investigated backend Docker logs showing repeated literal
%(levelname)-5.5s [%(name)s] %(message)slines during migrations. - Fixed
backend/alembic.inilogging formatter from escaped%%(...)tokens to runtime interpolation%(...)tokens. - Added a regression test for Alembic logging formatter correctness.
- Verified Alembic SQL rendering no longer emits literal formatter spam.
Files changed
backend/alembic.inibackend/tests/test_alembic_logging_config.pyCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Pass 37 - Frontend same-origin API proxy for Docker LAN access (2026-06-16)
Completed
- Audited the running app at
http://192.168.10.150:1202from Codex: frontend HTML and backend/healthwere reachable, but/api/v1/projectson the frontend origin returned the frontend HTML fallback. - Changed the frontend API client default from
http://localhost:8000to same-origin requests. - Added Vite proxy routes for
/apiand/health. - Added Docker Compose
VITE_API_PROXY_TARGET=http://backend:8000so LAN browsers usehttp://192.168.10.150:1202only and the frontend container proxies API calls internally. - Added regression tests for same-origin API/proxy behavior.
Files changed
frontend/src/services/api/client.tsfrontend/vite.config.tsdocker-compose.ymlbackend/tests/test_docker_runtime_config.pyREADME.mdfrontend/README.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- The running Tower deployment needs a rebuild/restart before this fix is active.
Pass 38 - Browser runtime proxy guard (2026-06-16)
Completed
- Added
scripts/verify_browser_runtime.shto verify the browser-facing frontend URL,/api/v1/projectsproxy behavior and optional backend health endpoint. - Added readiness syntax validation for the browser runtime verification script.
- Updated environment and local development documentation to prefer same-origin frontend API calls with Vite proxying in Docker/LAN deployments.
Files changed
scripts/verify_browser_runtime.shscripts/run_readiness_check.shbackend/tests/test_docker_runtime_config.pyREADME.mddocs/ENVIRONMENT_SPEC.mddocs/LOCAL_DEVELOPMENT_RUNBOOK.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- The currently running Tower deployment at
http://192.168.10.150:1202still returns frontend HTML for/api/v1/projectsuntil the frontend image is rebuilt and restarted.
Pass 39 - Environment contract cleanup (2026-06-16)
Completed
- Corrected
.env.exampleanddocs/ENVIRONMENT_SPEC.mdto use the YOLO environment variable names read by backend settings:YOLO_ENABLED,YOLO_MODEL_PATH,YOLO_MODEL_VERSIONandYOLO_MAX_TILES. - Updated frontend example settings to keep
VITE_API_BASE_URLempty by default and exposeVITE_API_PROXY_TARGETfor Vite proxy routing. - Added regression coverage for example environment names and browser runtime proxy verification.
Files changed
.env.exampledocs/ENVIRONMENT_SPEC.mdbackend/tests/test_docker_runtime_config.pyCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Docker cannot be executed in this local Codex environment; Tower still needs an image rebuild/restart to activate the frontend proxy fix.
Pass 40 - Frontend Docker nginx reverse proxy (2026-06-16)
Completed
- Replaced the Docker frontend runtime with a production Vite build served by nginx.
- Added
frontend/nginx.confwith explicit reverse proxy rules for/api/and/healthtobackend:8000. - Changed Docker Compose frontend publishing from
1202:5173to1202:80. - Updated Docker runtime regression tests and documentation so the browser-facing API path is no longer dependent on Vite dev-server proxy behavior.
Files changed
frontend/Dockerfilefrontend/nginx.confdocker-compose.ymlbackend/tests/test_docker_runtime_config.pyREADME.mdfrontend/README.mddocs/ENVIRONMENT_SPEC.mddocs/LOCAL_DEVELOPMENT_RUNBOOK.mdCHANGELOG.mddocs/CODEX_EXECUTION_LOG.md
Known limitations
- Docker still cannot be executed in this local Codex environment. Tower must rebuild the frontend image to activate the nginx runtime.
Sprint 14 - Docker GIS runtime enablement (2026-06-16)
- Added backend
gisoptional dependency group for the approved Rasterio/GeoPandas runtime stack. - Updated backend Docker image to install
.[gis]and GDAL/GEOS/PROJ system packages. - Added
scripts/verify_gis_runtime.shto verify PostGIS, Rasterio and GeoPandas capabilities through the browser-facing frontend proxy. - Added readiness syntax coverage for the GIS runtime verification script.
- Added regression tests for Docker GIS dependency installation and capability verification coverage.
- Updated backend, environment, root README and changelog documentation with local/LAN verification commands.
- No API contracts, migrations, AI dependencies, provider fetching or product features were changed.
- Added
scripts/gis_import_smoke.pyand wired it into the backend Docker build so broken Rasterio/GeoPandas/pyogrio imports fail during image build. - Added Docker Compose healthchecks for backend and frontend; frontend now waits for backend service health before starting.
- Corrected the GIS import smoke placement so the backend Docker build can access it inside the
./backendbuild context; the root script now wraps the backend script.
Sprint 15 - Explicit demo workflow seed (2026-06-16)
- Added
POST /api/v1/demo/workflowfor an explicit offline demo workflow seed. - Added
DemoWorkflowServiceto create or return a demo project, AOI, fixture reference dataset, fixture candidate dataset and persisted QA/QC metrics. - Added
scripts/seed_demo_workflow.pyfor terminal-based demo seeding. - Added frontend
Load demo workflowaction in the Projects panel. - Added endpoint/fixture-contract tests and readiness compile coverage for the demo seed script.
- No live GRB/OSM fetching, AI inference, migrations or new dependencies were introduced.
Sprint 16 - QA/QC result visibility (2026-06-16)
- Added
GET /api/v1/projects/{project_id}/quality-checksfor read-only project QA/QC result listing. - Added
QualityCheckServiceto return persistedquality_checkswith metric rows. - Added frontend QA/QC Results panel and API client support.
- Demo workflow loading and QA actions now refresh persisted QA/QC results in the UI.
- Added backend tests for quality check listing and canonical envelopes.
- No migrations, live provider fetching, AI inference or new dependencies were introduced.
Sprint 17 export foundation (2026-06-16)
Changed:
- Hardened GeoJSON exports so vector dataset, detection run and segmentation run exports persist
exportsrows and write JSON artifacts. - Added project metadata JSON export plus export list/read/content endpoints.
- Added a frontend Export Center panel for creating exports, listing export records and previewing JSON content.
- Added backend tests for export persistence, artifact writing, raster rejection and canonical envelope behavior.
Tested:
python -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shcd backend && python -m alembic heads && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh && bash -n scripts/verify_browser_runtime.sh && bash -n scripts/verify_gis_runtime.sh
Open:
- Docker/live browser validation must be rerun on the deployment host after rebuild.
- YOLO-format export and report export remain documented future work; this pass only implements JSON/GeoJSON export foundation.
Limitations:
- Export artifacts are returned through API JSON content preview; browser file-download UX is not implemented yet.
- Detection and segmentation exports require existing persisted runs; no inference or fake output generation is introduced.
Next recommended pass:
- Rebuild/redeploy the Docker stack and verify
/api/v1/exports/*through the LAN frontend proxy, then consider a lightweight file-download endpoint or report artifact pass.
Sprint 17 export download hardening (2026-06-16)
Changed:
- Added
GET /api/v1/exports/{export_id}/downloadas a raw file response for stored JSON/GeoJSON export artifacts. - Reused the same export artifact existence validation for content preview and downloads.
- Added frontend Export Center download buttons using the configured/same-origin API base URL.
- Added backend tests for missing artifacts and file download response headers/content.
Tested:
python -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shcd backend && python -m alembic heads && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh && bash -n scripts/verify_browser_runtime.sh && bash -n scripts/verify_gis_runtime.sh
Open:
- Docker/LAN validation should be rerun after redeploy on the Tower host.
Limitations:
- Download endpoint is intentionally a raw file response, not a canonical JSON envelope, because it is a browser/file artifact path.
Next recommended pass:
- Rebuild Docker and verify Export Center create/preview/download against
http://192.168.10.150:1202.
Sprint 17 lightweight report artifact export (2026-06-16)
Changed:
- Added
POST /api/v1/exports/reportto create a lightweight HTML project report artifact from persisted project, dataset and QA/QC summary state. - Added HTML escaping for report-rendered project and dataset values.
- Updated export downloads to return
text/htmlfor HTML report artifacts andapplication/jsonfor JSON/GeoJSON artifacts. - Added a frontend Export Center action for project report HTML export.
- Added backend tests for HTML report artifact creation and HTML download response behavior.
Tested:
python -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shcd backend && python -m alembic heads && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh && bash -n scripts/verify_browser_runtime.sh && bash -n scripts/verify_gis_runtime.sh
Open:
- Docker/LAN verification should be rerun after deployment rebuild.
Limitations:
- Report export is intentionally a simple HTML artifact, not a PDF designer or standalone Reports module.
- Report content is summary-only and uses existing persisted project, dataset and QA/QC rows.
Next recommended pass:
- Rebuild Docker and verify Export Center metadata, GeoJSON, report HTML and download flows through the LAN URL.
Sprint 17 export audit trail and LAN demo/export smoke (2026-06-16)
Changed:
- Added export history to project metadata JSON and lightweight HTML report artifacts.
- Added
scripts/verify_demo_export_workflow.shto verify the browser-facing demo workflow, persisted QA/QC listing, metadata export, report export, vector GeoJSON export, export listing and artifact downloads. - Included the demo/export workflow script in the main readiness syntax gate.
- Added backend tests to lock export-history content and demo/export script coverage.
Tested:
python -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shcd backend && python -m alembic heads && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh && bash -n scripts/verify_browser_runtime.sh && bash -n scripts/verify_gis_runtime.sh && bash -n scripts/verify_demo_export_workflow.sh
Open:
scripts/verify_demo_export_workflow.shstill needs to be run against the rebuilt Tower deployment URL.
Limitations:
- The smoke script intentionally uses explicit fixture demo data and does not fetch live GRB/OSM or run AI inference.
Next recommended pass:
- Rebuild Docker on the Tower host and run
bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202.
Sprint 32 Unraid all-in-one runtime verification (2026-06-17)
Changed:
- Converted the Unraid/Tower runtime to a single editable
geointelDocker container viadocker-compose.unraid.yml. - Built the all-in-one image from
postgres:16-bookwormwith PostgreSQL 16/PostGIS packages, the FastAPI backend, nginx and the React frontend. - Removed the default nginx site from the image so
/api/v1/*is proxied to the embedded backend instead of returning nginx 404s. - Hardened live migration smoke and browser runtime verification with startup retries.
- Browser runtime verification now checks the frontend,
/api/v1/projectscanonical JSON envelope and/geointel-icon.png.
Tested:
python -m pytest backend\tests\test_sprint31_unraid_template.pybash -n deploy/unraid/all-in-one-start.shbash -n scripts/live_migration_smoke.shbash -n scripts/verify_browser_runtime.shpowershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_tower.ps1docker compose -f docker-compose.unraid.yml pson Towerbash scripts/verify_browser_runtime.sh http://192.168.10.150:1202
Verified runtime:
- Tower runs one GeoIntel app container:
geointel. - Published browser port is
0.0.0.0:1202->80/tcp. - Container health is
healthy. - Live migration smoke passed with PostGIS available and one Alembic head.
- Frontend, API proxy and icon are reachable at
http://192.168.10.150:1202.
Open:
- Existing reused PostgreSQL volume logs a collation version mismatch because the old database was created on Debian glibc 2.31 and the all-in-one runtime uses glibc 2.36. Runtime and migrations pass; a future maintenance pass can rebuild/refresh collation metadata if needed.
Sprint 32 DockerMan template/icon follow-up (2026-06-17)
Changed:
- Added a PNG icon for Unraid/DockerMan because DockerMan may not reliably render app-served SVG icons.
- Changed the Unraid template
<Name>togeointelso it matches the running all-in-one container name. - Changed the template icon URL to the absolute PNG URL
http://192.168.10.150:1202/geointel-icon.png. - Added DockerMan labels to
docker-compose.unraid.ymlso the running Compose container exposes Unraid managed/webui/icon metadata. - Updated Tower deploy scripts to copy the editable template to
/boot/config/plugins/dockerMan/templates-user/my-geointel.xml. - Updated Tower deploy scripts to copy the PNG icon to
/boot/config/plugins/dockerMan/images/geointel-icon.png.
Expected Unraid behavior:
- Refresh the Unraid Docker page after deploy so DockerMan reloads the user template metadata.
- The running
geointelcontainer should have template-backed editable fields and a PNG icon.
Sprint 32 automatic DockerMan-native deploy follow-up (2026-06-17)
Changed:
- Added
deploy/unraid/run-dockerman-container.shas the single source of truth for the final Unraid container launch. - Updated Tower deploy scripts so repository deploys validate the Compose reference, build the image with plain
docker buildand start the final container withdocker runplus DockerMan labels. - The launch script installs the DockerMan template/icon, removes old
geointelcontainers, preserves/migrates the old Compose PostGIS volume when needed and starts the finalgeointelcontainer as DockerMan-managed. - Updated live migration smoke to support direct container execution through
LIVE_SMOKE_CONTAINER=geointel.
Expected Unraid behavior:
- A deploy from the repo should no longer leave the final app as a plain Compose-owned container.
- The final image/container should avoid Compose metadata labels that can confuse Unraid's Docker page.
- The running
geointelcontainer should exposenet.unraid.docker.managed=dockerman, web UI metadata and icon metadata immediately after deploy.
Sprint 33 QA/QC benchmark readiness hardening (2026-06-17)
Changed:
- Added
scripts/verify_golden_qa_benchmark.shas a shell wrapper for the deterministic QA/QC golden benchmark. - Made
scripts/run_readiness_check.shrunscripts/run_golden_qa_benchmark.py --jsonso QA/QC metric drift fails the main release gate. - Added a readiness syntax check for the golden benchmark wrapper.
- Hardened
scripts/validate_fixtures.pysofixtures/goldenGeoJSON files and expected fixture paths are validated alongside the general GeoJSON fixtures. - Added backend regression tests that keep the golden benchmark wired into readiness.
- Updated script/backend docs, TODO and changelog.
Tested:
python scripts/validate_fixtures.pypython scripts/run_golden_qa_benchmark.py --jsonbash -n scripts/verify_golden_qa_benchmark.shbash scripts/verify_golden_qa_benchmark.shpython -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shcd backend && python -m alembic heads && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh
Open:
- None for this pass.
Limitations:
- The benchmark intentionally uses explicit local fixtures only. It does not fetch live GRB/OSM data and does not run AI inference.
Next recommended pass:
- Continue with broader QA/QC golden demo coverage or frontend export preview decomposition.
Sprint 34 browser-facing golden QA demo hardening (2026-06-17)
Changed:
- Hardened
scripts/verify_demo_export_workflow.shso the browser-facing demo/export smoke loadsfixtures/golden/expected_qa_metrics.json. - The smoke now verifies persisted QA/QC status, F1 score, precision, recall, mean IoU, false positives, false negatives and match counts against the golden baseline.
- Corrected the offline demo AOI to cover the golden fixture geometries instead of an older broad Kempen placeholder outside the fixture coordinates.
- Made existing demo workflows self-heal stale/unsupported QA checks by syncing the demo AOI and persisting a fresh golden QA/QC result.
- Added regression checks in backend tests so the demo/export smoke cannot regress back to key-existence-only QA/QC validation.
- Updated script documentation, TODO and changelog.
Tested:
python -m compileall backend/appcd backend && python -m pytest tests/test_sprint15_demo_workflow.py tests/test_sprint21_demo_workflow_smoke.py tests/test_readiness_gate.py -qcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202
Open:
- Docker build still emits a warning about
GEOINTEL_POSTGRES_PASSWORDbeing present as an imageENV; runtime behavior is green, but a future secret-hygiene pass should move that default out of the Dockerfile.
Limitations:
- The demo/export smoke remains intentionally fixture-based and idempotent. It does not fetch live providers and does not run AI inference.
Next recommended pass:
- Run the full release-readiness gate and then rebuild/deploy to Tower for browser-facing verification.
Sprint 35 Docker runtime secret hygiene (2026-06-17)
Changed:
- Removed embedded PostGIS database name/user/password defaults from
deploy/unraid/Dockerfile.all-in-oneimage metadata. - Kept database credentials as runtime configuration supplied by
.env, the Unraid template, Compose ordocker run -e. - Added regression coverage so
GEOINTEL_POSTGRES_PASSWORDis not baked into the all-in-one Dockerfile again. - Updated Unraid runtime documentation and changelog.
Tested:
cd backend && python -m pytest tests/test_sprint31_unraid_template.py tests/test_docker_runtime_config.py -qbash -n deploy/unraid/all-in-one-start.shbash -n deploy/unraid/run-dockerman-container.shpython -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shcd backend && python -m alembic heads && python -m alembic upgrade head --sqlpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202
Open:
- Local Windows shell has no
dockercommand in PATH, so Docker build/config verification must run on Tower during deploy. - Tower rebuild completed and the previous Docker BuildKit
SecretsUsedInArgOrEnvwarning no longer appears.
Limitations:
- The start script still has safe local defaults for standalone/dev startup. Shared deployments should set
GEOINTEL_POSTGRES_PASSWORDvia runtime configuration.
Next recommended pass:
- Run release readiness, rebuild/deploy Tower and verify browser/GIS/demo smoke again.
Sprint 36 PostgreSQL collation maintenance visibility (2026-06-17)
Changed:
- Added PostgreSQL database collation version reporting to
scripts/live_migration_smoke.sh. - The live smoke now prints
COLLATION_VERSION_MISMATCHwith stored and actual versions when a reused PostGIS volume was created under an older libc/collation runtime. - The smoke also prints the exact
ALTER DATABASE "... " REFRESH COLLATION VERSION;acknowledgement command, but does not run it automatically. - Documented the Unraid maintenance procedure and backup/index review guidance.
- Added regression coverage for the collation reporting path.
Tested:
cd backend && python -m pytest tests/test_live_migration_smoke_script.py -qbash -n scripts/live_migration_smoke.shpython -m compileall backend/appcd backend && python -m pytest -W error::DeprecationWarningcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.shpowershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202bash scripts/verify_gis_runtime.sh http://192.168.10.150:1202bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202
Open:
- Tower live smoke reports
COLLATION_VERSION_MISMATCH: database=geointel stored=2.31 actual=2.36. - Runtime remains green. The next maintenance action is optional/manual acknowledgement after backup/index review:
ALTER DATABASE "geointel" REFRESH COLLATION VERSION;.
Limitations:
- The smoke reports and documents the maintenance action. It intentionally does not mutate collation metadata automatically.
Next recommended pass:
- Run release readiness, deploy Tower and decide whether to manually acknowledge the current collation version.
Sprint 49 Workbench shell UI refactor (2026-06-17)
Changed:
- Audited the live workbench UI and confirmed the main usability issue was information architecture: all V1 workflows were mounted as one long vertical panel stack.
- Refactored the frontend into a task-based workbench shell with Overview, Data, Map, QA/QC, AI Labs, Exports and System workspaces.
- Added a persistent top context bar for active project, AOI, dataset and layer state.
- Moved selected dataset details into a persistent right-side inspector while keeping the same dataset/raster/vector operation callbacks.
- Added stable primary navigation test anchors.
- Documented the new frontend shell structure and updated the changelog.
Tested:
cd frontend && npm run typecheckcd frontend && npm run build- Local Vite visual audit on
http://127.0.0.1:5175
Open:
- Local Vite visual audit shows
Request failed (404)when no local backend/proxy target is available. Docker/nginx same-origin proxy behavior remains the production path. - The next pass should run full release readiness and deploy to Tower for browser-facing verification on
http://192.168.10.150:1202.
Limitations:
- This pass intentionally changes UI structure only. It does not add product capabilities, alter API contracts, change migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Run full readiness, rebuild/deploy Tower, then perform a live browser smoke through the new workbench navigation.
Sprint 50 Workspace usability polish (2026-06-17)
Changed:
- Refined the task-based shell workspaces after the first UI refactor.
- Converted Project, AOI and Dataset panels into compact forms and card-based lists for faster scanning.
- Converted the Map workspace controls into a toolbar with dedicated AOI/layer controls and status.
- Converted Detection Lab and Segmentation Lab into model, run, result and QA blocks.
- Added CSS utilities for entity cards, dataset cards, model cards, lab blocks, primary/secondary actions and responsive nested forms.
- Added regression coverage for the polished workspace structure.
Tested:
cd frontend && npm run typecheckcd frontend && npm run buildcd backend && python -m pytest tests/test_sprint47_workbench_interaction_smoke.py tests/test_sprint49_workbench_shell_refactor.py -q
Open:
- Run full release readiness and deploy the polish to Tower.
Limitations:
- This pass remains frontend-only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Deploy to Tower and verify the Data, Map and AI Labs workspaces on
http://192.168.10.150:1202.
Sprint 51 QA/QC and export workspace polish (2026-06-17)
Changed:
- Refined the QA/QC workspace so persisted checks are shown as summary tiles, quality-check cards and metric chips instead of a raw nested list.
- Refined the Exports workspace with grouped export actions, latest-export status, artifact history cards and a framed JSON/GeoJSON preview panel.
- Kept the existing
useQualityWorkflowanduseExportWorkflowdataflow intact; no API client calls or backend contracts changed. - Added regression coverage for the polished QA/QC and Exports workspace structure.
Tested:
cd frontend && npm run typecheckcd backend && python -m pytest tests/test_sprint27_frontend_workflow_hooks.py tests/test_sprint30_workbench_components.py tests/test_sprint47_workbench_interaction_smoke.py -qcd backend && python -m pytest tests/test_sprint51_quality_export_polish.py -qcd frontend && npm run buildbash scripts/run_readiness_check.sh(207 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202.
Open:
- Manual visual review of populated QA/QC and Exports states with real project artifacts remains useful after the next demo workflow run.
Limitations:
- This pass remains UI polish only. It does not add product capabilities, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Verify QA/QC and Exports on the deployed Tower workbench, then continue with selected-object inspector detail tabs.
Sprint 52 selected context inspector tabs (2026-06-17)
Changed:
- Replaced the dataset-only right inspector with a tabbed
WorkbenchInspector. - Added Context, Dataset, QA/Exports and AI Runs tabs using existing project, AOI, dataset, QA, export and AI-run state.
- Kept the existing
DatasetDetailPanelas the Dataset tab so raster/vector operations and callbacks remain behavior-compatible. - Added inspector cards for selected map feature properties, latest QA/QC, latest export and selected detection/segmentation run summaries.
- Added regression coverage for inspector wiring and tab structure.
Tested:
cd frontend && npm run typecheckcd backend && python -m pytest tests/test_sprint49_workbench_shell_refactor.py tests/test_sprint50_workspace_usability_polish.py tests/test_sprint51_quality_export_polish.py -qcd backend && python -m pytest tests/test_sprint28_dataset_workflow_hook.py tests/test_sprint29_dataset_components.py tests/test_sprint52_workbench_inspector_tabs.py -qcd backend && python -m pytest tests/test_sprint52_workbench_inspector_tabs.py -qcd frontend && npm run buildbash scripts/run_readiness_check.sh(210 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202.
Open:
- Manual click-through of each inspector tab with populated demo data remains useful for visual fine-tuning.
Limitations:
- This pass remains UI orchestration only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Verify the tabbed inspector live on Tower, then continue with map/dataset selection ergonomics.
Sprint 53 map/dataset selection ergonomics (2026-06-17)
Changed:
- Added active-state styling to dataset cards so the selected dataset is visibly anchored in the catalog.
- Added dataset quick actions to open a dataset directly in the Map workspace or Exports workspace after loading details.
- Added inspector navigation actions to jump to Data, Map, QA/QC, Exports and AI Labs without hunting through the left navigation.
- Kept the existing dataset loading, map layer state, export flow and API clients unchanged.
- Added regression coverage for selection quick actions and inspector navigation wiring.
Tested:
cd frontend && npm run typecheckcd backend && python -m pytest tests/test_sprint28_dataset_workflow_hook.py tests/test_sprint29_dataset_components.py tests/test_sprint52_workbench_inspector_tabs.py -qcd backend && python -m pytest tests/test_sprint53_selection_ergonomics.py -qcd frontend && npm run buildbash scripts/run_readiness_check.sh(213 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202.
Open:
- Manual demo-data click-through can still tune copy/density after real populated cards are visible.
Limitations:
- This pass remains UI orchestration only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Verify dataset quick actions with demo data on Tower, then improve populated map/detail readability if needed.
Sprint 54 populated-state UI polish (2026-06-17)
Changed:
- Ran the live demo/export workflow against the Tower deployment to inspect real populated workbench states.
- Adjusted the Data workspace so Project and AOI remain side by side while the Dataset catalog spans the full row for readable populated dataset cards.
- Made dataset-card action rows responsive so Map/Exports/detail actions do not crowd or clip on populated cards.
- Limited the Exports artifact history to the latest 10 entries by default with an explicit show-all toggle.
- Kept the Export Preview panel visible even before an artifact is selected, avoiding a blank middle column in the Exports workspace.
- Shortened displayed export storage paths while keeping the full path available in the title attribute.
- Added regression coverage for the populated Data layout and Exports populated-state behavior.
Tested:
bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202- Local Vite visual audit using the live Tower API proxy on
http://127.0.0.1:5176 cd frontend && npm run typecheckcd backend && python -m pytest tests/test_sprint51_quality_export_polish.py tests/test_sprint53_selection_ergonomics.py -qcd frontend && npm run buildbash scripts/run_readiness_check.sh(214 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202. - Direct HTTP check passed for
http://192.168.10.150:1202andhttp://192.168.10.150:1202/api/v1/projects.
Open:
- Continue monitoring export history growth during repeated demo workflow runs.
Limitations:
- This pass remains UI polish only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Add export history filtering or retention controls if artifact history continues to grow during demo runs.
Sprint 55 live visual shell polish (2026-06-17)
Changed:
- Performed a Browser-based visual audit of the live Tower workbench at
http://192.168.10.150:1202. - Confirmed the main visual defect was the cramped three-column desktop shell: left navigation, central workspace and inspector competed for width at 1280px.
- Compacted the sticky top context bar and left navigation.
- Changed the standard desktop breakpoint so the inspector moves below the workspace up to 1360px, while remaining a side panel on wider displays.
- Made the Map toolbar wrap responsively instead of forcing four controls into a narrow row.
- Added a workspace-change scroll reset so switching pages starts at the workspace heading instead of inheriting stale scroll position.
- Added regression coverage for the standard desktop shell width and scroll-reset behavior.
Tested:
- Local Browser visual audit against
http://127.0.0.1:5177using the live Tower API proxy. - Verified Overview, Data, Map and Exports workspaces visually after the shell changes.
- Browser console error/warning check returned no entries.
cd frontend && npm run typecheckcd backend && python -m pytest tests/test_sprint53_selection_ergonomics.py tests/test_sprint50_workspace_usability_polish.py -qcd frontend && npm run buildbash scripts/run_readiness_check.sh(215 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202. - Live Browser visual verification passed for Overview and Map on
http://192.168.10.150:1202.
Open:
- Export history still grows during repeated demo runs and should get filtering or retention controls.
Limitations:
- This pass remains UI shell polish only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Continue with export history filtering or retention controls if repeated demo runs keep growing artifact history.
Sprint 56 export history controls (2026-06-17)
Changed:
- Added frontend-only search for export type, status, id and storage path in the Exports workspace.
- Added export type and status filters generated from the loaded export records.
- Made the latest-10 limiter apply after filtering so large histories stay manageable without hiding matching records unexpectedly.
- Added a clear no-match empty state and reset view action.
- Slightly compacted export action buttons so the history controls are visible earlier on standard desktop viewports.
- Added regression coverage for the export history controls, filtered list limiting and no-match state.
Tested:
cd frontend && npm run typecheckcd backend && python -m pytest tests/test_sprint51_quality_export_polish.py -qcd frontend && npm run build- Local Browser visual audit against
http://127.0.0.1:5178using the live Tower API proxy. - Verified Exports history controls render with 50 live artifacts and a
reportsearch narrows the list to 17 matching artifacts. - Browser console error/warning check returned no entries.
Open:
- Run full readiness, deploy Tower and verify the live Exports filters on
http://192.168.10.150:1202.
Limitations:
- This pass remains frontend UI hardening only. It does not add backend filtering, retention deletion, API changes, migrations, live provider fetching or AI model behavior.
Next recommended pass:
- Consider a safe export retention/cleanup command if the artifact table keeps growing beyond demo needs.
Sprint 57 safer demo export cleanup (2026-06-17)
Changed:
- Hardened the existing dry-run-first demo export cleanup command instead of creating a parallel cleanup path.
- Added
--max-deletewith a default cap of 25 so large--applyruns are blocked until explicitly reviewed and raised. - Added repeatable
--export-typefilters for targeted cleanup, e.g. reports only. - Extended the cleanup summary with
keep_latest,max_delete,export_types,type_filtered_export_count,candidate_exportsandblocked_reason. - Updated the root wrapper to expose the new filter helper.
- Updated
scripts/README.md,docs/STORAGE_ARCHITECTURE.md,backend/README.md,docs/TODO.mdandCHANGELOG.md. - Added regression coverage for export-type filtering, parser defaults and max-delete options.
Tested:
python -m py_compile scripts/cleanup_demo_artifacts.py backend/scripts/cleanup_demo_artifacts.pycd backend && python -m pytest tests/test_sprint24_cleanup_demo_artifacts.py tests/test_readiness_gate.py -q(16 passed)- Tower dry-run command passed without deleting data:
docker exec geointel /opt/geointel/venv/bin/python /app/scripts/cleanup_demo_artifacts.py --keep-latest 10 --max-delete 100 --export-type project_report_html - Tower dry-run reported
matched_export_count=51,type_filtered_export_count=17,selected_export_count=7,deleted_export_count=0.
Open:
- Run full readiness and redeploy Tower with the clearer
candidate_exportsdry-run output.
Limitations:
- Cleanup still targets demo export records/files only. It does not delete source uploads, vector features, projects, AOIs, QA/QC records, rasters, tiles, masks or production data.
Next recommended pass:
- Add a small live maintenance smoke that runs cleanup in dry-run mode through the deployed all-in-one container.
Sprint 58 demo cleanup dry-run smoke (2026-06-18)
Changed:
- Added
scripts/verify_demo_cleanup_dry_run.shas a live maintenance smoke for the demo export cleanup path. - The smoke auto-detects a running compose backend or all-in-one
geointelcontainer, with explicitCLEANUP_MODE=local|compose|containeroverrides. - The smoke runs cleanup without
--apply, then verifiesdry_run=true,deleted_export_count=0,deleted_files=[], expected filter settings and candidate dry-run fields. - Added the smoke syntax check to
scripts/run_readiness_check.sh. - Added regression coverage that the readiness gate checks the smoke and that the smoke contract remains non-mutating.
- Updated
scripts/README.md,docs/STORAGE_ARCHITECTURE.md,backend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
bash -n scripts/verify_demo_cleanup_dry_run.shpython -m py_compile scripts/cleanup_demo_artifacts.py backend/scripts/cleanup_demo_artifacts.pycd backend && python -m pytest tests/test_readiness_gate.py tests/test_sprint24_cleanup_demo_artifacts.py -q(18 passed)bash scripts/run_readiness_check.sh(219 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202. - Tower cleanup dry-run smoke passed with
matched=51,type_filtered=17,selected=7,deleted=0.
Open:
- None for this pass.
Limitations:
- The readiness gate checks this live smoke's syntax only. The actual cleanup dry-run still requires a running backend/PostGIS runtime.
Next recommended pass:
- Add browser screenshot artifact automation for visual regression handoff.
Sprint 59 workbench screenshot artifacts (2026-06-18)
Changed:
- Added
scripts/capture_workbench_screenshots.shfor optional visual regression handoff screenshots. - The script seeds the explicit offline demo workflow, opens Overview, Data, Map, QA/QC, AI Labs, Exports and System, then writes viewport screenshots plus
manifest.json. - Desktop capture is always enabled; mobile capture is enabled by default and can be disabled with
CAPTURE_MOBILE=0. - Added
/artifacts/to.gitignoreso screenshot outputs stay local. - Added readiness syntax coverage and regression checks for the screenshot capture contract.
- Updated
scripts/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
bash -n scripts/capture_workbench_screenshots.shcd backend && python -m pytest tests/test_readiness_gate.py -q(13 passed)bash scripts/run_readiness_check.sh(221 passed)- Local script execution without Playwright fails cleanly with setup instructions instead of producing partial artifacts.
- Browser-plugin visual capture against
http://192.168.10.150:1202created viewport screenshots for all seven workspaces with no console errors or warnings.
Open:
- Commit, deploy Tower and keep the visual artifact script available for future Playwright-enabled runners.
Limitations:
- Playwright/Chromium is intentionally optional and not added to the frontend dependency set. The readiness gate checks script syntax only.
Next recommended pass:
- Run a backend error-envelope audit for expected user-error paths.
Sprint 60 API error-envelope contract hardening (2026-06-18)
Changed:
- Audited the backend error payload shape against
docs/API_CONTRACTS.md. - Changed central FastAPI error serialization to return top-level
error,message,detailsandrequest_idfields. - Preserved HTTPException detail dict support for future explicit error codes.
- Updated the frontend API client to parse the canonical top-level error contract while remaining tolerant of the older nested
error.code/message/detailsshape. - Added regression tests for AppError, HTTPException and validation-error envelopes.
- Updated provider-registry error assertions to the canonical top-level schema.
- Added static frontend parser coverage for canonical and legacy error payloads.
- Updated
docs/TODO.mdandCHANGELOG.md.
Tested:
cd backend && python -m pytest tests/test_error_envelope_contract.py tests/test_sprint7b_provider_registry.py::test_provider_api_envelopes_and_invalid_provider -q(4 passed)python -m compileall backend/appcd frontend && npm run typecheckcd backend && python -m pytest -q(224 passed)cd frontend && npm run buildcd backend && python -m pytest tests/test_error_envelope_contract.py tests/test_frontend_api_client_error_parser.py tests/test_sprint7b_provider_registry.py::test_provider_api_envelopes_and_invalid_provider -q(6 passed)bash scripts/run_readiness_check.sh(226 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1- Tower live migration smoke passed.
- Tower browser runtime verification passed on
http://192.168.10.150:1202. - Live
GET /api/v1/external/providers/unknownreturned{"error":"PROVIDER_NOT_FOUND","message":"Provider not found","details":{},"request_id":null}. - Live
GET /api/v1/projects/not-a-uuidreturned top-levelVALIDATION_ERROR.
Open:
- None for this pass.
Limitations:
- This pass changes only the centralized response envelope and frontend parser. It does not rename route-level error codes or change product behavior.
Next recommended pass:
- Expand golden datasets beyond the current building QA fixtures.
Sprint 61 Golden QA scenario expansion (2026-06-18)
Changed:
- Added
fixtures/golden/golden_qa_benchmarks.jsonas the explicit scenario manifest for deterministic QA/QC regression coverage. - Added local golden fixture pairs for perfect-match, no-overlap and MultiPolygon building comparisons.
- Updated
scripts/run_golden_qa_benchmark.pyto execute all manifest scenarios, assert expected metric drift, persist simulatedQualityCheck/Metricrows for each scenario and report aggregate persistence totals. - Preserved backward-compatible top-level benchmark fields for scripts that still read the original single-scenario output shape.
- Updated
scripts/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
cd backend && python -m pytest tests/test_sprint12_golden_qa_benchmark.py -qfailed on missing multi-scenario manifest/output. cd backend && python -m pytest tests/test_sprint12_golden_qa_benchmark.py -q(4 passed)python scripts/run_golden_qa_benchmark.py --json
Open:
- Run full readiness and deploy Tower after the expanded golden benchmark passes the release gate.
Limitations:
- These are deterministic local QA/QC fixtures only. They do not introduce new production QA metrics or provider data.
Next recommended pass:
- Continue with frontend visual polish backlog or add a live golden benchmark smoke only if a running PostGIS environment needs that extra release signal.
Sprint 62 Workbench visual polish (2026-06-18)
Changed:
- Added a compact workspace command bar under the active workspace heading for quick movement between the main workbench surfaces.
- Polished the shared frontend visual system with raised/sunken surface tokens, softer shadows, tighter topbar spacing and consistent workspace panel styling.
- Replaced raw project/dataset empty-state text with structured empty-state blocks.
- Wrapped Detection Lab and Segmentation Lab result summaries in scan-friendly result cards and long result tables in scroll-safe containers.
- Improved mobile navigation density by making the primary nav and command chips horizontal rails on narrow screens.
- Added
backend/tests/test_sprint62_frontend_visual_polish.pyto guard the visual polish contracts. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
cd backend && python -m pytest tests/test_sprint62_frontend_visual_polish.py -qfailed on missing command bar, panel polish and empty/result wrappers. cd backend && python -m pytest tests/test_sprint62_frontend_visual_polish.py tests/test_sprint49_workbench_shell_refactor.py tests/test_sprint50_workspace_usability_polish.py -q(6 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local Chrome/Playwright visual check against
http://127.0.0.1:5175with live API proxy: desktop and mobile screenshots captured, no console warnings/errors, no horizontal page overflow.
Open:
- Run full readiness and deploy Tower after this visual polish pass.
Limitations:
- This is a frontend usability polish pass only. It does not add new API behavior, data processing, provider fetching or AI model functionality.
Next recommended pass:
- Continue with map/result overlay ergonomics, especially making selected dataset/result provenance easier to see beside the map.
Sprint 63 Map overlay ergonomics (2026-06-18)
Changed:
- Added active map layer source/provenance/draw-state context in the Map workspace using existing selected dataset, detection, segmentation and change-detection frontend state.
- Added a clear map empty-state when no vector/result layer is active.
- Added selected-feature property chips before the raw JSON feature inspector so common properties are scan-friendly.
- Tightened panel-title alignment with a scoped CSS override after the broader visual polish exposed a specificity issue in the existing
section > div:not(...)rule. - Added
backend/tests/test_sprint63_map_overlay_ergonomics.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
cd backend && python -m pytest tests/test_sprint63_map_overlay_ergonomics.py -qfailed on missing map provenance/feature-summary UI. cd backend && python -m pytest tests/test_sprint63_map_overlay_ergonomics.py tests/test_sprint30_workbench_components.py tests/test_sprint53_selection_ergonomics.py -q(11 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local Chrome/Playwright check against
http://127.0.0.1:5175with live API proxy: Map workspace opened, provenance rail present, no console warnings/errors, no horizontal page overflow.
Open:
- Run full readiness and deploy Tower after this pass.
Limitations:
- This is a frontend ergonomics pass only. It does not add new map layers, backend endpoints, provider fetching or geospatial processing.
Next recommended pass:
- Continue with export/report handoff polish or add a live browser smoke that explicitly visits every workspace after deployment.
Sprint 64 Export/report handoff polish (2026-06-18)
Changed:
- Added a handoff readiness card to the Export Center using existing project, selected dataset, selected detection run, selected segmentation run and latest export state.
- Reworked existing export actions into artifact cards for refresh, project report, project metadata, selected vector GeoJSON, detection GeoJSON and segmentation GeoJSON.
- Added formatted export-type badges and extra export-card provenance for analysis-run ids and created timestamps when those fields are available.
- Added responsive styling for handoff summary/action cards.
- Added
backend/tests/test_sprint64_export_handoff_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint64_export_handoff_polish.py -qfailed on missing handoff summary/action structure and styles. python -m pytest backend/tests/test_sprint64_export_handoff_polish.py backend/tests/test_sprint51_quality_export_polish.py -q(4 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local Chrome/Playwright check against
http://127.0.0.1:5175with live API proxy: Exports workspace opened, handoff summary/actions present, no console warnings/errors, no horizontal page overflow on desktop or mobile. bash scripts/run_readiness_check.sh(233 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the all-in-one container on Tower, with live migration smoke and browser runtime verification passing.- Live Chrome/Playwright check against
http://192.168.10.150:1202: Exports workspace opened, 6 handoff action cards present, no console warnings/errors, no horizontal page overflow on desktop or mobile.
Open:
- None for this pass.
Limitations:
- This is a frontend handoff usability pass only. It does not add export endpoints, change export persistence, introduce provider fetching or add AI/model behavior.
Next recommended pass:
- Run a live browser smoke across Exports and Overview after deployment, then continue with report artifact readability if the exported HTML itself needs visual polish.
Sprint 65 Project report readability polish (2026-06-18)
Changed:
- Reworked the lightweight
project_report_htmlrenderer into a self-contained handoff layout with hero, readiness pill, scorecards and sectioned report content. - Added print-friendly CSS and scroll-safe table wrappers to the HTML artifact.
- Added source and CRS columns to the dataset inventory section.
- Preserved existing export type, endpoint behavior, download behavior and storage flow.
- Added
backend/tests/test_sprint65_project_report_polish.py. - Updated
backend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint65_project_report_polish.py -qfailed on missing report shell, scorecards, print styles and readiness pill classes. python -m pytest backend/tests/test_sprint65_project_report_polish.py backend/tests/test_sprint17_export_foundation.py -q(12 passed)python -m compileall backend/appcd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(235 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live report smoke through
http://192.168.10.150:1202: seeded explicit demo workflow, createdproject_report_html, downloaded the HTML artifact and verified it in Chrome with 5 scorecards, 5 report sections, no console warnings/errors and no horizontal overflow on desktop or mobile.
Open:
- None for this pass.
Limitations:
- This remains a lightweight HTML handoff artifact. It does not add PDF generation, a report designer, new endpoints, live provider fetching or AI/model behavior.
Next recommended pass:
- Continue with a full-workspace browser smoke and then refine any remaining dense panels found during populated-state review.
Sprint 66 Live workspace smoke polish (2026-06-19)
Changed:
- Ran a live browser smoke against
http://192.168.10.150:1202across Overview, Data, Map, QA/QC, AI Labs, Exports and System. - Captured desktop and mobile screenshots under
artifacts/sprint66-live-workspace-smoke/. - Confirmed all primary workspaces load with no console warnings/errors and no page-level horizontal overflow.
- Tightened Export Center handoff card CSS so action cards and readiness cells wrap by available width instead of forcing cramped three/four-column layouts in the populated Exports workspace.
- Added
backend/tests/test_sprint66_live_workspace_smoke_polish.py.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint66_live_workspace_smoke_polish.py -qfailed on missing width-aware export grid CSS and Sprint 66 log entry. - Live desktop browser smoke: all seven primary workspaces opened, screenshots captured, no console warnings/errors, no horizontal page overflow.
- Live mobile browser smoke: all seven primary workspaces opened, screenshots captured, no console warnings/errors, no page-level horizontal overflow. The mobile primary nav intentionally remains a horizontal rail.
- Local post-fix browser check against
http://127.0.0.1:5175with live API proxy: Exports handoff action cards wrap to 2 desktop columns and 1 mobile column, no console warnings/errors and no horizontal page overflow. bash scripts/run_readiness_check.sh(237 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy Exports check on
http://192.168.10.150:1202: handoff action cards render as 2 usable columns at desktop width, no console warnings/errors and no horizontal overflow.
Open:
- None for this pass.
Limitations:
- This is a visual ergonomics hardening pass only. It does not add endpoints, migrations, provider fetching, AI/model behavior or new product capabilities.
Next recommended pass:
- Continue with populated Map/Data interaction polish, especially making it easier to activate the demo vector layer from the map empty state.
Sprint 67 Map empty-state quick actions (2026-06-19)
Changed:
- Added ready vector/GeoJSON dataset quick actions to the Map workspace empty state.
- Reused the existing
openDatasetInMapfrontend flow so quick actions load the same persisted dataset layer as the Data workspace button. - Added width-aware
.map-empty-action-gridstyling for desktop and mobile. - Added
backend/tests/test_sprint67_map_empty_state_quick_actions.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint67_map_empty_state_quick_actions.py -qfailed on missing Map quick-action props, App wiring and CSS. python -m pytest backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint63_map_overlay_ergonomics.py backend/tests/test_sprint30_workbench_components.py -q(9 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local Chrome/Playwright check against
http://127.0.0.1:5175with live API proxy: Map empty state showed 2 ready dataset actions, clicking the first loadeddemo_predicted_buildings.geojsonas a 2-feature active layer, no console warnings/errors and no horizontal overflow. bash scripts/run_readiness_check.sh(240 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy Map quick-action check on
http://192.168.10.150:1202: Map empty state showed 2 ready dataset actions, clicking the first loadeddemo_predicted_buildings.geojsonas a 2-feature active layer, no console warnings/errors and no horizontal overflow.
Open:
- None for this pass.
Limitations:
- This is a frontend interaction polish pass only. It does not add map layers, backend endpoints, migrations, provider fetching or geospatial processing.
Next recommended pass:
- Continue with Data catalog density polish, especially making selected/reference/candidate dataset roles easier to scan in populated demo projects.
Sprint 68 Data catalog density polish (2026-06-19)
Changed:
- Added a compact role summary to the Data catalog for Selected, Reference, Candidate and Source datasets.
- Added scan-friendly dataset card badges plus source, reference layer and CRS context.
- Treated non-reference vector/GeoJSON datasets as QA Candidate display roles in the frontend only, preserving persisted
dataset_rolevalues and API contracts. - Added responsive role-summary and role-badge CSS.
- Added
backend/tests/test_sprint68_dataset_catalog_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint68_dataset_catalog_density.py -qfailed on missing role summary, role badges and responsive CSS. python -m pytest backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint30_workbench_components.py -q(10 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5175with live API proxy: Data workspace showed Selected, Reference, Candidate and Source summary cards, with 1 Reference, 1 Candidate and 0 Source in the demo catalog; dataset badges rendered correctly on desktop and mobile, no console warnings/errors and no horizontal overflow. - Screenshots captured under
artifacts/sprint68-dataset-catalog-density/. bash scripts/run_readiness_check.sh(243 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy Data catalog check on
http://192.168.10.150:1202: Data workspace showed Selected, Reference, Candidate and Source summary cards, candidate/reference badges rendered, no console warnings/errors and no horizontal overflow on desktop or mobile.
Open:
- None for this pass.
Limitations:
- This is a frontend density/readability pass only. It does not change dataset persistence, backend role validation, API contracts, migrations, provider fetching or AI/model behavior.
Next recommended pass:
- Continue with Data workspace action polish, especially making QA/export affordances clearer once candidate and reference layers are present.
Sprint 69 Data catalog action polish (2026-06-19)
Changed:
- Added role-aware recommended action hints to dataset cards.
- Reworked dataset card actions into compact two-line buttons for Inspect, Map, Export / QA and Metadata.
- Kept all existing Data workspace handlers and API calls unchanged.
- Added disabled-action explanation copy for unsupported export/QA and raster metadata refresh cases.
- Added responsive
.dataset-action-gridand.dataset-action-buttonCSS. - Added
backend/tests/test_sprint69_dataset_action_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint69_dataset_action_polish.py -qfailed on missing action hints, action grid and responsive styles. python -m pytest backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint29_dataset_components.py -q(9 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5175with live API proxy: Data workspace rendered 2 role-aware hints and 8 compact dataset actions across the demo candidate/reference datasets, no console warnings/errors and no horizontal overflow on desktop or mobile. - Screenshots captured under
artifacts/sprint69-dataset-action-polish/. bash scripts/run_readiness_check.sh(246 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy Data action check on
http://192.168.10.150:1202: Data workspace rendered 2 role-aware hints and 8 compact dataset actions across the demo candidate/reference datasets, no console warnings/errors and no horizontal overflow on desktop or mobile.
Open:
- None for this pass.
Limitations:
- This is a frontend affordance/readability pass only. It does not add new workflows, change dataset persistence, change API contracts, add migrations, fetch providers or alter AI/model behavior.
Next recommended pass:
- Continue with QA/QC workspace handoff polish, especially linking the existing candidate/reference dataset context more clearly to persisted QA results.
Sprint 70 QA/QC handoff polish (2026-06-19)
Changed:
- Added candidate/reference handoff cards to the QA/QC results panel.
- Resolved persisted quality-check candidate/reference dataset IDs to loaded dataset names when available.
- Passed
candidateDatasetsandreferenceDatasetsfromApp.tsxintoQualityResultsPanel. - Tightened QA candidate context to non-reference vector/GeoJSON datasets while preserving persisted
dataset_rolevalues. - Added responsive
.quality-handoff-grid,.quality-dataset-nameand.quality-check-dataset-linkCSS. - Added
backend/tests/test_sprint70_quality_handoff_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint70_quality_handoff_polish.py -qfailed on missing dataset context props, handoff markup, App wiring and styles. python -m pytest backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint39_frontend_orchestration_hooks.py backend/tests/test_sprint51_quality_export_polish.py -q(15 passed)python -m pytest backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint51_quality_export_polish.py backend/tests/test_sprint30_workbench_components.py backend/tests/test_sprint27_frontend_workflow_hooks.py -q(14 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5175with live API proxy: QA/QC workspace showed 1 candidate layer, 1 reference layer, latest comparison names and named dataset links inside persisted quality-check cards, with no console warnings/errors and no horizontal overflow. - Screenshots captured under
artifacts/sprint70-quality-handoff-polish/. bash scripts/run_readiness_check.sh(250 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy QA/QC handoff check on
http://192.168.10.150:1202: QA/QC workspace showed 1 candidate layer, 1 reference layer, latest comparison names and named dataset links inside persisted quality-check cards, with no console warnings/errors and no horizontal overflow on desktop or mobile.
Open:
- None for this pass.
Limitations:
- This is a frontend handoff/readability pass only. It does not change QA persistence, metric calculations, API contracts, migrations, provider fetching or AI/model behavior.
Next recommended pass:
- Continue with QA/QC result card polish, especially making metric groups easier to scan in long-lived demo projects.
Sprint 71 QA/QC metric card polish (2026-06-19)
Changed:
- Added core metric evidence cards to QA/QC result cards for precision, recall, F1, mean IoU, false positives and false negatives.
- Kept the raw persisted metric list visible below the promoted evidence cards.
- Added compact metric label/value formatting in
QualityResultsPanel. - Added responsive
.quality-metric-grid,.quality-metric-cardand.quality-metric-card-criticalCSS. - Added
backend/tests/test_sprint71_quality_metric_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint71_quality_metric_polish.py -qfailed on missing metric promotion helpers, markup and styles. python -m pytest backend/tests/test_sprint71_quality_metric_polish.py backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint51_quality_export_polish.py backend/tests/test_sprint30_workbench_components.py -q(13 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5175with live API proxy: QA/QC workspace rendered 12 promoted metric cards across 2 persisted quality checks, retained 2 raw metric sections, no console warnings/errors and no horizontal overflow on desktop or mobile. - Screenshots captured under
artifacts/sprint71-quality-metric-polish/. bash scripts/run_readiness_check.sh(253 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy QA/QC metric check on
http://192.168.10.150:1202: QA/QC workspace rendered 12 promoted metric cards across 2 persisted quality checks, retained 2 raw metric sections, no console warnings/errors and no body-level horizontal overflow on desktop or mobile. - Live mobile screenshot captured at
artifacts/sprint71-quality-metric-polish/live-qa-metrics-mobile.png.
Open:
- None for this pass.
Limitations:
- Frontend readability pass only; no QA calculation, persistence, API, migrations, provider or AI/model changes.
Next recommended pass:
- Continue with QA/QC metric/result filtering or result-card density for long-lived demo projects.
Sprint 72 Mobile overflow hardening (2026-06-20)
Changed:
- Clamped page-level horizontal overflow for
html,bodyand the workbench shell. - Kept mobile sidebar navigation and workspace shortcut chips as contained horizontal scroll regions with overscroll containment.
- Added min-width/max-width containment for the workbench layout, main area, inspector panel and card surfaces.
- Allowed long QA check IDs, dataset links and inspector values to wrap instead of widening result cards.
- Switched inspector tabs to a two-column layout on narrow screens.
- Added
backend/tests/test_sprint72_mobile_overflow_hardening.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint72_mobile_overflow_hardening.py -qfailed on missing mobile overflow and identifier wrapping contracts. python -m pytest backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint71_quality_metric_polish.py backend/tests/test_sprint62_frontend_visual_polish.py backend/tests/test_sprint30_workbench_components.py -q(11 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5176with live API proxy at a 390px viewport: QA/QC workspace rendered 2 quality cards and 12 metric cards; body, shell, inspector, inspector panel and inspector tabs stayed within viewport width; sidebar/workspace nav retained contained horizontal scrolling; no console warnings/errors. - Screenshot captured under
artifacts/sprint72-mobile-overflow-hardening/. bash scripts/run_readiness_check.sh(255 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy mobile check on
http://192.168.10.150:1202at a 390px viewport: QA/QC workspace rendered 2 quality cards and 12 metric cards; body, shell, inspector, inspector panel and inspector tabs stayed within viewport width; sidebar/workspace nav retained contained horizontal scrolling; no console warnings/errors. - Live screenshot captured at
artifacts/sprint72-mobile-overflow-hardening/live-mobile-qa.png.
Open:
- None for this pass.
Limitations:
- Frontend CSS hardening only; no UI flow, API, persistence, migration, provider or AI/model changes.
Next recommended pass:
- Continue with QA/QC result filtering/density for long-lived demo projects, or a broader mobile visual pass across Data and Map once the overflow baseline is stable.
Sprint 73 QA/QC result filtering (2026-06-20)
Changed:
- Added client-side QA/QC result search across check id, type, status, candidate/reference dataset ids, analysis/job ids and resolved dataset names.
- Added status and check-type filters derived from the loaded quality-check list.
- Added latest-eight result density control with a show-all toggle.
- Added a no-match empty state and reset action for filtered result views.
- Reused the dense history control styling pattern while allowing the QA/QC controls to wrap inside narrower workspace columns.
- Added
backend/tests/test_sprint73_quality_result_filtering.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint73_quality_result_filtering.py -qfailed on missing filter state, filtered list logic and styles. python -m pytest backend/tests/test_sprint73_quality_result_filtering.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint71_quality_metric_polish.py backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint51_quality_export_polish.py -q(13 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5177with live API proxy: QA/QC filters rendered against 2 persisted demo checks; search/status conflict showed the no-match state; reset restored 2 checks and 12 metric cards; no console warnings/errors and no body-level overflow. - Local mobile browser check at a 390px viewport: filter controls stayed within viewport width, with 2 checks and 12 metric cards visible.
- Screenshots captured under
artifacts/sprint73-quality-result-filtering/. bash scripts/run_readiness_check.sh(257 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container, with live migration smoke and browser runtime verification passing.- Live post-deploy QA/QC filtering check on
http://192.168.10.150:1202: search/status conflict showed the no-match state; reset restored 2 checks and 12 metric cards; no console warnings/errors and no body-level overflow. - Live mobile check at a 390px viewport: QA/QC filter controls stayed within viewport width, with 2 checks and 12 metric cards visible.
- Live screenshots captured at
artifacts/sprint73-quality-result-filtering/live-qa-filtering.pngandartifacts/sprint73-quality-result-filtering/live-qa-filtering-mobile.png.
Open:
- None for this pass.
Limitations:
- Frontend filtering/density pass only; filtering is client-side over already-loaded persisted checks and does not change API pagination, persistence, QA calculations, migrations, provider behavior or AI/model behavior.
Next recommended pass:
- Continue with Data/Map mobile visual polish, especially dataset upload/action forms and map toolbar density on narrow screens.
Sprint 74 Data/Map mobile visual polish (2026-06-20)
Changed:
- Added mobile-density CSS for Data workspace upload forms, file input sizing and dataset action grids.
- Kept the desktop dataset action grid width contract intact while adding compact mobile tracks.
- Added touch/width containment for map toolbar controls, range sliders and empty-map quick actions.
- Reduced mobile map container height to keep controls and map visible together on narrow screens.
- Added
backend/tests/test_sprint74_data_map_mobile_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint74_data_map_mobile_polish.py -qfailed on missing mobile Data/Map CSS contracts. python -m pytest backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint63_map_overlay_ergonomics.py backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint30_workbench_components.py -q(21 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5178with live API proxy at a 390px viewport: Data upload form, file input and 8 dataset action buttons stayed within the viewport with no body-level horizontal overflow; Map toolbar, 2 layer controls, range sliders and empty-map quick actions also stayed within the viewport. - Screenshots captured under
artifacts/sprint74-data-map-mobile-polish/. bash scripts/run_readiness_check.sh(259 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, with live migration smoke and browser runtime verification passing.- Live post-deploy browser check on
http://192.168.10.150:1202at a 390px viewport: Data upload form, file input and 8 dataset action buttons stayed within the viewport; Map toolbar, 2 layer controls, range sliders and empty-map quick actions stayed within the viewport; no body-level horizontal overflow was detected. - Live screenshots captured at
artifacts/sprint74-data-map-mobile-polish/live-data-mobile.pngandartifacts/sprint74-data-map-mobile-polish/live-map-mobile.png.
Open:
- None for this pass.
Limitations:
- Frontend CSS polish only; no Data/Map workflow, API, persistence, migration, provider or AI/model changes.
Next recommended pass:
- Continue with AI Labs mobile/density polish, especially detection and segmentation forms/tables.
Sprint 75 AI Labs mobile visual polish (2026-06-20)
Changed:
- Added mobile-density CSS for Detection and Segmentation Lab model cards, run forms and result summaries.
- Added overflow wrapping for long model ids, source tile paths, mask paths and QA summary values.
- Kept AI result tables scroll-contained while reducing their mobile minimum width.
- Added
backend/tests/test_sprint75_ai_labs_mobile_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint75_ai_labs_mobile_polish.py -qfailed on missing AI Labs mobile CSS contracts. python -m pytest backend/tests/test_sprint75_ai_labs_mobile_polish.py backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint62_frontend_visual_polish.py backend/tests/test_sprint30_workbench_components.py backend/tests/test_sprint8c_detection_visualization_qa.py backend/tests/test_sprint9_segmentation_foundation.py -q(30 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser check against
http://127.0.0.1:5179with live API proxy at a 390px viewport: AI Labs rendered 2 panels, 7 model cards, 6 lab blocks and 4 lab forms with no body-level horizontal overflow. - Screenshot captured under
artifacts/sprint75-ai-labs-mobile-polish/. bash scripts/run_readiness_check.sh(261 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, with live migration smoke and browser runtime verification passing.- Live post-deploy browser check on
http://192.168.10.150:1202at a 390px viewport: AI Labs rendered 2 panels, 7 model cards, 6 lab blocks and 4 lab forms with no body-level horizontal overflow. - Live screenshot captured at
artifacts/sprint75-ai-labs-mobile-polish/live-ai-labs-mobile.png.
Open:
- None for this pass.
Limitations:
- Frontend CSS polish only; no Detection/Segmentation workflow, API, persistence, migration, provider or AI/model changes.
Next recommended pass:
- Continue with Export/System mobile-density polish, especially export action cards and provider capability lists.
Sprint 76 Export/System mobile visual polish (2026-06-20)
Changed:
- Added scan-friendly Provider Capabilities cards with structured provider header, status badge, authority/configuration/geometry/query mode fields and layer chips.
- Added mobile-density CSS for provider cards, export action cards, export history controls and export card headers.
- Added overflow wrapping for long provider limitations, attribution/license notes, export ids and artifact paths.
- Added
backend/tests/test_sprint76_export_system_mobile_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint76_export_system_mobile_polish.py -qfailed on missing Export/System mobile CSS and provider markup contracts. python -m pytest backend/tests/test_sprint76_export_system_mobile_polish.py backend/tests/test_sprint75_ai_labs_mobile_polish.py backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint31_unraid_template.py backend/tests/test_sprint64_export_handoff_polish.py backend/tests/test_sprint7b_provider_registry.py backend/tests/test_sprint30_workbench_components.py -q(27 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(263 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, with live migration smoke and browser runtime verification passing.
Open:
- None for this pass.
Limitations:
- Frontend presentation polish only; no export workflow, provider API, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with right-side inspector mobile polish, especially long dataset/vector/raster metadata and action groups.
Sprint 77 Inspector mobile visual polish (2026-06-20)
Changed:
- Added compact inspector action button grids and mobile-safe wrapping for long inspector values.
- Added scroll/wrap containment for dataset detail text, job JSON and loaded feature metadata.
- Added
dataset-tool-panelanddataset-tool-groupclasses to raster/vector operation controls. - Added CSS containment for raster/vector tool labels, inputs, selects and buttons inside the inspector.
- Added
backend/tests/test_sprint77_inspector_mobile_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint77_inspector_mobile_polish.py -qfailed on missing inspector mobile CSS and dataset tool markup contracts. python -m pytest backend/tests/test_sprint77_inspector_mobile_polish.py backend/tests/test_sprint76_export_system_mobile_polish.py backend/tests/test_sprint75_ai_labs_mobile_polish.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint52_workbench_inspector_tabs.py backend/tests/test_sprint30_workbench_components.py backend/tests/test_sprint29_dataset_components.py -q(18 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(265 passed)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, with live migration smoke and browser runtime verification passing.
Open:
- None for this pass.
Limitations:
- Frontend presentation polish only; no dataset workflow, raster/vector operation behavior, API, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with report/export preview readability polish, especially large JSON/HTML handoff artifacts.
Sprint 78 Export preview readability polish (2026-06-20)
Changed:
- Added preview summary cards for JSON/GeoJSON export payload root type, root key count and rendered preview size.
- Added a scroll-contained export preview JSON shell and toolbar around the existing stored payload preview.
- Added wrapping for long JSON keys/values inside the preview body.
- Added
backend/tests/test_sprint78_export_preview_readability.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint78_export_preview_readability.py -qfailed on missing preview summary/shell CSS and markup contracts. python -m pytest backend/tests/test_sprint78_export_preview_readability.py backend/tests/test_sprint77_inspector_mobile_polish.py backend/tests/test_sprint76_export_system_mobile_polish.py backend/tests/test_sprint51_quality_export_polish.py backend/tests/test_sprint64_export_handoff_polish.py backend/tests/test_sprint17_export_foundation.py -q(20 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(267 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.
Open:
- None for this pass.
Limitations:
- Frontend presentation polish only; no export content, export API, artifact storage, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with accessibility/keyboard focus polish across primary workbench controls.
Sprint 79 Accessibility focus polish (2026-06-20)
Changed:
- Added a shared visible keyboard focus contract for primary buttons, workspace navigation, command chips, inspector tabs and dataset action buttons.
- Added explicit ARIA labels for workspace sidebar navigation, workspace command chips and overview quick actions.
- Bound inspector tabs to active tab panels with
aria-controls, tab ids,tabpanelrole andaria-labelledby. - Added
backend/tests/test_sprint79_accessibility_focus_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint79_accessibility_focus_polish.py -qfailed on missing focus-visible CSS, navigation labels and inspector tab/panel bindings. python -m pytest backend/tests/test_sprint79_accessibility_focus_polish.py backend/tests/test_sprint77_inspector_mobile_polish.py backend/tests/test_sprint53_selection_ergonomics.py backend/tests/test_sprint49_workbench_shell_refactor.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(15 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(270 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.
Open:
- None for this pass.
Limitations:
- Frontend accessibility/presentation polish only; no workflow behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with form-level validation/readability polish for dense raster/vector operation panels.
Sprint 80 Operation form readability polish (2026-06-20)
Changed:
- Added structured headings, helper text, field wrappers, responsive field grids and action rows to raster operation controls.
- Added equivalent readability structure to vector clip, buffer and intersect controls.
- Added inline dataset tool error styling for raster clip/tile validation messages.
- Added
backend/tests/test_sprint80_operation_form_readability.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint80_operation_form_readability.py -qfailed on missing form readability CSS and markup contracts. python -m pytest backend/tests/test_sprint80_operation_form_readability.py -q(3 passed)python -m pytest backend/tests/test_sprint80_operation_form_readability.py backend/tests/test_sprint77_inspector_mobile_polish.py backend/tests/test_sprint29_dataset_components.py backend/tests/test_sprint28_dataset_workflow_hook.py backend/tests/test_vector_operations_service.py backend/tests/test_raster_operations_service.py -q(37 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(273 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.
Open:
- None for this pass.
Limitations:
- Frontend readability/presentation polish only; no raster/vector operation behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with compact empty/error-state polish across QA, exports and AI lab result panels.
Sprint 81 Result state consistency polish (2026-06-20)
Changed:
- Added shared
result-stateCSS variants for loading, error, empty and ready states. - Applied result-state blocks to QA/QC error/empty/filter-empty states.
- Applied result-state blocks to export loading, error and empty/filter-empty states.
- Applied result-state blocks to Detection and Segmentation model loading/errors, empty registries, result counts and QA/run errors.
- Added
backend/tests/test_sprint81_result_state_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint81_result_state_polish.py -qfailed on missing result-state CSS and panel markup contracts. python -m pytest backend/tests/test_sprint81_result_state_polish.py -q(3 passed)python -m pytest backend/tests/test_sprint81_result_state_polish.py backend/tests/test_sprint80_operation_form_readability.py backend/tests/test_sprint75_ai_labs_mobile_polish.py backend/tests/test_sprint76_export_system_mobile_polish.py backend/tests/test_sprint73_quality_result_filtering.py backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint8c_detection_visualization_qa.py backend/tests/test_sprint9_segmentation_foundation.py -q(34 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(276 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.
Open:
- None for this pass.
Limitations:
- Frontend presentation/state polish only; no workflow behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with visual density review for topbar/sidebar/responsive shell after another live browser pass.
Sprint 82 Shell density polish (2026-06-20)
Changed:
- Added a keyboard skip link that targets the active workspace main region.
- Added an explicit
Primary workspaceslabel to the sidebar navigation and a focusableworkspace-maintarget. - Tightened narrow-screen topbar, context chip, sidebar nav and workspace shortcut density while keeping intentional horizontal rails scroll-safe.
- Added
backend/tests/test_sprint82_shell_density_polish.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live browser pre-check against
http://192.168.10.150:1202showed no console errors, no horizontal document overflow and a too-tall narrow viewport topbar/context stack. - Red step:
python -m pytest backend/tests/test_sprint82_shell_density_polish.py -qfailed on missing skip-link, main focus target and compact mobile shell CSS contracts. python -m pytest backend/tests/test_sprint82_shell_density_polish.py -q(3 passed)python -m pytest backend/tests/test_sprint82_shell_density_polish.py backend/tests/test_sprint79_accessibility_focus_polish.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint49_workbench_shell_refactor.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(13 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(279 passed; frontend typecheck/build passed; Alembic single head202606120900)- Live post-deploy browser check found a narrow-screen cascade override that made
.context-barone-column again; tightened the regression test and kept the context rail scrollable through the smallest breakpoint. - Re-ran
python -m pytest backend/tests/test_sprint82_shell_density_polish.py -q,cd frontend && npm run typecheck,cd frontend && npm run buildandbash scripts/run_readiness_check.sh(279 passed) after that fix. powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.- Final live browser check against
http://192.168.10.150:1202passed on desktop and mobile viewports: no console warnings/errors, no horizontal document overflow, skip link/main target present,Primary workspacesnav label present and mobile context bar stayed compact at 64px tall.
Open:
- None for this pass.
Limitations:
- Frontend shell presentation/accessibility polish only; no workflow behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with a live visual review of dense workspace panel hierarchy after the shell density changes are deployed.
Sprint 83 Workspace panel hierarchy polish (2026-06-20)
Changed:
- Made the Overview readiness strip visually calmer with a compact section surface and tighter status tiles.
- Added explicit
overview-action-copy,overview-quick-actionsandquick-action-buttonregions to the recommended-action block. - Restyled the recommended flow block as a lighter accent callout so it no longer competes visually with the readiness strip.
- Added
backend/tests/test_sprint83_workspace_panel_hierarchy.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live browser pre-check against
http://192.168.10.150:1202showed no console errors or horizontal overflow, but the first workspace viewport still had several equally weighted white cards. - Red step:
python -m pytest backend/tests/test_sprint83_workspace_panel_hierarchy.py -qfailed on missing Overview hierarchy regions and compact section-surface CSS contracts. python -m pytest backend/tests/test_sprint83_workspace_panel_hierarchy.py -q(3 passed)python -m pytest backend/tests/test_sprint83_workspace_panel_hierarchy.py backend/tests/test_sprint82_shell_density_polish.py backend/tests/test_sprint62_frontend_visual_polish.py backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint22_workbench_status_strip.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(15 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(282 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.- Final live browser check against
http://192.168.10.150:1202passed on desktop and mobile viewports: no console warnings/errors, no horizontal document overflow, Overview hierarchy regions present and four recommended-action buttons rendered.
Open:
- None for this pass.
Limitations:
- Frontend Overview presentation hierarchy only; no workflow behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with Data workspace panel hierarchy and selected-item density after this pass is deployed and visually checked.
Sprint 84 Data workspace density polish (2026-06-20)
Changed:
- Added selected-summary regions to Project, AOI and Dataset panels so the active data context appears before creation/upload forms.
- Split Project and AOI panels into
data-panel-form-blockanddata-panel-list-blockregions. - Split Dataset catalog into selected dataset, upload source data and available dataset regions.
- Restyled dataset upload as an embedded source-data block while preserving the existing upload flow.
- Added
backend/tests/test_sprint84_data_workspace_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live browser pre-check against
http://192.168.10.150:1202showed Data workspace had no console errors or horizontal overflow, but the first Data viewport was still form-first and visually heavy. - Red step:
python -m pytest backend/tests/test_sprint84_data_workspace_density.py -qfailed on missing selected-summary and named form/list/catalog regions. python -m pytest backend/tests/test_sprint84_data_workspace_density.py -q(3 passed)python -m pytest backend/tests/test_sprint84_data_workspace_density.py backend/tests/test_sprint83_workspace_panel_hierarchy.py backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint29_dataset_components.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(20 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(285 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.- Final live browser DOM/console check against
http://192.168.10.150:1202passed on desktop and mobile viewports: Data workspace active, no console warnings/errors, no horizontal document overflow, three selected-summary regions, three form blocks and three list/catalog blocks rendered.
Open:
- None for this pass.
Limitations:
- Frontend Data workspace presentation hierarchy only; no upload behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with Map workspace panel hierarchy and layer-control density after this pass is deployed and visually checked.
Sprint 85 Map workspace density polish (2026-06-20)
Changed:
- Added a compact Map workspace context summary for selected AOI, active layer and rendered feature state.
- Wrapped existing layer controls and provenance in a dedicated
map-control-surface. - Wrapped the existing MapLibre component in a
map-frame-surfaceand the selected-feature inspector in amap-inspection-surface. - Added
backend/tests/test_sprint85_map_workspace_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live browser pre-check against
http://192.168.10.150:1202showed Map workspace had no console errors or horizontal overflow, but controls, provenance, map frame and inspector still read as a loose vertical stack. - Red step:
python -m pytest backend/tests/test_sprint85_map_workspace_density.py -qfailed on missing Map workspace surface and context-summary contracts. python -m pytest backend/tests/test_sprint85_map_workspace_density.py -q(3 passed)python -m pytest backend/tests/test_sprint85_map_workspace_density.py backend/tests/test_sprint63_map_overlay_ergonomics.py backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(13 passed)cd frontend && npm run typecheckcd frontend && npm run build- Live browser post-deploy check showed desktop Map workspace was structured and overflow-free, but the mobile breakpoint still stacked controls too tall above the map.
- Red step:
python -m pytest backend/tests/test_sprint85_map_workspace_density.py -qthen failed on missing compact mobile Map workspace breakpoint contracts. python -m pytest backend/tests/test_sprint85_map_workspace_density.py -q(4 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(289 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.- Final live browser check against
http://192.168.10.150:1202passed on desktop and mobile viewports: no console warnings/errors, no horizontal document overflow, three Map context summary cards, two layer control cards, separated control/map/inspector surfaces and mobile control preamble reduced after the compact breakpoint correction.
Open:
- None for this pass.
Limitations:
- Frontend Map workspace presentation hierarchy only; no overlay behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with QA/QC workspace result hierarchy and filter density after this pass is deployed and visually checked.
Sprint 86 QA/QC workspace density polish (2026-06-20)
Changed:
- Wrapped QA/QC summary metrics in
quality-summary-surface. - Wrapped candidate/reference/latest comparison context in
quality-evidence-surface. - Wrapped refresh, result states, filters and list limit controls in
quality-control-surface. - Wrapped persisted quality check cards in
quality-history-surface. - Added compact mobile CSS contracts for QA/QC summary, handoff, filter, score, metric and raw metric grids.
- Added
backend/tests/test_sprint86_quality_workspace_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live browser pre-check against
http://192.168.10.150:1202showed QA/QC workspace had no console errors or horizontal overflow, but summary, handoff, filters and history were still visually stacked at equal weight. Mobile measured summary at 210px, handoff at 295px and filters at 278px before the result history. - Red step:
python -m pytest backend/tests/test_sprint86_quality_workspace_density.py -qfailed on missing QA/QC surface and density CSS contracts. python -m pytest backend/tests/test_sprint86_quality_workspace_density.py -q(3 passed)python -m pytest backend/tests/test_sprint86_quality_workspace_density.py backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint71_quality_metric_polish.py backend/tests/test_sprint73_quality_result_filtering.py backend/tests/test_sprint81_result_state_polish.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(18 passed)cd frontend && npm run typecheckcd frontend && npm run build- First full readiness run caught a compatibility regression in
backend/tests/test_sprint51_quality_export_polish.py: the rootquality-results-panelclass was no longer exact. Kept the old root class and moved the new shell into a wrapper. python -m pytest backend/tests/test_sprint51_quality_export_polish.py backend/tests/test_sprint86_quality_workspace_density.py backend/tests/test_sprint70_quality_handoff_polish.py backend/tests/test_sprint73_quality_result_filtering.py -q(11 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(292 passed; frontend typecheck/build passed; Alembic single head202606120900)powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1rebuilt and redeployed the Tower all-in-one container on port 1202, then passed live migration smoke and browser runtime verification.- Final live browser check against
http://192.168.10.150:1202passed on desktop and mobile viewports: no console warnings/errors, no horizontal document overflow, QA/QC shell/surfaces present and two persisted quality check cards rendered.
Open:
- None for this pass.
Limitations:
- Frontend QA/QC workspace presentation hierarchy only; no quality-check behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with Change Detection panel hierarchy and analysis workspace balance after this pass is deployed and visually checked.
Sprint 87 Change Detection density polish (2026-06-20)
Changed:
- Wrapped Change Detection input controls in
change-detection-input-surface. - Replaced loose error/empty text with shared
result-statecards insidechange-detection-state-stack. - Wrapped result metrics in
change-detection-result-surface. - Wrapped warning output in
change-detection-warning-surface. - Added compact responsive CSS contracts for Change Detection form and summary grids.
- Added
backend/tests/test_sprint87_change_detection_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live browser pre-check attempt against
http://192.168.10.150:1202hit a transient browser automation click timeout on the QA/QC workspace nav; source review showed Change Detection was still the older header/form/summary stack. - Red step:
python -m pytest backend/tests/test_sprint87_change_detection_density.py -qfailed on missing Change Detection surface and density CSS contracts. python -m pytest backend/tests/test_sprint87_change_detection_density.py backend/tests/test_sprint18_change_detection.py backend/tests/test_sprint39_frontend_orchestration_hooks.py backend/tests/test_sprint86_quality_workspace_density.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(20 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(295 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy via
scripts/deploy_tower.ps1rebuilt and restarted the all-in-one container onhttp://192.168.10.150:1202. - Tower deploy live migration smoke passed with PostGIS
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and required runtime schema objects present. - Browser runtime verification passed for frontend, proxied API and icon.
- Direct Chrome live UI check passed on desktop
1440x1000and mobile390x844: Change Detection shell/input surface rendered, no horizontal overflow and no console warnings/errors.
Open:
- None known after full readiness, Tower deploy and live browser validation.
Limitations:
- Frontend Change Detection presentation hierarchy only; no change-detection behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with AI Labs run-form hierarchy and detection/segmentation result density after this pass is deployed and visually checked.
Sprint 88 AI Labs density polish (2026-06-20)
Changed:
- Wrapped Detection Lab and Segmentation Lab in shared
ai-lab-shellworkspace shells. - Grouped model registry states into
ai-lab-model-surfacewith a sharedai-lab-state-stack. - Grouped run controls into
ai-lab-run-surface. - Grouped persisted detection/segmentation result loading and tables into
ai-lab-results-surface. - Grouped QA controls and metric summaries into
ai-lab-qa-surface. - Added shared AI Lab CSS contracts for compact model grids, form grids and summary grids.
- Added
backend/tests/test_sprint88_ai_lab_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint88_ai_lab_density.py -qfailed on missing AI Lab shells/surfaces and CSS contracts. python -m pytest backend/tests/test_sprint88_ai_lab_density.py backend/tests/test_sprint8c_detection_visualization_qa.py backend/tests/test_sprint9_segmentation_foundation.py backend/tests/test_sprint39_frontend_orchestration_hooks.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q(34 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser UI check against
http://127.0.0.1:5174passed on desktop and mobile: Detection/Segmentation shells and model/run/result/QA surfaces rendered, no horizontal overflow and no console warnings/errors. The local-only screenshot showed expected API 500 states because only the frontend Vite server was running. - First full readiness run caught legacy AI Lab static contract expectations for exact
lab-blockandresult-summary-cardclass names. Kept those compatibility anchors while preserving the new AI Lab surfaces. python -m pytest backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint75_ai_labs_mobile_polish.py backend/tests/test_sprint88_ai_lab_density.py -q(8 passed)bash scripts/run_readiness_check.sh(299 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy via
scripts/deploy_tower.ps1rebuilt and restarted the all-in-one container onhttp://192.168.10.150:1202. - Tower deploy live migration smoke passed with PostGIS
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and required runtime schema objects present. - Browser runtime verification passed for frontend, proxied API and icon.
- Live browser AI Labs check against
http://192.168.10.150:1202passed on desktop and mobile: Detection/Segmentation shells and model/run/result/QA surfaces rendered, no horizontal overflow and no console warnings/errors.
Open:
- None known after full readiness, Tower deploy and live browser validation.
Limitations:
- Frontend AI Labs presentation hierarchy only; no detection/segmentation behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with export/system final visual consistency or live workflow guidance once this pass is deployed and visually checked.
Sprint 89 Export/System density polish (2026-06-20)
Changed:
- Wrapped Export Center content in
export-center-shell. - Grouped export summary, handoff readiness, artifact actions, current state cards and history into focused
export-*surfaces. - Wrapped Provider Capabilities content in
system-provider-shell. - Replaced loose provider loading/error/empty text with shared
result-statecards. - Grouped provider registry content into
system-provider-capability-surface. - Split provider limitation/reason text and attribution/license data into
provider-detail-stackand provenance cards. - Added shared Export/System density CSS for compact summary, handoff, action, history and provider provenance grids.
- Added
backend/tests/test_sprint89_export_system_density.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint89_export_system_density.py -qfailed on missing Export/System shells, surfaces and CSS contracts. python -m pytest backend/tests/test_sprint89_export_system_density.py backend/tests/test_sprint51_quality_export_polish.py backend/tests/test_sprint64_export_handoff_polish.py backend/tests/test_sprint76_export_system_mobile_polish.py backend/tests/test_sprint78_export_preview_readability.py -q(12 passed)cd frontend && npm run typecheckcd frontend && npm run build- In-app browser fallback note: the Browser click path timed out on the local workspace navigation CDP command, so rendered validation used local Chrome via Playwright.
- Local Chrome UI check against
http://127.0.0.1:5174passed on desktop and mobile: Export/System shells and surfaces rendered with no horizontal overflow. Local console showed expected Vite proxy 500s because only the frontend server was running. bash scripts/run_readiness_check.sh(303 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy via
scripts/deploy_tower.ps1rebuilt and restarted the all-in-one container onhttp://192.168.10.150:1202. - Tower deploy live migration smoke passed with PostGIS
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and required runtime schema objects present. - Browser runtime verification passed for frontend, proxied API and icon.
- Live Chrome UI check against
http://192.168.10.150:1202passed on desktop and mobile: Export/System shells and surfaces rendered, four provider cards and eight provider provenance cards were visible, no horizontal overflow and no console warnings/errors.
Open:
- None known after full readiness, Tower deploy and live browser validation.
Limitations:
- Frontend Export/System presentation hierarchy only; no export behavior, API contract, persistence, migration, provider fetching or AI/model changes.
Next recommended pass:
- Continue with end-to-end workflow guidance after this pass is deployed and visually checked.
Sprint 90 workflow guidance polish (2026-06-20)
Changed:
- Added an Overview
workflow-guidance-panelthat shows the V1 flow from Project & AOI through Data, Map, QA / AI and Export. - Added ready/waiting/next state labels from existing loaded project, dataset, map, QA/AI and export state.
- Routed the guidance cards through the existing
setActiveWorkspacenavigation only. - Added compact responsive CSS for the guidance rail.
- Added
backend/tests/test_sprint90_workflow_guidance.py. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend/tests/test_sprint90_workflow_guidance.py -qfailed on missing workflow guidance App and CSS contracts. python -m pytest backend/tests/test_sprint90_workflow_guidance.py backend/tests/test_sprint83_workspace_panel_hierarchy.py backend/tests/test_sprint49_workbench_shell_refactor.py backend/tests/test_sprint62_frontend_visual_polish.py backend/tests/test_sprint82_shell_density_polish.py -q(13 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(306 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Local browser UI check against
http://127.0.0.1:5174passed on desktop and mobile: workflow guidance panel rendered with five steps and no horizontal overflow. Local console showed expected Vite proxy 500s because only the frontend server was running. - Tower deploy via
scripts/deploy_tower.ps1rebuilt and restarted the all-in-one container onhttp://192.168.10.150:1202from commit2a0e7e7. - Tower deploy live migration smoke passed with PostGIS
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and required runtime schema objects present. - Browser runtime verification passed for frontend, proxied API and icon.
- Live browser UI check against
http://192.168.10.150:1202passed on desktop and mobile: workflow guidance panel rendered with five steps, no horizontal overflow and no console warnings/errors.
Open:
- None known after full readiness, Tower deploy and live browser validation.
Limitations:
- Frontend Overview workflow guidance only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
Next recommended pass:
- After deploy and visual validation, continue with any remaining end-to-end workflow handoff polish surfaced by the live audit.
Sprint 91 populated workflow audit polish (2026-06-21)
Changed:
- Audited the live populated demo state on
http://192.168.10.150:1202across Overview, Data, Map, QA/QC, AI Labs and Exports. - Changed the Overview workflow guidance badge to show
Ready for handoffwhen project, dataset, map, QA/AI and export state are all present. - Clarified the Map workflow step so it reports layer feature count separately from AOI context and shows
AOI loadedfor AOI-only map context. - Extended
backend/tests/test_sprint90_workflow_guidance.pywith complete-state and Map-copy regression coverage. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live pre-change browser audit passed for the populated demo workflow: Data had 2 ready datasets, Map rendered
demo_predicted_buildings.geojsonwith 2 layer features, QA/QC showed 2 checks, AI Labs showed model/result/QA surfaces, Exports showed 50 artifacts, and no checked workspace had console warnings/errors or horizontal overflow. - Red step:
python -m pytest backend/tests/test_sprint90_workflow_guidance.py -qfailed on missingworkflowGuidanceComplete/Ready for handoff/ precise Map copy contracts. - Post-deploy live check found the AOI-only reload state rendered
0 layer features + AOI; a second red step failed on missingAOI loadedcopy before the fix. python -m pytest backend/tests/test_sprint90_workflow_guidance.py -q(4 passed)python -m pytest backend/tests/test_sprint90_workflow_guidance.py backend/tests/test_sprint83_workspace_panel_hierarchy.py backend/tests/test_sprint82_shell_density_polish.py -q(10 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser UI check against
http://127.0.0.1:5174passed for the Overview guidance panel with no horizontal overflow. Local console showed expected Vite proxy 500s because only the frontend server was running. bash scripts/run_readiness_check.sh(307 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy via
scripts/deploy_tower.ps1rebuilt and restarted the all-in-one container onhttp://192.168.10.150:1202from commit97b943d. - Tower deploy live migration smoke passed with PostGIS
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1and required runtime schema objects present. - Browser runtime verification passed for frontend, proxied API and icon.
- Live post-change browser check passed: AOI-only Overview state showed
Map AOI loaded; after openingdemo_predicted_buildings.geojsonon the map, Overview showedMap 2 layer features + AOI; both states showedReady for handoff, no horizontal overflow and no console warnings/errors.
Open:
- None known after full readiness, Tower deploy and live browser validation.
Limitations:
- Frontend Overview copy/state polish only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
Next recommended pass:
- After deploy and live validation, continue with any remaining populated-state visual issues found in the next audit.
Sprint 92 workflow rail interaction polish (2026-06-21)
Changed:
- Audited the live Overview workflow rail click path on
http://192.168.10.150:1202. - Added
openWorkflowGuidanceStepso Map and Export rail clicks can reuse existing dataset context flows. - Map rail click now opens the first ready vector/GeoJSON dataset through
openDatasetInMapwhen no layer is active. - Export rail click now opens the first ready vector/GeoJSON dataset through
openDatasetExportwhen no dataset is selected. - Extended
backend/tests/test_sprint90_workflow_guidance.pywith regression coverage for the context-aware rail handler. - Updated
frontend/README.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Live pre-change browser audit showed the rail navigated correctly but Map landed with no active layer and Exports landed with
Selected dataset: none. - Red step:
python -m pytest backend/tests/test_sprint90_workflow_guidance.py -qfailed on missingopenWorkflowGuidanceStep/ dataset-context handler contracts. python -m pytest backend/tests/test_sprint90_workflow_guidance.py backend/tests/test_sprint53_selection_ergonomics.py backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint64_export_handoff_polish.py -q(15 passed)cd frontend && npm run typecheckcd frontend && npm run build- Local browser UI check against
http://127.0.0.1:5174passed for rail rendering with no horizontal overflow. Local console showed expected Vite proxy 500s because only the frontend server was running. bash scripts/run_readiness_check.sh(308 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy from commit
1872c60completed; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live targeted browser validation against
http://192.168.10.150:1202passed forOpen Map step:demo_predicted_buildings.geojsonbecame active,2 featuresrendered, no horizontal overflow and no console/page errors. - Live targeted browser validation against
http://192.168.10.150:1202passed forOpen Export step:demo_predicted_buildings.geojsonbecame the selected export dataset, no horizontal overflow and no console/page errors.
Open:
- None for this pass.
Limitations:
- Frontend workflow navigation polish only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
Next recommended pass:
- After deploy and live validation, continue with export artifact action ergonomics or QA result drill-down, depending on the next live friction point.
Sprint 93 export handoff artifact polish (2026-06-21)
Changed:
- Added a
Latest handoff artifactssection tofrontend/src/components/exports/ExportCenter.tsx. - Grouped newest persisted artifacts for project report, project metadata, dataset GeoJSON, detection GeoJSON and segmentation GeoJSON.
- Reused existing JSON preview and artifact download callbacks from latest artifact cards.
- Added responsive latest artifact card styling in
frontend/src/styles/app.css. - Added
backend/tests/test_sprint93_export_handoff_completion.pyto lock the grouped handoff surface, actions and responsive CSS. - Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint93_export_handoff_completion.py -qfailed on missing latest artifact grouping/actions/styles. python -m pytest backend\tests\test_sprint93_export_handoff_completion.py -q(3 passed)python -m pytest backend\tests\test_sprint93_export_handoff_completion.py backend\tests\test_sprint64_export_handoff_polish.py backend\tests\test_sprint89_export_system_density.py backend\tests\test_sprint51_quality_export_polish.py backend\tests\test_sprint78_export_preview_readability.py -q(13 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(311 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy from commit
0a9054ccompleted; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live browser validation against
http://192.168.10.150:1202passed forOpen Export step: selected dataset stayeddemo_predicted_buildings.geojson,Latest handoff artifactsrendered, project report/project metadata/dataset GeoJSON cards were present, detection/segmentation cards showedNo artifact yet, preview opened from the latest artifact card, no horizontal overflow and no console/page errors.
Open:
- None for this pass.
Limitations:
- Export Center frontend handoff polish only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
Next recommended pass:
- After deploy and live validation, continue with QA/QC drilldown and map evidence layers.
Sprint 94 QA/QC evidence drilldown (2026-06-22)
Changed:
- Added selected-check drilldown state to
frontend/src/components/quality/QualityResultsPanel.tsx. - Added a
QA/QC evidence drilldownsurface with selected check, candidate/reference layer, analysis run, job, status, score and timestamp provenance. - Added false-positive evidence, false-negative evidence and map evidence handoff cards using persisted metric rows and dataset names.
- Added parameter and findings JSON panes for persisted QA/QC provenance.
- Added
Inspect latest checkand per-resultInspect checkcontrols. - Added responsive QA drilldown styles to
frontend/src/styles/app.css. - Added
backend/tests/test_sprint94_quality_drilldown.py. - Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint94_quality_drilldown.py -qfailed on missing drilldown state/surfaces/styles. python -m pytest backend\tests\test_sprint94_quality_drilldown.py backend\tests\test_sprint70_quality_handoff_polish.py backend\tests\test_sprint71_quality_metric_polish.py backend\tests\test_sprint73_quality_result_filtering.py backend\tests\test_sprint86_quality_workspace_density.py -q(15 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(314 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)- Tower deploy from commit
f3ad9c3completed; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live browser validation against
http://192.168.10.150:1202passed forOpen QA / AI step: QA/QC evidence drilldown rendered, candidate/reference names resolved, false-positive/negative evidence rendered, parameters/findings JSON rendered, per-resultInspect checkcontrols were available, no horizontal overflow and no console/page errors.
Open:
- None for this pass.
Limitations:
- QA/QC frontend drilldown only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
- Map evidence handoff points reviewers to candidate/reference datasets already persisted in the workbench; it does not create a new matched/unmatched geometry export.
Next recommended pass:
- After deploy and live validation, continue with QA map overlay affordances or raster pipeline hardening.
Sprint 95 raster pipeline hardening (2026-06-22)
Changed:
- Added a
Raster pipeline readinesssurface tofrontend/src/components/datasets/RasterControls.tsx. - Surfaced metadata profile, CRS readiness, preview artifact, tile manifest handoff and clip AOI state before raster operations.
- Added
Processing guardrailsfor missing selected dataset, unavailable raster processing, missing metadata, missing CRS, missing preview, invalid tile parameters and missing clip areas. - Added responsive raster readiness, guardrail and manifest-handoff styles to
frontend/src/styles/app.css. - Added
backend/tests/test_sprint95_raster_pipeline_hardening.py. - Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint95_raster_pipeline_hardening.py -qfailed on missing readiness/handoff component structure and CSS. python -m pytest backend\tests\test_sprint95_raster_pipeline_hardening.py -q(2 passed)python -m pytest backend\tests\test_sprint80_operation_form_readability.py backend\tests\test_sprint77_inspector_mobile_polish.py -q(5 passed)python -m compileall backend/appcd backend && python -m pytest -q(316 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(316 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh- Tower deploy from commit
330b677completed; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live browser validation against
http://192.168.10.150:1202passed for the workbench shell: Overview/Data/Map/QA/QC/AI Labs/Exports markers were present, no horizontal overflow and no console/page errors. - Live dataset API validation confirmed the default demo currently contains vector fixtures only, so the raster-specific panel is not visible in the default live state without a raster upload.
Open:
- None for this pass.
Limitations:
- Frontend raster inspector hardening only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
- The panel explains the existing tile manifest handoff but does not create a new manifest picker or new detection/segmentation behavior.
- Raster-specific live visual validation requires a raster dataset in the live project; the current offline demo seed contains vector fixtures only.
Next recommended pass:
- After deploy and live validation, add a raster fixture/demo upload smoke or continue with map evidence overlay affordances for QA/QC.
Sprint 96 useful default context (2026-06-22)
Changed:
- Added a guarded default dataset effect in
frontend/src/hooks/useDatasetWorkflow.ts. - When project data loads and no dataset is selected, the workbench now auto-opens the first ready vector dataset, falling back to any ready dataset and then the first dataset.
- This gives Data, Map and Exports an immediately useful selected dataset/map layer context for the populated demo flow.
- Added explicit no-raster guidance cards to Detection Lab and Segmentation Lab run controls.
- Added
backend/tests/test_sprint96_useful_default_context.py. - Updated
CHANGELOG.md,docs/TODO.mdandfrontend/README.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint96_useful_default_context.py -qfailed on missing default dataset selection and no-raster AI Lab guidance. python -m pytest backend\tests\test_sprint96_useful_default_context.py -q(2 passed)python -m pytest backend\tests\test_sprint39_frontend_orchestration_hooks.py backend\tests\test_sprint29_dataset_components.py backend\tests\test_sprint88_ai_lab_density.py -q(16 passed)python -m compileall backend/appcd backend && python -m pytest -q(318 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(318 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh- Tower deploy from commit
aaf1299completed; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live browser validation against
http://192.168.10.150:1202passed: Data auto-selecteddemo_predicted_buildings.geojson, Map rendered2 features, Exports showed the same selected dataset, AI Labs showed no-raster guidance for detection and segmentation, desktop/mobile had no horizontal overflow and no console/page errors.
Open:
- None for this pass.
Limitations:
- Frontend usability/default-context hardening only; no API contract, persistence, migration, provider fetching or AI/model behavior changes.
- Detection and segmentation remain correctly blocked without a raster dataset.
Next recommended pass:
- After deploy and live validation, add a raster fixture/demo upload smoke so AI Labs and raster controls can be validated with a connected raster state.
Sprint 101 AI Lab handoff browser smoke (2026-06-24)
Changed:
- Added
scripts/verify_ai_handoff_interactions.sh. - The script seeds the explicit offline demo workflow through the frontend-facing API, creates a small raster tile manifest, opens the browser workbench with Playwright/Chromium, clicks
Use in Detection LabandUse in Segmentation Lab, and verifies both AI Lab forms receive the selected raster dataset plusRaster tile manifest path. - Added syntax coverage for the new script to
scripts/run_readiness_check.sh. - Added
backend/tests/test_sprint101_ai_handoff_interaction_smoke.py. - Updated
scripts/README.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint101_ai_handoff_interaction_smoke.py -qfailed whilescripts/verify_ai_handoff_interactions.shwas absent. python -m pytest backend\tests\test_sprint101_ai_handoff_interaction_smoke.py -q(1 passed)bash -n scripts/verify_ai_handoff_interactions.sh- Local Node Playwright availability check failed with
ERR_MODULE_NOT_FOUND, so live browser-click execution requires Playwright to be installed or exposed in the runner environment. python -m compileall backend/appcd backend && python -m pytest -q(324 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(324 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh- Tower deploy from commit
aab51edcompleted; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live smoke passed:
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202. - Live browser-click validation with Codex Playwright plus installed Chrome passed against
http://192.168.10.150:1202: the smoke seeded the demo workflow, generated a raster tile manifest, selected the raster in Data, opened the Dataset inspector tab, clickedUse in Detection Lab, selectedyolo-configured, verified Detection Lab dataset and manifest values, clickedUse in Segmentation Lab, verified Segmentation Lab dataset and manifest values, and observed no console/page errors.
Open:
- None for this pass.
Limitations:
- Test/smoke tooling only; no product behavior, API contract, migration, AI dependency, provider fetching or model behavior changes.
scripts/verify_ai_handoff_interactions.shrequires a runner with Playwright plus a browser. This Codex environment had Playwright available through the Node REPL and used installed Chrome; plain localnodestill reportsERR_MODULE_NOT_FOUNDforplaywright.
Next recommended pass:
- After validation and deploy, keep using the AI handoff smoke as the browser-level regression guard for raster-to-AI workspace wiring.
Sprint 102 Detection Lab handoff polish (2026-06-24)
Changed:
- Updated
useRasterTileManifestForDetectioninfrontend/src/App.tsxto setselectedDetectionModelIdtoyolo-configuredwhen a raster tile manifest is handed off from the dataset inspector. - Tightened
scripts/verify_ai_handoff_interactions.shso it verifies that Detection Lab is already onyolo-configuredafter the handoff instead of selecting that model inside the smoke. - Updated
backend/tests/test_sprint99_raster_ui_handoff.pyandbackend/tests/test_sprint101_ai_handoff_interaction_smoke.py. - Updated
CHANGELOG.mdanddocs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint99_raster_ui_handoff.py -qfailed while the detection handoff did not setyolo-configured. python -m pytest backend\tests\test_sprint99_raster_ui_handoff.py backend\tests\test_sprint101_ai_handoff_interaction_smoke.py -q(2 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash -n scripts/verify_ai_handoff_interactions.shpython -m compileall backend/appcd backend && python -m pytest -q(324 passed)bash scripts/run_readiness_check.sh(324 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh- First Tower redeploy attempt failed with Docker btrfs
no space left on devicewhile writing build context files. - Remote Docker diagnosis showed
/var/lib/dockerhad ordinary free space but btrfs metadata was 94.80% used with the 300GB docker image fully allocated. - Removed dangling Docker images and cleared orphaned hung Docker CLI processes from prior inspection/prune attempts.
- Ran a limited Docker btrfs balance:
btrfs balance start -dusage=40 -musage=80 /var/lib/docker; metadata improved to 75.63% used and 94.95GiB became unallocated. - Tower deploy from commit
4367400then completed; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live smoke passed:
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202. - Internal Codex browser validation passed against
http://192.168.10.150:1202: Data workspace selected the raster fixture, Dataset inspector handoff clickedUse in Detection Lab, Detection Lab auto-selectedyolo-configured, the raster dataset and tile manifest matched the generated manifest, the manifest input was visible, and no console/page errors were reported.
Open:
- None for this pass.
Limitations:
- Frontend handoff polish only; no backend API, persistence, migration, provider fetching, AI dependency or model execution behavior changed.
- The Tower Docker image required btrfs metadata balancing before redeploy. If this recurs, inspect
btrfs filesystem usage /var/lib/docker; metadata near full can fail builds even whendfreports free GB.
Next recommended pass:
- After live validation, continue with the next V1 usability gap from the workbench flow rather than adding new model/provider scope.
Sprint 103 AI Lab run readiness (2026-06-24)
Changed:
- Added compact run-readiness panels to Detection Lab and Segmentation Lab.
- Detection readiness now checks selected raster dataset, selected model availability and the configured-YOLO tile manifest requirement before a run is submitted.
- Segmentation readiness now checks selected raster dataset, configured segmentation model state and whether a tile manifest is present for provenance.
- Added shared AI Lab readiness styling and regression coverage in
backend/tests/test_sprint103_ai_lab_run_readiness.py. - Updated
CHANGELOG.mdanddocs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint103_ai_lab_run_readiness.py -qfailed while the readiness panels and CSS contracts were absent. python -m pytest backend\tests\test_sprint103_ai_lab_run_readiness.py -q(3 passed)python -m compileall backend/appcd backend && python -m pytest -q(327 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(327 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh- Tower deploy from commit
98fff63completed; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live smoke passed:
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202. - Internal Codex browser validation passed against
http://192.168.10.150:1202: AI Labs rendered Detection and Segmentation run-readiness panels; Detection stayed blocked whenConfigured YOLO detectorhad no local YOLO configuration but marked dataset and tile manifest as provided; Segmentation became ready with the explicit fixture segmenter and manifest; desktop and mobile viewports had no horizontal overflow and no console warnings/errors.
Open:
- None for this pass.
Limitations:
- Frontend readiness guidance only; no backend API, persistence, migration, provider fetching, AI dependency or model execution behavior changed.
Next recommended pass:
- Continue with V1 usability work that reduces operator confusion without expanding frozen product scope.
Sprint 122 Detection model asset activation guardrails (2026-07-08)
Changed:
- Hardened Detection Lab local model handling so reported runtime model assets are read-only choices and are not auto-selected by the frontend hook.
- Configured YOLO run readiness now blocks submission when local model assets exist but no explicit
model_asset_idhas been selected. - Added an explicit model asset section with active runtime env status,
will_download_models, SHA-256 preview, file size and mounted model path. - Surfaced the current benchmark candidate
geointel-building-yolov8s-hardneg160r4e50-ptwith recommended starting threshold0.25. - Added compact UI guidance styling for the benchmark/threshold warning.
- Added regression coverage in
backend/tests/test_sprint122_model_asset_activation_guardrails.py. - Updated
CHANGELOG.mdanddocs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint122_model_asset_activation_guardrails.py -qfailed on the previous auto-selection behavior and missing guardrail copy. python -m pytest backend\tests\test_sprint122_model_asset_activation_guardrails.py -q(3 passed)python -m pytest backend\tests\test_sprint118_yolo_preflight_ui.py backend\tests\test_sprint103_ai_lab_run_readiness.py backend\tests\test_sprint104_ai_lab_action_guardrails.py backend\tests\test_model_asset_catalog.py backend\tests\test_sprint122_model_asset_activation_guardrails.py -q(16 passed)python -m compileall backend/apppython -m pytest backend\tests -q(408 passed)cd frontend && npm run typecheckcd frontend && npm run build
Open:
- Full threshold calibration comparison UI is still pending; this pass adds safe single-threshold guidance and explicit asset choice only.
Limitations:
- Frontend guardrail only; no backend API contracts, migrations, provider fetching, model downloads or model weight mutation behavior changed.
- The active runtime env model can still be configured by operators through existing deployment/env tooling, but the Detection Lab no longer silently chooses a local asset from the catalog for a run.
Next recommended pass:
- Add threshold calibration comparison UX over existing persisted runs so candidate models can be promoted with visible precision/recall/F1 and hard-negative counts.
Operator YOLOv8s hard-negative model benchmark (2026-07-08)
Changed:
- No repository code, API contract, migration, UI or application behavior was changed in this pass.
- Downloaded the official Ultralytics YOLOv8s base model manually as an operator/runtime asset on Tower at
/mnt/user/appdata/geointel/models/yolov8s.pt. - Trained a local hard-negative building detector on Tower from the existing exported operator tile dataset
yolo-building-tile-hardneg160r4. - Produced the trained runtime model artifact
/mnt/user/appdata/geointel/models/geointel-building-yolov8s-hardneg160r4e50.pt, mounted in the container as/app/models/geointel-building-yolov8s-hardneg160r4e50.pt. - Verified the live model catalog exposes the trained model as
geointel-building-yolov8s-hardneg160r4e50-ptwith SHA2569bf71ad4742048ac77f07060b677bacd9757b8d310497fcada334d543e320d19, size22473194,will_download_models=falseandactive=false. - Reused existing persisted dense QA and hard-negative benchmark runs through the live API; no external provider fetching and no fake data were introduced.
Training evidence:
- Base model:
/app/models/yolov8s.pt. - Base model SHA256:
1f47a78bf100391c2a140b7ac73a1caae18c32779be7d310658112f7ac9aa78a. - Training run:
/app/storage/training/operator-yolo/geointel-building-yolov8s-hardneg160r4e50. - Best checkpoint copied to:
/app/models/geointel-building-yolov8s-hardneg160r4e50.pt. - Final validation from Ultralytics: precision
0.449, recall0.404, mAP500.322, mAP50-950.110.
Live benchmark evidence:
- Created 24 persisted rescored detection runs with
model_asset_id=geointel-building-yolov8s-hardneg160r4e50-pt. - Dense persisted QA matrix results at IoU
0.1:- Four dense benchmark scenes saturated at 300 detections across thresholds
0.05,0.15and0.25. - Dense F1 scores observed:
0.6380,0.5627,0.5247,0.4678. - Dense precision ranged from
0.7167to0.8600; recall ranged from0.3247to0.5749. - Mean IoU ranged from
0.3962to0.4465. - The sparse/forest scene improved as the threshold increased:
49detections and F10.1429at0.05;18detections and F10.3200at0.15;10detections and F10.4706at0.25.
- Four dense benchmark scenes saturated at 300 detections across thresholds
- Hard-negative detection counts:
kasterlee_bos:49at threshold0.05,18at0.15,10at0.25.lommel_heide:0at thresholds0.05,0.15and0.25.postel_bos:1at threshold0.05,0at0.15and0.25.
Assessment:
- The YOLOv8s hard-negative model is a materially better evaluation candidate than the previous tiny smoke models and is useful in dense building scenes.
- The model should not be made the silent default yet because
kasterlee_bosstill produces 10 hard-negative detections at threshold0.25. - Threshold
0.25is the safest observed operating point for the current candidate. - The next product step should be model-selection and threshold workflow hardening before any operator-facing default activation.
Operational note:
- Tower root SSH works with
widefrog_unraid_deployon the default SSH port22. - Gitea SSH works separately on port
222through thegitea-widefroghost alias andwidefrog_giteakey. - Do not test Unraid/root deploy access against port
222; that port belongs to Gitea and correctly rejectsroot. - Live HTTP API verification on
http://192.168.10.150:1202remained reachable.
Open:
- Add an operator-facing model selection/activation flow or documented command that can promote a chosen local model deliberately, with visible SHA256 and threshold guidance.
- Add more negative/background AOIs and a threshold calibration benchmark before activating this model by default.
Next recommended pass:
- Implement V1 model-catalog hardening: show available local model assets, make active model/threshold explicit, and prevent accidental silent default activation.
Sprint 123 Raster detection manifest handoff (2026-07-08)
Changed:
- Added a typed
RasterTileHandofffrontend contract so raster tile jobs can expose manifest path, tile count, tile size, overlap, tile-set id and source dataset provenance. - Updated the dataset workflow hook to retain the latest structured raster tile manifest alongside the existing manifest path.
- Updated Raster Controls to show manifest details and explicit Detection/Segmentation Lab handoff actions.
- Updated the Detection Lab handoff so a raster manifest selects
yolo-configured, selects the active raster dataset, applies threshold0.25, refreshes YOLO preflight and does not auto-select a local model asset. - Added linked tile manifest, manifest validation, tile count and
will_run_inferencevisibility to Detection Lab. - Added regression coverage in
backend/tests/test_sprint123_raster_detection_handoff_operational.py.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint123_raster_detection_handoff_operational.py -qfailed while the typed handoff, Raster Controls details and Detection Lab preflight indicators were absent. python -m pytest backend\tests\test_sprint123_raster_detection_handoff_operational.py -q(3 passed)python -m pytest backend\tests\test_sprint99_raster_ui_handoff.py backend\tests\test_sprint122_model_asset_activation_guardrails.py backend\tests\test_sprint120_model_asset_detection_workflow_smoke.py backend\tests\test_sprint123_raster_detection_handoff_operational.py -q(8 passed)python -m compileall backend/appcd frontend && npm run typecheckcd frontend && npm run build
Limitations:
- This pass improves the operator handoff and preflight visibility only. It does not change backend inference contracts, migrations, model files, provider fetching or automatic model promotion.
Next recommended pass:
- Add threshold calibration comparison UX so an operator can compare candidate thresholds before promoting a local model.
Sprint 133 Detection threshold calibration UX (2026-07-08)
Changed:
- Added a Detection Lab calibration comparison panel that combines existing persisted
DetectionRunReadrows with existing persistedQualityCheckRead/metric rows. - The panel shows confidence threshold, model, local model asset id, detection count, precision, recall, F1, false positives, false negatives and linked quality-check id.
- Added summary cards for best F1 candidate, best precision candidate and lowest false-positive pressure.
- Added a promotion guardrail that keeps model/threshold acceptance tied to QA evidence across AOIs instead of a single run.
- Passed project-level
qualityChecksinto Detection Lab without adding API routes, migrations or new AI execution behavior. - Added regression coverage in
backend/tests/test_sprint133_detection_threshold_calibration_ux.py. - Marked the threshold calibration UX item complete in
docs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint133_detection_threshold_calibration_ux.py -qfailed while the persisted calibration comparison UI was absent. python -m pytest backend\tests\test_sprint133_detection_threshold_calibration_ux.py -q(1 passed)python -m pytest backend\tests\test_sprint122_model_asset_activation_guardrails.py backend\tests\test_sprint123_raster_detection_handoff_operational.py backend\tests\test_sprint133_detection_threshold_calibration_ux.py -q(7 passed)cd frontend && npm run typecheckcd frontend && npm run build
Limitations:
- This is a persisted-run comparison surface only. It does not launch batch calibration sweeps from the browser and does not auto-promote model assets or thresholds.
Next recommended pass:
- Add a guided in-app calibration runner that can queue a small explicit threshold set for one selected raster/reference pair, reusing the existing detection and QA APIs.
Sprint 134 Guided detection calibration runner (2026-07-08)
Changed:
- Added an explicit guided calibration runner to Detection Lab for operator-selected confidence threshold sweeps.
- Added frontend detection workflow state for calibration thresholds, progress rows, running state and errors.
- The runner parses a space/comma/semicolon-separated threshold set, validates project/raster/reference/model/manifest/model-asset readiness and runs one existing
detectionApi.runplus one existing detection QA comparison per threshold. - Successful threshold rows report persisted analysis run/job/quality check ids, detection count, precision, recall, F1, false positives and false negatives.
- Added UI copy that this runs real configured YOLO jobs and QA comparisons and does not promote or mutate model files.
- Added regression coverage in
backend/tests/test_sprint134_guided_detection_calibration_runner.py. - Marked the guided calibration runner task complete in
docs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint134_guided_detection_calibration_runner.py -qfailed while the runner contract was absent. python -m pytest backend\tests\test_sprint134_guided_detection_calibration_runner.py -q(1 passed)python -m pytest backend\tests\test_sprint133_detection_threshold_calibration_ux.py backend\tests\test_sprint134_guided_detection_calibration_runner.py backend\tests\test_sprint122_model_asset_activation_guardrails.py backend\tests\test_sprint123_raster_detection_handoff_operational.py -q(8 passed)cd frontend && npm run typecheckcd frontend && npm run build
Limitations:
- The runner is intentionally sequential and explicit. It does not schedule background batches, compare multiple AOIs at once or promote model assets/thresholds automatically.
Next recommended pass:
- Add an evidence shortcut from each calibration row to the persisted QA evidence map/review flow so false positives and false negatives can be inspected faster.
Sprint 117 Safe local YOLO model activation (2026-07-06)
Changed:
- Added
scripts/configure_yolo_model.pyto configure an existing local YOLO model into the deployment.envfile without downloading model weights, loading a model or running inference. - The helper scans a mounted model directory for
.pt,.onnxand.enginefiles, refuses no-model and ambiguous multi-model states, and writes env updates only when--applyis provided. - Added regression coverage in
backend/tests/test_sprint119_yolo_model_configuration.pyfor no local model, ambiguous model selection, dry-run single model selection and env-file apply behavior. - Downloaded the official Ultralytics
yolov8n.ptsmoke model to Tower under/mnt/user/appdata/geointel/models/yolov8n.pt, recorded checksumf59b3d833e2ff32e194b5bb8e08d211dc7c5bdf144b90d2c8412c47ccfc83b36, and applied the env configuration with the local helper. - Hardened
YoloDetectionAdapter.predict_tileso non-RGB raster tile artifacts are converted to a temporary RGB image before YOLO inference while georeferencing remains driven by the tile manifest. - Wrapped YOLO prediction runtime errors as typed
DETECTION_INFERENCE_FAILEDAppErrors instead of leaking raw runtime exceptions through FastAPI. - Updated
scripts/README.md,deploy/unraid/README.md,backend/README.md,docs/AI_PIPELINES.md,docs/TODO.mdandCHANGELOG.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint119_yolo_model_configuration.py -qfailed whilescripts/configure_yolo_model.pywas absent. - Red step:
python -m pytest backend\tests\test_sprint8b_yolo_foundation.py -qfailed because single-band TIFF tiles were passed through as modeLand prediction runtime errors leaked as rawRuntimeError. python -m pytest backend\tests\test_sprint119_yolo_model_configuration.py -q(4 passed)python -m pytest backend\tests\test_sprint8b_yolo_foundation.py -q(12 passed)python -m py_compile scripts\configure_yolo_model.pypython -m compileall backend/appcd backend && python -m pytest -q(377 passed, existing Pydantic protected-namespace warnings remain)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(Run readiness check passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.shbash -n scripts/deploy_tower.sh- Tower deploy from commit
72ee623completed withGEOINTEL_INSTALL_AI=true; the all-in-one container is published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live API check passed:
GET /api/v1/detection/yolo/preflightreturned canonicaldatawithstatus=not_configured,YOLO_ENABLED=false,torch_version=2.12.1,ultralytics_version=8.4.89,will_download_models=falseandwill_run_inference=false. - Tower helper dry-run passed:
python scripts/configure_yolo_model.py --models-dir /mnt/user/appdata/geointel/models --env-file .env --jsonreturnedstatus=no_model_found, empty candidates and no env updates. - Tower model apply passed:
python scripts/configure_yolo_model.py --models-dir /mnt/user/appdata/geointel/models --env-file .env --model-file /mnt/user/appdata/geointel/models/yolov8n.pt --apply --jsonreturnedstatus=applied,YOLO_ENABLED=trueandYOLO_MODEL_PATH=/app/models/yolov8n.pt. - Live YOLO preflight with generated demo raster tile manifest passed with
status=ready,model_load_ok=true,manifest_valid=true,tile_paths_exist=true,tile_count=1,will_download_models=falseandwill_run_inference=false. - Live inference smoke before the RGB adapter fix reproduced the runtime bug: YOLOv8n expected 3 channels but the demo tile was single-band (
input[1, 1, 480, 640]). - Tower deploy from commit
add4768completed withGEOINTEL_INSTALL_AI=true; the all-in-one container is published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 3; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live YOLO preflight after the RGB adapter fix passed with generated demo raster tile manifest and
status=ready. - Live real YOLO inference smoke after the RGB adapter fix passed:
POST /api/v1/detection/runreturnedstatus=success, analysis runbbd80690-baf3-4e83-8ffb-fdcb07a70c0c, job9636ed10-bbde-463f-a47a-6d7706c81e19,detection_count=0and no error code. Zero detections is expected for the generic COCO smoke model on the synthetic demo raster. - Downloaded
keremberke/yolov8n-building-segmentationfrom Hugging Face as an explicit Tower runtime artifact at/mnt/user/appdata/geointel/models/yolov8n-building-segmentation.pt. - Recorded building-model checksum
152d6a9c5c76c9f2fd2fd5cc167efaed7c8c02e31002b15415899710f1d71f98, matching the Hugging Face file metadata forbest.pt. - Applied
.envwithYOLO_MODEL_PATH=/app/models/yolov8n-building-segmentation.ptthroughscripts/configure_yolo_model.py --model-file ... --apply. - Restarted the all-in-one container without rebuild; it remained healthy and published on
0.0.0.0:1202->80/tcp. - Live building-model preflight passed with
model_load_ok=true,dependencies_available=true,torch_version=2.12.1,ultralytics_version=8.4.89,will_download_models=falseandwill_run_inference=false. - Live building-model preflight with generated demo raster tile manifest passed with
status=ready. - Live real building-model YOLO inference smoke passed:
POST /api/v1/detection/runreturnedstatus=success, analysis runbe609d4a-3e01-42df-bca8-0d5a2289120d, job9c8bc26d-7753-4537-ab98-dc31b9029450,detection_count=0and no error code. Zero detections remains expected on the synthetic demo raster.
Open:
- A local YOLO smoke model is now present and configured on Tower, but it is the generic COCO
yolov8n.ptmodel. It proves the runtime path, not production-quality aerial building detection.
Limitations:
- The bundled Tower model file was placed as an operator/runtime artifact under appdata, not committed to Git.
- The configured model is a generic COCO model and should be replaced by a suitable aerial/building detector for meaningful GIS output.
- The active configured model is now a building segmentation YOLO model trained for satellite-building segmentation, but it is still a third-party Hugging Face PyTorch
.ptartifact and should be treated as an evaluation model until validated on local Belgian/Kempen orthophotos. - No model download behavior was added to the application; the manual operator placement remains explicit.
- If multiple local model files are present, the operator must choose one with
--model-fileso GeoIntel does not silently activate the wrong model.
Next recommended pass:
- Load a real georeferenced orthophoto/GeoTIFF for the target area, generate raster tiles, run the active building YOLO model and compare persisted detections against reference vector buildings through QA/QC.
Sprint 104 AI Lab action guardrails (2026-06-24)
Changed:
- Added explicit action guardrails below the Detection Lab and Segmentation Lab run-readiness panels.
- Detection now distinguishes
configuredmodel registry state from UI-runnable action state, blocking the explicit test/demo-onlymanual-fixture-detectorin the normal workbench run form. - Segmentation now distinguishes
configuredmodel registry state from UI-runnable action state, blocking the explicit test/demo-onlyfixture-segmenterin the normal workbench run form. - Updated run button disabled conditions to use the new readiness/action state.
- Added compact guardrail styling and regression coverage in
backend/tests/test_sprint104_ai_lab_action_guardrails.py. - Updated
CHANGELOG.mdanddocs/TODO.md.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint104_ai_lab_action_guardrails.py -qfailed while the action guardrails and CSS contracts were absent. python -m pytest backend\tests\test_sprint104_ai_lab_action_guardrails.py -q(3 passed)python -m pytest backend\tests\test_sprint103_ai_lab_run_readiness.py backend\tests\test_sprint104_ai_lab_action_guardrails.py -q(6 passed)python -m compileall backend/appcd backend && python -m pytest -q(330 passed)cd frontend && npm run typecheckcd frontend && npm run buildbash scripts/run_readiness_check.sh(330 passed; frontend typecheck/build passed; Alembic head202606120900; live smoke syntax passed)cd backend && python -m alembic heads(202606120900 (head))cd backend && python -m alembic upgrade head --sqlbash -n scripts/live_migration_smoke.sh- Tower deploy from commit
0bc3b2fcompleted; all-in-one container published on0.0.0.0:1202->80/tcp. - Deploy-time live migration smoke passed after the database became ready on attempt 2; PostGIS reported
3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1, required runtime schema objects were present and Alembic head was202606120900. - Deploy-time browser runtime verification passed for frontend, API proxy and icon.
- Live smoke passed:
bash scripts/verify_demo_raster_workflow.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_default_state.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_workbench_interactions.sh http://192.168.10.150:1202. - Live smoke passed:
bash scripts/verify_browser_runtime.sh http://192.168.10.150:1202. - Internal Codex browser validation passed against
http://192.168.10.150:1202: AI Labs opened cleanly; run action guardrails rendered; Detection and Segmentation run buttons were disabled without a raster dataset; selecting explicit fixture models kept both run buttons disabled withFixture model is explicit test/demo-onlyandFixture segmenter is explicit test/demo-only; desktop and mobile viewports had no horizontal overflow and no console warnings/errors.
Open:
- None for this pass.
Limitations:
- Frontend action-guardrail guidance only; no backend API, persistence, migration, provider fetching, AI dependency or model execution behavior changed.
Next recommended pass:
- Continue with V1 usability work that reduces operator confusion without expanding frozen product scope.
Sprint 142 Calibration evidence response uniqueness (2026-07-08)
Changed:
- Hardened
scripts/export_detection_calibration_evidence.shso calibration evidence response files include both confidence threshold and quality-check id. - Prevented same-threshold runs from different model assets or calibration jobs from overwriting each other before portfolio assembly.
- Extended the multi-AOI calibration evidence portfolio regression test with two Geel runs at the same threshold and distinct quality checks.
Tested:
- Red step:
python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py -qfailed because only two evidence features were retained when three same-threshold responses were expected. python -m pytest backend\tests\test_sprint139_multi_aoi_calibration_evidence_portfolio.py backend\tests\test_sprint138_calibration_evidence_bundle_smoke.py backend\tests\test_sprint137_browser_calibration_summary_evidence_script.py backend\tests\test_sprint125_detection_calibration_evidence_bundle.py -q(4 passed)bash -n scripts/export_detection_calibration_evidence.shbash -n scripts/assemble_detection_calibration_evidence_portfolio.shpython scripts\smoke_docs.pypython -m compileall backend/appbash scripts/run_readiness_check.sh(418 passed, frontend typecheck/build passed, Alembic head202606120900)- Tower pulled commit
5314f16and regenerated/mnt/user/appdata/geointel/artifacts/detection-calibration-portfolio/positive-aoi-expanded-20260708/output. - The regenerated portfolio contains 7 samples, 38,007 evidence features and no missing model metadata.
- Best runs are now preserved across same-threshold model comparisons: Geel, Mol, Turnhout, Retie, Balen, Herentals and Westerlo all select
geointel-building-yolov8n-expanded160e50-ptas their best scored run. - Tower container remained healthy on
0.0.0.0:1202->80/tcp.
Open:
- The expanded160e50 model is consistently best on the current positive AOI portfolio, but hard-negative/background AOI evidence still prevents blind default promotion.
Sprint 146 - Operator YOLO dataset quality audit
What changed
- Added
scripts/audit_operator_yolo_dataset_quality.pyto inspect generated operator YOLO tile datasets before further model training. - Added a focused pytest that creates a synthetic tile summary and YOLO label files, then verifies JSON/Markdown audit output and warning gates.
- Added the audit script to the readiness syntax gate.
- Documented the operator audit command in
scripts/README.md.
What was tested
python -m pytest backend\tests\test_sprint146_operator_yolo_dataset_quality_audit.py -qbash scripts/run_readiness_check.sh- Tower live audit after pulling commit
5898e54:yolo-building-tile-dataset:needs_attention; only 3 positive samples and no background negatives.yolo-building-tile-expanded160:ok; 10 samples, 8 positive samples, 360 tiles, 11,213 labels, no missing/invalid label rows.yolo-building-tile-hardneg160r4:needs_attention; repeated background negatives are 91.1% of negative tiles.yolo-building-tile-hardneg160r8:needs_attention; repeated background negatives are 95.4% of negative tiles.
Known limitations
- The audit is evidence tooling only. It does not modify datasets, train models, fetch external data or change active YOLO configuration.
- The report flags likely dataset risks, but final promotion decisions must still come from persisted detection QA/QC matrices and hard-negative benchmarks.
Next recommended pass
- Add more unique hard-negative/background AOIs before another hard-negative training run. The current label files are clean, so the bottleneck is dataset diversity and balance rather than label-file corruption.
Sprint 147 - Unique hard-negative AOI expansion
What changed
- Expanded
scripts/prepare_operator_real_data_samples.pywith six additional explicit background-candidate AOIs: Dessel-heide, Ravels-bos, Meerhout-bos, Geel-Bel, Arendonk-heide and Herenthout-bos. - Background candidates remain operator/runtime samples only. They are not product providers, not fixtures and not automatic app fetches.
- 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 the all-in-one Dockerfile training-runtime gap so
/app/scripts/train_operator_yolo_detector.shis also copied into the rebuilt container and marked executable. - Fixed
scripts/yolo_preflight.pyso it respectsYOLO_ENABLED,YOLO_MODEL_PATHandYOLO_MAX_TILESfrom 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 -qpython -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py backend\tests\test_sprint131_operator_sample_expansion.py -qpython -m pytest backend\tests\test_sprint13_yolo_preflight.py -q- Red/green Docker runtime guard for the training wrapper:
python -m pytest backend\tests\test_docker_runtime_config.py::test_all_in_one_dockerfile_copies_operator_scripts_for_runtime_use -q python -m pytest backend\tests\test_docker_runtime_config.py -qbash scripts/run_readiness_check.sh- Tower live operator sample prep:
- manifest samples: 16 total, 7 reference and 9 background candidates.
- background candidate GRB feature counts: Postel-bos 0, Lommel-heide 0, Kasterlee-bos 7, Dessel-heide 30, Ravels-bos 3, Meerhout-bos 20, Geel-Bel 17, Arendonk-heide 0, Herenthout-bos 90.
- Tower live tile export and audit for
yolo-building-tile-uniquehardneg160:- status
ok - 576 tiles, 346 positive, 230 negative
- 16 samples, 13 positive samples, 9 background samples
- 11,757 labels, 0 missing label files, 0 invalid label rows
- repeated background negative share 0.0
- status
- Tower all-in-one rebuild from commit
f949347withGEOINTEL_INSTALL_AI=true:- live migration smoke passed.
- browser runtime verification passed on
http://192.168.10.150:1202. /app/scripts/prepare_operator_real_data_samples.py,/app/scripts/export_operator_yolo_tile_dataset.pyand/app/scripts/audit_operator_yolo_dataset_quality.pyare present in the rebuilt container.- YOLO preflight with an existing raster tile manifest returned
status: ready,dependencies_available: true,model_file_exists: true,tile_paths_exist: true,will_download_models: falseandwill_run_inference: false.
Known limitations
- Some background candidates contain real GRB buildings. They are still useful as mixed rural/background samples, but the pure negative pressure currently comes mostly from Postel-bos, Lommel-heide and Arendonk-heide plus empty tiles inside sparse candidates.
- The rebuilt Tower image now contains the operator scripts automatically. The generated
yolo-building-tile-uniquehardneg160dataset is ready for a controlled training candidate, but no model has been promoted from it yet.
Next recommended pass
- Use
yolo-building-tile-uniquehardneg160as the next safer hard-negative training dataset candidate. Benchmark after training before changing defaults.
Sprint 152 - GRB reference paging for operator samples
What changed
- Fixed
scripts/prepare_operator_real_data_samples.pyso GRB GBG reference exports follow OGC APIrel=nextpagination links instead of silently trusting only the firstlimit=1000page. - Added operator controls:
--reference-page-limit/OPERATOR_GRB_PAGE_LIMIT, default1000.--reference-max-features/OPERATOR_GRB_MAX_FEATURES, default100000.
- Generated reference GeoJSON now records
source_urls,reference_pages_fetched,reference_truncated,reference_page_limitandreference_max_features. - Kept the change operator-only: no GeoIntel API route calls this helper, no product provider endpoint changed, no live GRB/OSM import was added, no migration changed and no YOLO model was activated.
What was tested
- RED:
python -m pytest backend\tests\test_sprint131_operator_sample_expansion.py::test_fetch_reference_follows_grb_next_links_until_complete -qfailed because only the first GRB page was persisted. - GREEN:
python -m pytest backend\tests\test_sprint131_operator_sample_expansion.py::test_fetch_reference_follows_grb_next_links_until_complete -q python -m pytest backend\tests\test_sprint127_operator_sample_quality_matrix.py backend\tests\test_sprint131_operator_sample_expansion.py -qpython -m py_compile scripts\prepare_operator_real_data_samples.pybash scripts/run_readiness_check.sh- Local live GRB paging smoke with
page_limit=2andmax_features=5fetched 3 source pages, returned 5 features and correctly markedreference_truncated=true. - Tower deploy from commit
a63d4eapassed live migration smoke and browser runtime verification onhttp://192.168.10.150:1202. - Tower one-sample Geel AOI1024 paging smoke passed with
/opt/geointel/venv/bin/pythonand produced 2,268 GRB reference features instead of the old 1,000-feature cap. - Tower full AOI1024 operator sample regeneration passed:
- Geel: 2,268 features, 3 GRB pages, not truncated.
- Mol: 1,993 features, 2 GRB pages, not truncated.
- Turnhout: 3,278 features, 4 GRB pages, not truncated.
- Herentals: 2,478 features, 3 GRB pages, not truncated.
- Balen: 1,343 features, 2 GRB pages, not truncated.
- Retie: 1,734 features, 2 GRB pages, not truncated.
- Westerlo: 1,133 features, 2 GRB pages, not truncated.
- Re-exported
/app/storage/operator-data/yolo-building-aoi1024-visible025from the regenerated paged references:- 144 tiles, 117 positive tiles, 27 negative tiles, 29,170 labels.
min_label_visible_ratio=0.25,negative_keep_ratio=1.0.
- Re-ran the Tower dataset audit:
- output:
/app/storage/operator-data/yolo-building-aoi1024-visible025-audit/operator_yolo_dataset_quality_audit.json - status remains
needs_attention - missing label files: 0
- invalid labels: 0
- median normalized box area:
0.000762939453125 - small-box share:
0.34744600617072335 - repeated background negative share: 0.0
- output:
Known limitations
- The Tower AOI1024 operator samples and tile dataset have now been regenerated from paged GRB references, but the tile audit still reports
needs_attentionbecause small clipped boxes remain common. - This does not make the Sprint 7B GRB provider a live product importer; it only fixes explicit operator sample preparation.
Next recommended pass
- Before another training run, improve label quality: either raise
--min-label-visible-ratio, increase tile size, reduce dense clipped-edge tiles or add cleaner AOIs. Do not activate or retrain from this dataset as-is without acknowledging the small-box warning.
Sprint 151 - Runtime GIS upload and AOI1024 YOLO candidate
What changed
- Fixed
scripts/train_operator_yolo_detector.shso the all-in-one image uses/opt/geointel/venv/bin/pythonby default when that AI venv exists. ExplicitPYTHON_BINstill wins, and local shells still fall back topython3. - Raised the Nginx request body limit to
250min bothfrontend/nginx.confanddeploy/unraid/nginx-all-in-one.confafter the live 1024px GeoTIFF upload path returned413 Request Entity Too Large. - Raised Nginx proxy read/send timeouts to
600safter the live low-threshold persisted YOLO/QA path reached504 Gateway Timeout. - Kept the change runtime-only: no API contract, persistence model, migration, model-download behavior or default model selection changed.
What was tested
- Red/green TDD guard for the training wrapper fallback:
python -m pytest backend\tests\test_sprint129_operator_yolo_training_dataset.py -q
- Red/green TDD guard for real GIS upload payload support:
python -m pytest backend\tests\test_docker_runtime_config.py::test_nginx_runtime_allows_real_gis_upload_payloads -q
- Red/green TDD guard for long AI/QA proxy requests:
python -m pytest backend\tests\test_docker_runtime_config.py::test_nginx_runtime_allows_long_ai_and_qa_requests -q
bash -n scripts/train_operator_yolo_detector.sh- Tower live model training on
/app/storage/operator-data/yolo-building-aoi1024-visible025:- output model:
/app/models/geointel-building-yolov8s-aoi1024visible025e50.pt - model asset id:
geointel-building-yolov8s-aoi1024visible025e50-pt - final Ultralytics validation: precision approximately
0.275, recall0.331, mAP500.188, mAP50-950.0716
- output model:
- Tower live runtime validation after deploy:
- browser/runtime verification passed on
http://192.168.10.150:1202 - the previous Geel 1024px upload
413no longer occurs - the previous Geel low-threshold persisted YOLO/QA
504no longer occurs - Geel
threshold=0.05completed with 2,612 detections, 5,091 raw candidates, 2,479 suppressed duplicates, precision0.06316998468606431, recall0.165and F10.09136212624584718
- browser/runtime verification passed on
- Full AOI1024 positive persisted QA matrix:
- Geel best F1:
0.09136212624584718at threshold0.05 - Turnhout best F1:
0.058721074894252295at threshold0.05 - Retie best F1:
0.15621436716077539at threshold0.15 - Westerlo best F1:
0.28703703703703703at threshold0.15
- Geel best F1:
- Full AOI1024 hard-negative/background matrix:
- pure empty Postel/Lommel/Arendonk samples stayed at or near zero detections
- mixed background candidates still produced false-positive pressure: max detections were
59at threshold0.25,107at0.15and226at0.05
- Fixed
scripts/build_detection_model_promotion_report.pyafter discovering it acceptedmulti_sample_quality_summary.jsonbut counted positive samples as0. The report now supports bothsamples[].runs[]portfolios anditems[]multi-sample summaries. - AOI1024 promotion report path:
artifacts/detection-model-promotion/aoi1024visible025e50-full/detection_model_promotion_report.md; recommendation remainsnone. - Corrected AOI1024 promotion decision after parser fix:
- threshold
0.05: 4 positive samples, 9 background samples, mean F10.13307746028311157, max background detections226 - threshold
0.15: 4 positive samples, 9 background samples, mean F10.13900227809255514, max background detections107 - threshold
0.25: 4 positive samples, 9 background samples, mean F10.09694707724016788, max background detections59
- threshold
Known limitations
- The AOI1024 tile audit is still
needs_attention: median normalized box area is below gate and small-box share remains high. - Several dense 1024 GRB reference exports reached the current 1000-feature source cap. Treat those samples as useful but potentially reference-capped until the provider query path supports paging or smaller dense AOIs are chosen.
- The trained model is intentionally inactive. It needs persisted detection QA/QC matrix evidence and background/hard-negative evidence before default promotion.
- The first completed persisted Geel QA run confirms the candidate is not promotion-ready: recall improves at low threshold, but false-positive pressure is too high.
- The complete positive/background evidence confirms the candidate is not promotion-ready. The bottleneck is label/source quality and sample design, not runtime configuration.
Next recommended pass
- Fix dense GRB reference completeness first: add provider-side paging or split dense AOIs so reference exports do not cap at 1000 features, then regenerate AOI1024 labels before another training run.
Sprint 153 - AOI1024 clean-label YOLOv8s candidate gate
What changed
- Built and audited AOI1024 label-quality candidate exports on Tower after the paged GRB reference regeneration:
- baseline
yolo-building-aoi1024-visible025: 144 tiles, 117 positive, 27 negative, 29,170 labels, auditneeds_attention, median normalized box area0.000762939453125, small-box share0.34744600617072335. yolo-building-aoi1024-visible050: 144 tiles, 117 positive, 27 negative, 28,552 labels, auditneeds_attention, small-box share0.34463435135892406.yolo-building-aoi1024-visible025-tile640: 45,529 labels, auditneeds_attention, small-box share0.4952667530584902.yolo-building-aoi1024-visible025-tile384: 400 tiles, 311 positive, 89 negative, 46,423 labels, auditok, small-box share0.215281218361588.yolo-building-aoi1024-visible050-minpx8: 144 tiles, 117 positive, 27 negative, 21,530 labels, auditok, median normalized box area0.0010299684375, small-box share0.14681839294008361.
- baseline
- Selected
/app/storage/operator-data/yolo-building-aoi1024-visible050-minpx8for the next controlled candidate because it passes the label audit while preserving the 512px runtime scale. - Trained Tower-local inactive model asset:
- model path:
/app/models/geointel-building-yolov8s-aoi1024clean512e50.pt - asset id:
geointel-building-yolov8s-aoi1024clean512e50-pt - SHA256:
7cfadb684dd56623d2e35ebd65593211d3051908c87121bef438b231d3e47cce - training summary:
/app/storage/training/operator-yolo/geointel-building-yolov8s-aoi1024clean512e50/training_summary.json - base model:
/app/models/yolov8s.pt - epochs: 50
- image size: 512
- batch size: 2
- device: CPU
- final Ultralytics validation on
best.pt: precision0.441, recall0.380, mAP500.265, mAP50-950.096.
- model path:
- Verified the live model catalog reports the candidate as
status=available,active=falseandwill_download_models=false.
What was tested
- Tower training command:
docker exec -e OPERATOR_YOLO_DATASET_DIR=/app/storage/operator-data/yolo-building-aoi1024-visible050-minpx8 -e YOLO_BASE_MODEL_PATH=/app/models/yolov8s.pt -e TRAIN_OUTPUT_DIR=/app/storage/training/operator-yolo -e TRAIN_RUN_NAME=geointel-building-yolov8s-aoi1024clean512e50 -e TRAIN_MODEL_OUTPUT_PATH=/app/models/geointel-building-yolov8s-aoi1024clean512e50.pt -e TRAIN_EPOCHS=50 -e TRAIN_IMGSZ=512 -e TRAIN_BATCH=2 -e TRAIN_WORKERS=0 -e TRAIN_DEVICE=cpu geointel bash /app/scripts/train_operator_yolo_detector.sh
- Full seven-reference AOI1024 persisted positive QA matrix:
- command used
scripts/run_multi_sample_detection_quality_matrix.shwith manifest/mnt/user/appdata/geointel/storage/operator-data/operator-samples-1024/operator_samples_manifest.json, samplesgeel mol turnhout herentals balen retie westerlo, modelgeointel-building-yolov8s-aoi1024clean512e50-pt, tile512, overlap64, thresholds0.25 0.15 0.05and IoU threshold0.25. - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/aoi1024clean512e50-full/multi_sample_quality_summary.json - threshold
0.05: 7 positive samples, mean F10.4723513253430784, mean precision0.44861169484563357, mean recall0.5039340859731523, min F10.4442082890541977. - threshold
0.15: 7 positive samples, mean F10.4753322215541376, mean precision0.6673270868402211, mean recall0.37207511021815726, min F10.4055555555555556. - threshold
0.25: 7 positive samples, mean F10.31021575247724875, mean precision0.8163316419273472, mean recall0.19608909809008596, min F10.16430903155603915.
- command used
- Full nine-sample hard-negative/background matrix:
- command used
scripts/run_operator_hard_negative_detection_matrix.shwith the same AOI1024 manifest, modelgeointel-building-yolov8s-aoi1024clean512e50-pt, tile512, overlap64and thresholds0.25 0.15 0.05. - output:
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/aoi1024clean512e50-full/hard_negative_matrix_summary.json - threshold
0.05: total background detections488, max sample detections137. - threshold
0.15: total background detections269, max sample detections75. - threshold
0.25: total background detections205, max sample detections55.
- command used
- Promotion report:
- command used
scripts/build_detection_model_promotion_report.pywith--min-positive-samples 7,--min-background-samples 9,--min-mean-f1 0.25and--max-background-detections-per-sample 0. - output:
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/aoi1024clean512e50-full/detection_model_promotion_report.md - recommendation:
none.
- command used
Known limitations
- The clean-label model is materially stronger on positive reference AOIs than the previous AOI1024-visible025 candidate, but it is still not safe as a V1 default because hard-negative/background false positives remain high in mixed wooded AOIs.
- The likely bottleneck has shifted from label-file integrity to discriminating buildings from visually similar background structures and wooded-edge artifacts.
- The model remains inactive. No default model, API contract, migration, provider fetching or download behavior changed.
Next recommended pass
- Build a background-aware training pass instead of another positive-only clean-label pass: combine the
visible050-minpx8positives with stronger unique hard-negative/background retention, then re-run the same seven-positive/nine-background promotion gate before any activation.
Sprint 154 - Background-aware AOI1024 YOLOv8s candidate gate
What changed
- Built a background-aware AOI1024 tile dataset on Tower from the clean positive labels plus explicit background retention:
- dataset path:
/app/storage/operator-data/yolo-building-aoi1024-bgaware512r3 - audit path:
/mnt/user/appdata/geointel/storage/operator-data/yolo-building-aoi1024-bgaware512r3-audit/operator_yolo_dataset_quality_audit.json - tile count:
162 - positive tiles:
117 - negative tiles:
45 - label count:
21530 - background negative repeat:
3 - audit status:
ok - warnings:
[]
- dataset path:
- Trained Tower-local inactive model asset:
- model path:
/app/models/geointel-building-yolov8s-aoi1024bg512r3e50.pt - asset id:
geointel-building-yolov8s-aoi1024bg512r3e50-pt - SHA256:
e0980572aac90e7efc514608eb16d7de5bfbf27a4bbec04e7bc1bc8c02f9601f - training summary:
/app/storage/training/operator-yolo/geointel-building-yolov8s-aoi1024bg512r3e50/training_summary.json - base model:
/app/models/yolov8s.pt - epochs:
50 - image size:
512 - batch size:
2 - device: CPU
- final Ultralytics validation on
best.pt: precision0.440, recall0.362, mAP500.251, mAP50-950.0878.
- model path:
- Verified the live model catalog reports the candidate as
status=available,active=falseandwill_download_models=false. - No API contract, migration, provider fetching, fake detection data, model download behavior or active model default changed.
What was tested
- Tower training command:
docker exec -e OPERATOR_YOLO_DATASET_DIR=/app/storage/operator-data/yolo-building-aoi1024-bgaware512r3 -e YOLO_BASE_MODEL_PATH=/app/models/yolov8s.pt -e TRAIN_OUTPUT_DIR=/app/storage/training/operator-yolo -e TRAIN_RUN_NAME=geointel-building-yolov8s-aoi1024bg512r3e50 -e TRAIN_MODEL_OUTPUT_PATH=/app/models/geointel-building-yolov8s-aoi1024bg512r3e50.pt -e TRAIN_EPOCHS=50 -e TRAIN_IMGSZ=512 -e TRAIN_BATCH=2 -e TRAIN_WORKERS=0 -e TRAIN_DEVICE=cpu geointel bash /app/scripts/train_operator_yolo_detector.sh
- Full seven-reference AOI1024 persisted positive QA matrix:
- command used
scripts/run_multi_sample_detection_quality_matrix.shwith manifest/mnt/user/appdata/geointel/storage/operator-data/operator-samples-1024/operator_samples_manifest.json, samplesgeel mol turnhout herentals balen retie westerlo, modelgeointel-building-yolov8s-aoi1024bg512r3e50-pt, tile512, overlap64, thresholds0.25 0.15 0.05and IoU threshold0.25. - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/aoi1024bg512r3e50-full/multi_sample_quality_summary.json - threshold
0.05: 7 positive samples, mean F10.4908049127242224, mean precision0.468604, mean recall0.520016, total detections15277. - threshold
0.15: 7 positive samples, mean F10.5074022485589402, mean precision0.636639, mean recall0.424258, total detections9186. - threshold
0.25: 7 positive samples, mean F10.44378879337957716, mean precision0.762683, mean recall0.316314, total detections5584.
- command used
- Conservative seven-reference AOI1024 persisted positive QA matrix:
- command used the same manifest/model/tile/overlap with thresholds
0.35 0.45 0.60. - output:
/mnt/user/appdata/geointel/artifacts/detection-quality-matrix/multi-sample/aoi1024bg512r3e50-high-threshold/multi_sample_quality_summary.json - threshold
0.35: 7 positive samples, mean F10.32086574003576274, mean precision0.840006, mean recall0.202135, total detections3106. - threshold
0.45: 7 positive samples, mean F10.20093433626447627, mean precision0.885043, mean recall0.116348, total detections1592. - threshold
0.60: 7 positive samples, mean F10.06640476239173489, mean precision0.871611, mean recall0.035083, total detections418.
- command used the same manifest/model/tile/overlap with thresholds
- Full nine-sample hard-negative/background matrix:
- command used
scripts/run_operator_hard_negative_detection_matrix.shwith the AOI1024 manifest, modelgeointel-building-yolov8s-aoi1024bg512r3e50-pt, tile512, overlap64and thresholds0.25 0.15 0.05. - output:
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/aoi1024bg512r3e50-full/hard_negative_matrix_summary.json - threshold
0.05: total background detections638, max sample detections184. - threshold
0.15: total background detections390, max sample detections103. - threshold
0.25: total background detections278, max sample detections75.
- command used
- Conservative nine-sample hard-negative/background matrix:
- output:
/mnt/user/appdata/geointel/artifacts/detection-hard-negatives/aoi1024bg512r3e50-high-threshold/hard_negative_matrix_summary.json - threshold
0.35: total background detections198, max sample detections55. - threshold
0.45: total background detections148, max sample detections38. - threshold
0.60: total background detections76, max sample detections18.
- output:
- Promotion reports:
- balanced thresholds report:
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/aoi1024bg512r3e50-full/detection_model_promotion_report.md - conservative thresholds report:
/mnt/user/appdata/geointel/artifacts/detection-model-promotion/aoi1024bg512r3e50-high-threshold/detection_model_promotion_report.md - recommendation:
none.
- balanced thresholds report:
Known limitations
- The background-aware model is the strongest positive-AOI candidate so far and is usable as an explicit review/demo candidate, especially at threshold
0.15for balance or0.35for conservative high-precision review. - It is still not safe as a V1 default because the full background-candidate gate fails
background_false_positive_pressure. - Some
background_candidateAOIs contain GRB reference buildings and should be split into pure-empty negatives versus sparse-positive contextual samples before the next gate; otherwise the hard-negative score remains intentionally conservative but not perfectly diagnostic. - The model remains inactive. Operators can select it explicitly from the local model asset catalog.
Next recommended pass
- Build a V1 operator detection profile layer in the UI/docs: expose
balanced(threshold=0.15) andconservative review(threshold=0.35) as explicit choices for local model assets, with clear warning that the model is not a default-approved detector. - Clean the background corpus classification: separate pure-empty AOIs from sparse-building contextual AOIs, then retrain or recalibrate against that cleaner gate.
Sprint 155 - Detection operator profiles
What changed
- Added
frontend/src/components/detection/detectionProfiles.tswith explicit operator profiles for the inactivegeointel-building-yolov8s-aoi1024bg512r3e50-ptlocal model asset. - Exposed two deliberate Detection Lab actions:
balanced-review: confidence threshold0.15, positive-AOI F10.5074022485589402, precision0.636639, recall0.424258, max background detections103.conservative-review: confidence threshold0.35, positive-AOI F10.32086574003576274, precision0.840006, recall0.202135, max background detections55.
- Applying a profile selects
yolo-configured, the local model asset id and the profile threshold. It does not auto-select assets on model catalog load and does not promote the candidate as a default detector. - Detection Lab now marks both profiles as
Candidate only - not default-approvedbecause the promotion recommendation remainsnone. - Updated frontend, AI pipeline and TODO documentation.
What was tested
- Added regression coverage in
backend/tests/test_sprint155_detection_operator_profiles.py. - Ran
python -m pytest tests/test_sprint155_detection_operator_profiles.py tests/test_sprint122_model_asset_activation_guardrails.py -q. - Ran
python -m pytestinbackend: 435 passed. - Ran
python -m compileall backend/app. - Ran
cd frontend && npm run typecheck. - Ran
cd frontend && npm run build. - Ran
bash scripts/run_readiness_check.sh. - Ran
cd backend && python -m alembic headsandcd backend && python -m alembic upgrade head --sql. - Ran
bash -n scripts/live_migration_smoke.sh.
Known limitations
- The profiles are review/demo aids only. The background corpus still needs to be split into pure-empty negatives and sparse-building contextual AOIs before retraining or recalibrating for a default detector decision.
- No backend API contract, migration, provider fetching, fake detection output, model download behavior or active runtime default changed.
Sprint 156 - Background corpus classification
What changed
- Added explicit background category classification to operator sample preparation:
pure_empty_negativewhen a background candidate has zero GRB reference buildings.sparse_building_contextwhen a background candidate has one or more GRB reference buildings.reference_aoifor normal positive reference samples.
- Persisted
background_categoryinto generated operator sample manifests and reference GeoJSON metadata. - Added
OPERATOR_BACKGROUND_CATEGORIEStoscripts/run_operator_hard_negative_detection_matrix.shso the strict default-promotion hard-negative gate can run only onpure_empty_negativesamples, whilesparse_building_contextsamples can be reviewed separately. - Preserved
background_categoryin YOLO tile export metadata so negative-tile provenance survives training dataset audits. - Updated operator pipeline docs, TODO and changelog.
What was tested
- Added regression coverage in
backend/tests/test_sprint156_background_corpus_classification.py. - Ran
python -m pytest tests/test_sprint156_background_corpus_classification.py -q. - Ran
python -m pytest tests/test_sprint156_background_corpus_classification.py tests/test_sprint131_operator_sample_expansion.py tests/test_sprint132_operator_hard_negative_matrix.py tests/test_sprint130_operator_yolo_tile_dataset.py -q: 17 passed. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 439 passed. - Ran
cd frontend && npm run typecheck. - Ran
cd frontend && npm run build. - Ran
bash scripts/run_readiness_check.sh. - Ran
cd backend && python -m alembic headsandcd backend && python -m alembic upgrade head --sql. - Ran
bash -n scripts/live_migration_smoke.shandbash -n scripts/run_operator_hard_negative_detection_matrix.sh.
Known limitations
- This pass adds the cleaner corpus/gate contract only. It does not regenerate Tower manifests, retrain YOLO, rerun the live hard-negative matrices or change any model default.
- No backend API contract, database migration, provider fetching, fake detection output or model download behavior changed.
Next recommended pass
- Redeploy/rebuild the runtime scripts, regenerate the operator sample manifest, then run:
OPERATOR_BACKGROUND_CATEGORIES="pure_empty_negative"for the strict default-promotion false-positive gate.OPERATOR_BACKGROUND_CATEGORIES="sparse_building_context"for contextual review evidence.
- Retrain or recalibrate the inactive AOI1024 local model candidate only after those two matrices are available.
Sprint 157 - Background split matrix runner
What changed
- Added
scripts/run_background_corpus_split_matrix.shas the operator wrapper for the next Tower run. - The wrapper runs
scripts/run_operator_hard_negative_detection_matrix.shtwice:OPERATOR_BACKGROUND_CATEGORIES="pure_empty_negative"for the strict default-promotion false-positive gate.OPERATOR_BACKGROUND_CATEGORIES="sparse_building_context"for review-only contextual evidence.
- Added
scripts/build_background_corpus_split_report.pyto combine both summaries into:background_corpus_split_summary.jsonbackground_corpus_split_summary.md
- The combined report records
strict_default_gate,context_review,passes_zero_detection_gate, max detection counts and the recommended next step. - Added readiness coverage for the new Python and Bash scripts.
- Updated operator pipeline docs, TODO and changelog.
What was tested
- Added regression coverage in
backend/tests/test_sprint157_background_split_matrix_runner.py. - Ran
python -m pytest tests/test_sprint157_background_split_matrix_runner.py -q. - Ran
python -m pytest tests/test_sprint157_background_split_matrix_runner.py tests/test_sprint156_background_corpus_classification.py tests/test_sprint132_operator_hard_negative_matrix.py -q: 9 passed. - Ran
python -m py_compile scripts/build_background_corpus_split_report.py. - Ran
bash -n scripts/run_background_corpus_split_matrix.sh. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 443 passed. - Ran
cd frontend && npm run typecheck. - Ran
cd frontend && npm run build. - Ran
bash scripts/run_readiness_check.sh. - Ran
cd backend && python -m alembic headsandcd backend && python -m alembic upgrade head --sql. - Ran
bash -n scripts/live_migration_smoke.shandbash -n scripts/run_background_corpus_split_matrix.sh.
Known limitations
- This pass adds orchestration/report tooling only. It does not run live inference on Tower, retrain YOLO, rerun the split matrices or change any model default.
- No backend API contract, database migration, provider fetching, fake detection output or model download behavior changed.
Next recommended pass
- Rebuild/redeploy the runtime, regenerate the operator manifest if needed, then run
scripts/run_background_corpus_split_matrix.shagainsthttp://192.168.10.150:1202. - Use the emitted split report to decide whether to retrain, recalibrate thresholds or keep the AOI1024 candidate operator-only.
Sprint 158 - Split-aware promotion report
What changed
- Added
--background-split-summarysupport toscripts/build_detection_model_promotion_report.py. - The promotion report now resolves a split report's
pure_empty_negativesource summary as the strict default-promotion background gate. - The same report records
sparse_building_contextas review-only evidence, including source path and detection-pressure context, without counting it as a default-promotion blocker. - Kept direct
--hard-negative-summarysupport unchanged for older operator workflows. - Updated operator pipeline docs, TODO and changelog.
What was tested
- Red step:
python -m pytest tests/test_sprint158_promotion_report_split_background.py -qfailed because the promotion report required--hard-negative-summaryand did not yet accept--background-split-summary. - Ran
python -m pytest tests/test_sprint158_promotion_report_split_background.py -q: 1 passed. - Ran
python -m pytest tests/test_sprint143_detection_model_promotion_report.py tests/test_sprint157_background_split_matrix_runner.py -q: 7 passed. - Ran
python -m py_compile scripts/build_detection_model_promotion_report.py scripts/build_background_corpus_split_report.py. - Ran
python -m pytest tests/test_sprint158_promotion_report_split_background.py tests/test_sprint143_detection_model_promotion_report.py tests/test_sprint157_background_split_matrix_runner.py -q: 8 passed. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 444 passed, 17 existing Pydantic namespace warnings. - Ran
cd frontend && npm run typecheck. - Ran
cd frontend && npm run build. - Ran
bash scripts/run_readiness_check.sh: passed. - Ran
cd backend && python -m alembic heads:202606120900 (head). - Ran
cd backend && python -m alembic upgrade head --sql. - Ran
bash -n scripts/live_migration_smoke.sh.
Known limitations
- This pass is report/tooling only. It does not run live split matrices on Tower, retrain YOLO, change a model default, change API contracts, change migrations, fetch providers, download model weights or create fake detections.
- The AOI1024 background-aware local model remains explicit operator-review only until the split matrices plus positive-AOI QA/QC evidence pass the documented gates.
Next recommended pass
- After redeploy, run
scripts/run_background_corpus_split_matrix.shon Tower forgeointel-building-yolov8s-aoi1024bg512r3e50-pt. - Feed the generated
background_corpus_split_summary.jsonintoscripts/build_detection_model_promotion_report.py --background-split-summarytogether with the seven-AOI positive summary. - If pure-empty false-positive pressure still fails, retrain or recalibrate before any default activation. If pure-empty passes, inspect sparse-context review evidence before deciding whether to keep the model operator-only or prepare a guarded default-candidate decision.
Sprint 159 - Split-background promotion workflow wrapper
What changed
- Added
scripts/run_split_background_promotion_workflow.sh. - The wrapper runs
scripts/run_background_corpus_split_matrix.sh, verifies the emittedbackground_corpus_split_summary.json, then callsscripts/build_detection_model_promotion_report.py --background-split-summary. - The wrapper requires
PROMOTION_POSITIVE_PORTFOLIO_PATHand exposes promotion gate overrides through environment variables. - Added readiness syntax coverage for the new wrapper.
- Updated operator pipeline docs, TODO and changelog.
What was tested
- Red step:
python -m pytest tests/test_sprint159_split_promotion_workflow.py -qfailed because the wrapper script and readiness syntax check did not exist. - Ran
python -m pytest tests/test_sprint159_split_promotion_workflow.py -q: 2 passed. - Ran
bash -n scripts/run_split_background_promotion_workflow.sh. - Ran
python -m pytest tests/test_sprint159_split_promotion_workflow.py tests/test_sprint158_promotion_report_split_background.py tests/test_sprint157_background_split_matrix_runner.py -q: 7 passed. - Ran
bash -n scripts/run_readiness_check.sh. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 446 passed, 17 existing Pydantic namespace warnings. - Ran
cd frontend && npm run typecheck. - Ran
cd frontend && npm run build. - Ran
cd backend && python -m alembic heads:202606120900 (head). - Ran
cd backend && python -m alembic upgrade head --sql. - Ran
bash -n scripts/live_migration_smoke.sh. - Ran
bash scripts/run_readiness_check.sh: passed.
Known limitations
- This pass adds operator orchestration only. It does not run live inference locally, retrain YOLO, activate a model default, change backend API contracts, change migrations, fetch providers, fetch weights or create fake detections.
http://192.168.10.150:1202is reachable from this workstation, butssh -p 222 root@192.168.10.150returnedPermission denied (publickey). Port222appears to be the Gitea SSH endpoint rather than an Unraid shell endpoint, so Docker rebuild/restart still needs the existing Unraid deployment path or a separate shell-access route.
Next recommended pass
- Redeploy/pull commit on Tower through the existing Gitea/Unraid flow.
- Run:
PROMOTION_POSITIVE_PORTFOLIO_PATH=... bash scripts/run_split_background_promotion_workflow.sh http://192.168.10.150:1202
- Review the generated split-aware promotion report before any retraining, recalibration or default-model decision.
Sprint 160 - Split-background promotion preflight
What changed
- Added
--preflight-onlytoscripts/run_split_background_promotion_workflow.sh. - Preflight now checks:
PROMOTION_POSITIVE_PORTFOLIO_PATHexists and is readable.OPERATOR_SAMPLE_MANIFEST_PATHexists and is readable.- the manifest contains both
pure_empty_negativeandsparse_building_contextbackground categories. - Python and
curlare available. - the runtime frontend API proxy returns the canonical
dataenvelope from/api/v1/projects.
- Updated operator docs, TODO and changelog with the quick post-redeploy preflight command.
What was tested
- Red step:
python -m pytest tests/test_sprint159_split_promotion_workflow.py -qfailed because--preflight-onlywas not yet present. - Ran
python -m pytest tests/test_sprint159_split_promotion_workflow.py -q: 3 passed. - Ran
bash -n scripts/run_split_background_promotion_workflow.sh. - Ran
python -m pytest tests/test_sprint159_split_promotion_workflow.py tests/test_sprint158_promotion_report_split_background.py -q: 4 passed. - Ran
curl.exe -fsS http://192.168.10.150:1202/api/v1/projects: runtime API proxy returned a canonicaldataenvelope. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 447 passed, 17 existing Pydantic namespace warnings. - Ran
cd frontend && npm run typecheck. - Ran
cd frontend && npm run build. - Ran
cd backend && python -m alembic heads:202606120900 (head). - Ran
cd backend && python -m alembic upgrade head --sql. - Ran
bash -n scripts/live_migration_smoke.sh. - Ran
bash scripts/run_readiness_check.sh: passed.
Known limitations
- Preflight is intentionally non-mutating and does not run inference, create datasets, retrain models, activate defaults, fetch providers, fetch weights or change API/database behavior.
- Full split-background matrix execution still requires redeploying this commit to the Tower/Unraid runtime and running the wrapper in the runtime checkout where the positive portfolio and operator manifest artifacts exist.
Next recommended pass
- Redeploy/pull on Tower, then run:
PROMOTION_POSITIVE_PORTFOLIO_PATH=... OPERATOR_SAMPLE_MANIFEST_PATH=... bash scripts/run_split_background_promotion_workflow.sh --preflight-only http://192.168.10.150:1202
- If preflight passes, rerun without
--preflight-onlyto generate the split summary and split-aware promotion report.
Sprint 161 - Widescreen workbench support
What changed
- Added dedicated frontend CSS breakpoints for
1800pxand2200pxworkbench widths. - Wide screens now expand the workbench shell columns, inspector padding, Data/Analysis/AI/Export grids and Map workspace controls without changing workflows.
- Ultrawide screens prioritize the MapLibre review frame with a taller map and wider toolbar/inspection layout.
- Added static regression coverage for widescreen/ultrawide layout contracts.
- Updated frontend README, TODO and changelog.
What was tested
- Red step:
python -m pytest tests/test_sprint161_widescreen_workbench.py -qfailed before the widescreen CSS contracts existed. - Ran
python -m pytest tests/test_sprint161_widescreen_workbench.py tests/test_sprint53_selection_ergonomics.py tests/test_sprint85_map_workspace_density.py tests/test_sprint113_calm_workbench_layout.py -q: 13 passed. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 449 passed, 17 existing Pydantic protected-namespace warnings. - Ran
npm run typecheckinfrontend. - Ran
npm run buildinfrontend. - Ran
python -m alembic headsinbackend:202606120900 (head). - Ran
python -m alembic upgrade head --sqlinbackend. - Ran
bash -n scripts/live_migration_smoke.sh. - Ran
bash scripts/run_readiness_check.sh: passed. - Ran a local Vite preview visual/layout check at
2560x1080through the in-app browser. The workbench measured no horizontal overflow, shell columns240px 1889px 416px, and the Map workspace rendered an832pxhigh MapLibre frame with the road basemap visible.
Known limitations
- Local
docker compose configcould not be run on this Windows workstation because the Docker CLI is not installed or not onPATH. - The live Tower/Unraid runtime at
http://192.168.10.150:1202will show the widescreen changes only after redeploying this commit. - The local preview showed an expected API error because it served the built frontend without the Docker backend proxy; the layout and MapLibre basemap rendered correctly.
Next recommended pass
- Redeploy/pull this commit on Tower/Unraid and visually recheck
http://192.168.10.150:1202on the actual widescreen monitor. - Continue with the split-background promotion preflight/matrix flow once the runtime has been rebuilt.
Sprint 161 - Tower redeploy and live widescreen runtime verification
What changed
- Redeployed Tower/Unraid from commit
07ea8dbwith the existing all-in-one deploy path. - Preserved the remote AI runtime setting by deploying with
GEOINTEL_INSTALL_AI=true. - The deployed
geointelcontainer is healthy and published on0.0.0.0:1202->80/tcp. - No application code, API contract, migration, provider fetching, model default, model download behavior or fake data path changed in this pass.
What was tested
- Verified Tower SSH access through
root@192.168.10.150with thewidefrog_unraid_deploykey. - Verified the remote checkout reset to
07ea8db. - Ran the Tower deploy script with AI dependencies enabled.
- Deploy build produced frontend asset
assets/index-CxHabIo7.css; the live CSS contains the Sprint 161 wide/ultrawide layout rules including15rem minmax(0,1fr) 26remandmin-height:42rem. - Live migration smoke passed inside the
geointelcontainer:- database connection ok
- PostGIS
3.6 - database collation ok
- required runtime schema objects ok
- Alembic head
202606120900
- Browser runtime smoke passed against
http://192.168.10.150:1202. - GIS runtime smoke passed against
http://192.168.10.150:1202. - Health endpoint returned
status=ok,database=ok. - YOLO preflight returned:
dependencies_available=truemodel_file_exists=truetorch_version=2.13.0ultralytics_version=8.4.92will_download_models=falsewill_run_inference=falsewithout a tile manifest
Known limitations
- The optional local screenshot script could not run in this Windows runner because Node cannot import Playwright here. The script remains optional and reports the documented install commands.
- The in-app browser could not attach a fresh browser-use tab during this pass, so the final visual confirmation is based on deploy smoke, live CSS verification and runtime API/GIS/AI checks rather than a new inline screenshot.
Next recommended pass
- Manually refresh the already-open
http://192.168.10.150:1202browser tab on the actual widescreen monitor to observe the new layout. - Continue with the split-background promotion preflight/matrix workflow now that Tower is rebuilt with the latest frontend and AI runtime.
Sprint 162 - Split-background promotion runtime pass
What changed
- Hardened
scripts/run_split_background_promotion_workflow.shpreflight so legacy operator manifests without explicitbackground_categoryare handled consistently withrun_operator_hard_negative_detection_matrix.sh. - Missing background categories are now derived from
reference_feature_count:0becomespure_empty_negative, and background samples with references becomesparse_building_context. - Added a regression test for the derived-category preflight path.
- Updated operator docs and changelog. No API contract, migration, provider fetching, model default, fake output or model download behavior changed.
What was tested locally
- Ran
python -m pytest tests/test_sprint159_split_promotion_workflow.py -q: 4 passed. - Ran
python -m pytest tests/test_sprint157_background_split_matrix_runner.py tests/test_sprint158_promotion_report_split_background.py tests/test_sprint159_split_promotion_workflow.py -q: 9 passed. - Ran
bash -n scripts/run_split_background_promotion_workflow.sh. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 450 passed, 17 existing Pydantic protected-namespace warnings. - Ran
npm run typecheckinfrontend. - Ran
npm run buildinfrontend. - Ran
bash scripts/run_readiness_check.sh: passed.
Tower runtime evidence
- Pushed commit
a499c5fand fast-forwarded the Tower checkout. - Ran split-background preflight against
http://192.168.10.150:1202with:PROMOTION_POSITIVE_PORTFOLIO_PATH=artifacts/detection-quality-matrix/multi-sample/aoi1024bg512r3e50-full/multi_sample_quality_summary.jsonOPERATOR_SAMPLE_MANIFEST_PATH=storage/operator-data/operator-samples-1024/operator_samples_manifest.json- result: passed.
- Ran the full low/mid-threshold split workflow into:
- background split:
artifacts/detection-hard-negatives/background-split/aoi1024bg512r3e50-split-20260710T222641Z - promotion report:
artifacts/detection-model-promotion/split-aware/aoi1024bg512r3e50-split-20260710T222641Z/detection_model_promotion_report.json - result: no recommended candidate because
0.15produced 46 pure-empty detections onpostel_bos, while0.35had no matching positive evidence in that portfolio.
- background split:
- Ran high-threshold preflight and full split workflow using:
PROMOTION_POSITIVE_PORTFOLIO_PATH=artifacts/detection-quality-matrix/multi-sample/aoi1024bg512r3e50-high-threshold/multi_sample_quality_summary.jsonQUALITY_THRESHOLDS="0.35 0.45 0.6"- background split:
artifacts/detection-hard-negatives/background-split/aoi1024bg512r3e50-high-threshold-split-20260710T222934Z - promotion report:
artifacts/detection-model-promotion/split-aware/aoi1024bg512r3e50-high-threshold-split-20260710T222934Z/detection_model_promotion_report.json
- High-threshold strict pure-empty gate passed:
- 3 pure-empty samples:
arendonk_heide,lommel_heide,postel_bos - 9 pure-empty runs
- total detections:
0 - max detections per sample/threshold run:
0
- 3 pure-empty samples:
- Recommended candidate:
geointel-building-yolov8s-aoi1024bg512r3e50-pt|512|64|0.35- positive samples:
7 - pure-empty background samples:
3 - mean F1:
0.32086574003576274 - mean precision:
0.8400057773951873 - mean recall:
0.20213514285308795 - max pure-empty detections:
0 - promotion status:
promote_candidate
- Sparse-context review remained review-only:
- 6 sparse-context samples
- 18 sparse-context runs
- total detections:
422 - max sparse-context detections:
55
Known limitations
- The recommended candidate has conservative recall (
0.2021) at threshold0.35; it is suitable as an operator-review candidate, not as an automatically activated production default. - The model default was not changed. Activation should remain a separate explicit operator decision after reviewing the high-threshold report.
Next recommended pass
- Add a guarded model activation/operator-selection workflow that can mark a promoted candidate as active only after the report artifact and candidate key are explicitly supplied.
Sprint 163 - Guarded promoted YOLO activation workflow
What changed
- Added
scripts/activate_promoted_yolo_candidate.py. - The helper validates:
- the promotion report file exists and is valid JSON;
- the exact supplied
candidate_keymatches the report recommended candidate; - the candidate has
promotion_status=promote_candidate; - positive sample count, background sample count, mean F1 and max background detections still satisfy report gates;
- the candidate
model_asset_idresolves to an existing local model file under the mounted models directory.
- The helper emits
.envupdates in dry-run mode by default and writes them only when--applyis supplied. - Updated Detection Lab operator profiles:
balanced-reviewat threshold0.15remains candidate-only because pure-empty false-positive pressure failed.conservative-reviewat threshold0.35is marked as promoted/default-approved based on the split-background pure-empty gate.
- Added docs for the guarded activation command in
docs/AI_PIPELINES.md,scripts/README.md,backend/README.mdandfrontend/README.md. - Added readiness coverage for compiling the new helper.
- No API contract, database migration, provider fetching, fake detection path, model file mutation, model download or automatic runtime activation was introduced in code.
What was tested locally
- RED:
python -m pytest tests/test_sprint162_promoted_model_activation.py -qfailed whilescripts/activate_promoted_yolo_candidate.pywas absent. - RED:
python -m pytest tests/test_sprint155_detection_operator_profiles.py -qfailed beforeconservative-reviewwas marked promoted. - RED:
python -m pytest tests/test_sprint162_promoted_model_activation.py::test_readiness_gate_compiles_promoted_activation_script -qfailed before readiness compiled the helper. - Ran
python -m pytest tests/test_sprint162_promoted_model_activation.py tests/test_sprint155_detection_operator_profiles.py -q: 7 passed. - Ran
python -m py_compile scripts/activate_promoted_yolo_candidate.py. - Ran
python -m compileall backend/app. - Ran
python -m pytestinbackend: 454 passed, 17 existing Pydantic protected-namespace warnings. - Ran
npm run typecheckinfrontend. - Ran
npm run buildinfrontend. - Ran
bash scripts/run_readiness_check.sh: passed.
Known limitations
- The helper updates runtime environment only; a container restart or rebuild is still required for
YOLO_MODEL_PATHchanges to take effect. - The promoted threshold is represented in the operator profile and promotion report. The backend detection endpoint still requires clients to submit the intended confidence threshold explicitly.
Next recommended pass
- Push this helper to Tower, run it first as dry-run against the high-threshold promotion report, then apply and redeploy/restart only if the emitted
YOLO_MODEL_PATHmatches the promoted local asset.
Sprint 164 - Live operational YOLO detection and QA smoke
What changed
- No product code, API contract, migration, model artifact, fake-data path or provider-fetching behavior changed.
- Ran the deployed all-in-one Tower runtime at
http://192.168.10.150:1202through a real raster/reference detection and QA workflow using existing operator data and the local promoted YOLO model asset.
Tower runtime evidence
- Runtime URL:
http://192.168.10.150:1202 - Raster input:
/mnt/user/appdata/geointel/storage/operator-data/operator-samples-1024/geel_orthophoto_wms_1024.tif - Reference input:
/mnt/user/appdata/geointel/storage/operator-data/operator-samples-1024/geel_grb_gbg_buildings.geojson - Model asset:
geointel-building-yolov8s-aoi1024bg512r3e50-pt - Project:
865746ee-10ce-40a1-a3da-98b2182200e5 - Raster dataset:
c87ed009-0bf0-4a34-adc5-51e6747d847b - Reference dataset:
d9bca687-20ca-4609-8c15-d24d240cfae6 - Tile manifest:
/app/storage/tiles/865746ee-10ce-40a1-a3da-98b2182200e5/c87ed009-0bf0-4a34-adc5-51e6747d847b/b1335951-4ead-4e08-9c5f-08c67e026a8f/manifest.json - Analysis run:
45159e0b-36be-4300-8132-fef3a1e6b667 - Persisted detections:
333 - Quality check:
2e696dca-dea6-42d1-af2a-4894b182d427 - Detection export:
339344f7-38e3-4558-b66b-459726051bac
Validation
- Ran
scripts/verify_real_data_detection_qa_workflow.shagainst the deployed Tower runtime: passed. - Confirmed detection run status:
success. - Confirmed detection list endpoint returned
333persisted detections with real source tile provenance. - Confirmed detection GeoJSON endpoint returned a
FeatureCollectionwith333persisted geometry features. - Confirmed detection export content returned a
detection_geojsonFeatureCollectionwith333features. - Confirmed QA/QC persisted metrics:
- precision:
0.21621621621621623 - recall:
0.031746031746031744 - F1:
0.05536332179930796 - mean IoU:
0.5697275247203281 - false positives:
261 - false negatives:
2196
- precision:
- Confirmed QA evidence overlay endpoint returned a
FeatureCollectionwith2601features and no warnings.
Known limitations
- The model is operational and demonstrable, but the Geel smoke confirms low recall at the current conservative threshold. It should remain an operator-review detector, not an automated decision engine.
- Further training data quality work remains required before treating the detector as production-grade.
Next recommended pass
- Add/curate more high-quality positive AOIs and cleaner building labels, then rerun the multi-AOI calibration and promotion gate before changing default operator thresholds.
Sprint 165 - Clean AOI1024 YOLO dataset and promotion rejection
What changed
- Hardened
scripts/export_operator_yolo_tile_dataset.pyso legacy operator manifests without explicitbackground_categorynow derive background categories consistently with the split-background evaluator:reference_feature_count == 0->pure_empty_negativereference_feature_count > 0->sparse_building_context- normal reference samples ->
reference_aoi
- Added regression coverage in:
backend/tests/test_sprint130_operator_yolo_tile_dataset.pybackend/tests/test_sprint156_background_corpus_classification.py
- Documented the clean AOI1024 export/audit profile in
scripts/README.md. - Updated
docs/TODO.mdwith the clean dataset and rejected candidate state. - No API contract, migration, default model activation, provider fetch path, model download behavior or fake detection path changed.
Local validation
- RED:
python -m pytest backend/tests/test_sprint130_operator_yolo_tile_dataset.py::test_background_category_is_derived_for_legacy_operator_manifests -qfailed before the exporter helper existed. - GREEN: same targeted test passed after adding
background_category_for_sample. - Ran
python -m pytest backend/tests/test_sprint130_operator_yolo_tile_dataset.py backend/tests/test_sprint146_operator_yolo_dataset_quality_audit.py backend/tests/test_sprint157_background_split_matrix_runner.py -q: 12 passed. - Ran
python -m pytest backend/tests/test_sprint130_operator_yolo_tile_dataset.py backend/tests/test_sprint156_background_corpus_classification.py -q: 11 passed. - Ran
bash scripts/run_readiness_check.sh: 457 backend tests passed, frontend typecheck passed, frontend build passed, readiness passed.
Tower runtime evidence
- Pushed commit
b3bd34cand redeployed the all-in-one Tower runtime athttp://192.168.10.150:1202. - Deploy validation passed:
- live migration smoke passed;
- browser runtime verification passed;
- container exposed
0.0.0.0:1202->80/tcp.
- Regenerated clean AOI1024 tile dataset:
- dataset:
/app/storage/operator-data/yolo-building-aoi1024-cleanpx12vis035 - tile count:
144 - positive tiles:
114 - negative tiles:
30 - labels:
14632 min_label_px=12min_label_visible_ratio=0.35- background categories in tile summary:
pure_empty_negative=27sparse_building_context=54reference_aoi=63
- dataset:
- Dataset audit:
- report:
/app/artifacts/operator-yolo-dataset-audit/aoi1024-cleanpx12vis035/operator_yolo_dataset_quality_audit.json - status:
ok - positive sample count:
13 - background sample count:
9 - invalid labels:
0 - missing label files:
0 - median normalized box area:
0.001373291015625 - small-box share:
0.0
- report:
Training and evaluation
- Trained a new inactive local model:
- model asset id:
geointel-building-yolov8s-aoi1024cleanpx12vis035e50-pt - model file:
/app/models/geointel-building-yolov8s-aoi1024cleanpx12vis035e50.pt - SHA256:
4863b27717cb7fd3126ccf86a988b3c1863b5fb9271cf35370ca2473b9ed10f4 - base model:
/app/models/yolov8s.pt - dataset:
/app/storage/operator-data/yolo-building-aoi1024-cleanpx12vis035/dataset.yaml - epochs:
50 - image size:
512 - batch:
4 - device:
cpu - active runtime model: unchanged
- model asset id:
- Ran positive multi-AOI matrix:
- output:
artifacts/detection-quality-matrix/multi-sample/aoi1024cleanpx12vis035e50-positive/multi_sample_quality_summary.json - samples:
geel,mol,turnhout,herentals,balen,retie,westerlo - thresholds:
0.35,0.25,0.15
- output:
- Ran split-background promotion workflow:
- background split:
artifacts/detection-hard-negatives/background-split/aoi1024cleanpx12vis035e50-split/background_corpus_split_summary.json - promotion report:
artifacts/detection-model-promotion/split-aware/aoi1024cleanpx12vis035e50-split/detection_model_promotion_report.json - recommended candidate:
none
- background split:
Promotion result
geointel-building-yolov8s-aoi1024cleanpx12vis035e50-pt|512|64|0.15- rejected:
positive_mean_f1_below_gate,background_false_positive_pressure - positive samples:
7 - background samples:
3 - mean F1:
0.1542209371995884 - mean precision:
0.18801639524786692 - mean recall:
0.13146097412721683 - max pure-empty detections:
2
- rejected:
geointel-building-yolov8s-aoi1024cleanpx12vis035e50-pt|512|64|0.25- rejected:
positive_mean_f1_below_gate - mean F1:
0.14443976458069788 - mean precision:
0.24254741138809843 - mean recall:
0.10383903038875668 - max pure-empty detections:
0
- rejected:
geointel-building-yolov8s-aoi1024cleanpx12vis035e50-pt|512|64|0.35- rejected:
positive_mean_f1_below_gate - mean F1:
0.11851668674424971 - mean precision:
0.30588130541017644 - mean recall:
0.07481388046665544 - max pure-empty detections:
0
- rejected:
Known limitations
- The clean label filter fixed the small-box audit problem but did not improve promotion-quality detection metrics.
- The new model remains useful evidence only and must stay inactive.
- The current limiting factor is not script/runtime wiring; it is training data representativeness and label geometry quality for small/dense Belgian building footprints.
Next recommended pass
- Add building-size/visibility diagnostics per AOI and use them to choose or generate better positive samples before another training run. Do not spend more CPU on the current cleanpx dataset without changing the sample/label strategy.
Sprint 166 - Per-sample YOLO dataset audit diagnostics
What changed
- Extended
scripts/audit_operator_yolo_dataset_quality.pywith per-sample YOLO label diagnostics insample_summaries:- parsed label count;
- invalid label count;
- missing label file count;
- median/mean normalized box area;
- median normalized width/height;
- small-box count/share;
- sample-specific quality warning codes.
- Kept the existing global audit gates unchanged.
- Updated the Markdown audit output so each AOI/sample line includes the new label-quality signals.
- Added regression assertions in
backend/tests/test_sprint146_operator_yolo_dataset_quality_audit.py. - Updated
scripts/README.mdto document per-sample diagnostics.
Local validation
- RED:
python -m pytest backend/tests/test_sprint146_operator_yolo_dataset_quality_audit.py::test_operator_yolo_dataset_quality_audit_reports_dataset_risks -qfailed withKeyError: 'parsed_label_count'before sample diagnostics existed. - GREEN: same targeted test passed after adding sample label stats.
- Ran
python -m pytest backend/tests/test_sprint146_operator_yolo_dataset_quality_audit.py backend/tests/test_sprint130_operator_yolo_tile_dataset.py backend/tests/test_sprint156_background_corpus_classification.py -q: 12 passed. - Ran
bash scripts/run_readiness_check.sh: 457 backend tests passed, frontend typecheck passed, frontend build passed, readiness passed.
Tower runtime evidence
- Pushed commit
7ccabf5and redeployed the all-in-one Tower runtime athttp://192.168.10.150:1202. - Deploy validation passed:
- live migration smoke passed;
- browser runtime verification passed;
- container exposed
0.0.0.0:1202->80/tcp.
- Re-ran the clean AOI1024 audit with sample diagnostics:
- report:
/app/artifacts/operator-yolo-dataset-audit/aoi1024-cleanpx12vis035-sample-diagnostics/operator_yolo_dataset_quality_audit.json - status:
ok - tile count:
144 - positive tiles:
114 - negative tiles:
30 - labels:
14632 - parsed labels:
14632 - median normalized box area:
0.001373291016 - small-box share:
0.0 - sample count:
16
- report:
- All samples reported
quality_warnings=[]under the current gates. - Lowest positive/context label counts:
ravels_bos: 22 parsed labels, median box area0.001140594385geel_bel: 56 parsed labels, median box area0.001411437891kasterlee_bos: 73 parsed labels, median box area0.001522064229dessel_heide: 77 parsed labels, median box area0.001495361328meerhout_bos: 99 parsed labels, median box area0.001232147197
Known limitations
- Numeric label diagnostics now pass, but the rejected
aoi1024cleanpx12vis035e50model proves that numeric gates alone are insufficient. - The next unknown is visual alignment and semantic fit: whether GRB building boxes line up well enough with the orthophoto tiles and whether sparse/context AOIs represent the false-positive modes seen during promotion.
Next recommended pass
- Design and add a visual YOLO label QA artifact generator: deterministic contact sheets of selected train/val tiles with YOLO boxes overlaid on imagery, grouped by AOI/sample and label density. Use it before another training run.
Sprint 167 - Operator YOLO visual label QA contact sheets
What changed
- Added
scripts/render_operator_yolo_label_qa_contact_sheets.pyto render deterministic operator-only contact sheets from existing YOLO tile datasets. - The script reads the existing
yolo_tile_dataset_summary.json, image tiles and label files, then writes:operator_yolo_label_qa_summary.json;operator_yolo_label_qa_contact_sheet.md;- one or more PNG contact sheets with YOLO labels drawn over the tile imagery.
- Added explicit checks for missing images, missing label files, invalid YOLO rows and blank-looking/low-variance tiles.
- Added regression coverage in
backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py. - Updated the all-in-one Dockerfile so operator QA scripts are copied after the expensive dependency layer, keeping future script-only rebuilds cache-friendlier.
- Updated Docker runtime tests so the all-in-one image keeps packaging the operator scripts needed on Tower.
- No inference, training, provider fetch, database mutation, model activation or fake detection path was introduced.
Local validation
- RED:
python -m pytest backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py -qfailed before the contact-sheet script existed. - GREEN: same targeted test passed after adding the renderer.
- RED: the low-variance regression failed before
low_visual_variance_tile_countexisted. - GREEN: same targeted test passed after adding low-variance tile reporting.
- Ran
python -m pytest backend/tests/test_docker_runtime_config.py::test_all_in_one_dockerfile_copies_operator_scripts_for_runtime_use backend/tests/test_docker_runtime_config.py::test_all_in_one_dockerfile_copies_operator_scripts_after_dependency_install backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py -q: 3 passed. - Ran
bash scripts/run_readiness_check.sh: 459 backend tests passed, frontend typecheck passed, frontend build passed, readiness passed.
Tower runtime evidence
- Pushed commits
fbccf83and5688fee, then redeployed the all-in-one Tower runtime athttp://192.168.10.150:1202. - Docker storage had filled during the first build attempt. Cleaned Docker build cache and dangling images only; application volumes and appdata were not pruned. Docker reclaimed
98.38GB. - Deploy validation for commit
5688feepassed:- live migration smoke passed;
- browser runtime verification passed;
- container exposed
0.0.0.0:1202->80/tcp; - Unraid icon check remained OK.
- Rendered the clean AOI1024 visual label QA artifact inside the live container:
- summary:
/app/artifacts/operator-yolo-label-qa/aoi1024-cleanpx12vis035/operator_yolo_label_qa_summary.json - Markdown:
/app/artifacts/operator-yolo-label-qa/aoi1024-cleanpx12vis035/operator_yolo_label_qa_contact_sheet.md - contact sheet:
/app/artifacts/operator-yolo-label-qa/aoi1024-cleanpx12vis035/contact_sheet_001.png
- summary:
- Runtime summary:
- status:
ok - selected tiles:
32 - rendered tiles:
32 - valid labels:
7670 - invalid labels:
0 - missing images:
0 - missing label files:
0 - low-variance tiles:
6
- status:
- Visual inspection confirmed:
- dense positive tiles show yellow YOLO boxes over real orthophoto imagery;
- the six low-variance tiles are
arendonk_heidepure-empty negative validation tiles with no labels and blank-looking imagery.
Known limitations
- The contact sheet now makes visual label inspection possible, but it also proves that the current clean AOI1024 dataset still contains blank-looking pure-empty negative tiles.
- Those blank/low-variance negatives should not be used blindly for the next training run. They can distort the background corpus and do not represent realistic aerial false-positive pressure.
- The current inactive model/promotion state remains unchanged.
Next recommended pass
- Add no-data/low-variance filtering to the operator YOLO tile export path, regenerate the clean AOI1024 dataset, rerun the contact-sheet QA, and only then consider another training attempt.
Sprint 168 - Operator YOLO low-variance negative filtering
What changed
- Added opt-in low-variance negative filtering to
scripts/export_operator_yolo_tile_dataset.py. - Added CLI/env controls:
--drop-low-variance-negatives/OPERATOR_YOLO_DROP_LOW_VARIANCE_NEGATIVES;--blank-range-threshold/OPERATOR_YOLO_BLANK_RANGE_THRESHOLD.
- The filter evaluates the rendered raster tile image and skips only negative tiles when enabled.
- Positive/labeled tiles are never removed by this variance gate.
- Kept tile records now include
low_visual_variance. - Skipped blank/no-data negative records use
skip_reason="low_visual_variance_negative". - Dataset summaries now include:
drop_low_variance_negatives;blank_range_threshold;skipped_low_variance_negative_tile_count.
- Updated operator documentation with the refreshed AOI1024 cleanpx export command.
- Added design and execution plan docs under
docs/superpowers/.
Local validation
- RED:
python -m pytest backend/tests/test_sprint130_operator_yolo_tile_dataset.py::test_export_can_skip_low_variance_negative_tiles -qfailed becauseexport_sample_tiles()did not acceptdrop_low_variance_negatives. - GREEN: same targeted test passed after adding the filter.
- Ran
python -m pytest backend/tests/test_sprint130_operator_yolo_tile_dataset.py -q: 8 passed. - Ran
python -m pytest backend/tests/test_sprint130_operator_yolo_tile_dataset.py backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py backend/tests/test_docker_runtime_config.py::test_all_in_one_dockerfile_copies_operator_scripts_for_runtime_use backend/tests/test_docker_runtime_config.py::test_all_in_one_dockerfile_copies_operator_scripts_after_dependency_install -q: 11 passed. - Ran
python scripts/export_operator_yolo_tile_dataset.py --help: the CLI exposes--drop-low-variance-negatives,--no-drop-low-variance-negativesand--blank-range-thresholdwithout loading GIS dependencies. - Ran
bash scripts/run_readiness_check.sh: 460 backend tests passed, frontend typecheck passed, frontend build passed, readiness passed.
Tower runtime evidence
- Pushed commit
a159370and redeployed the all-in-one Tower runtime athttp://192.168.10.150:1202. - Deploy validation passed:
- live migration smoke passed;
- browser runtime verification passed;
- container exposed
0.0.0.0:1202->80/tcp.
- Regenerated the AOI1024 cleanpx dataset with low-variance negative filtering enabled:
- dataset:
/app/storage/operator-data/yolo-building-aoi1024-cleanpx12vis035 drop_low_variance_negatives=trueblank_range_threshold=3- tile count:
135 - positive tiles:
114 - negative tiles:
21 - skipped negative tiles:
9 - skipped low-variance negative tiles:
9 - labels:
14632 - train tiles:
108 - validation tiles:
27
- dataset:
- Dataset audit:
- report:
/app/artifacts/operator-yolo-dataset-audit/aoi1024-cleanpx12vis035-lowvarfilter/operator_yolo_dataset_quality_audit.json - status:
ok - invalid labels:
0 - missing label files:
0 - median normalized box area:
0.001373291016 - small-box share:
0.0
- report:
- Visual label QA:
- report:
/app/artifacts/operator-yolo-label-qa/aoi1024-cleanpx12vis035-lowvarfilter/operator_yolo_label_qa_summary.json - contact sheet:
/app/artifacts/operator-yolo-label-qa/aoi1024-cleanpx12vis035-lowvarfilter/contact_sheet_001.png - selected tiles:
32 - rendered tiles:
32 - valid labels:
7670 - invalid labels:
0 - missing images:
0 - missing label files:
0 - low-variance rendered tiles:
0
- report:
- Visual inspection confirmed that the previous blank white
arendonk_heidenegatives are no longer present in the review sheet. The remaining selected pure-empty negatives are real visible orthophoto/context tiles.
Known limitations
- The low-variance gate is deliberately simple and only identifies visually blank/no-data-looking negative tiles.
- Operator visual contact-sheet review remains required before any new training run.
- The filtered dataset is now a cleaner input candidate, but model training is still not guaranteed to improve QA/QC; another training run must be gated through the existing positive-AOI and background promotion reports.
Next recommended pass
- Train one inactive candidate from the filtered AOI1024 cleanpx dataset, then run the existing positive-AOI matrix and split-background promotion workflow before considering default activation.
Sprint 171 - Positive AOI expansion and split safety
What changed
- Converted the Sprint 170 false-negative evidence into a guarded data action instead of another blind training run.
- Added Olen, Lille, Oud-Turnhout and Kasterlee center as explicit real-reference training AOIs.
- Kept Turnhout, Retie, Westerlo and Arendonk-heide as the documented validation holdouts.
- Added generated
recommended_splitprovenance and tile-export validation that rejects unknown samples and manifest-backed holdout leakage. - Hardened false-negative portfolio comparison to require identical reference feature identities, not only matching AOI names.
Local validation
- RED tests proved the expansion/split constants and validation guard were absent before implementation.
python -m pytest backend/tests/test_sprint131_operator_sample_expansion.py backend/tests/test_sprint130_operator_yolo_tile_dataset.py backend/tests/test_sprint156_background_corpus_classification.py backend/tests/test_sprint170_detection_false_negative_audit.py -q: 23 passed.- Official GRB OGC API probes returned building features at all four new AOI centers.
- Local sample generation was attempted but correctly stopped because the workstation Python lacks the existing GIS runtime extras; the all-in-one Tower runtime is the supported execution environment.
Tower runtime evidence
- Pushed
0f49c98and redeployed the all-in-one runtime athttp://192.168.10.150:1202; live migration and browser proxy verification passed. - Refreshed
/app/storage/operator-data/operator-samples-1024/operator_samples_manifest.jsonto schema version 2 with 20 sources. - Newly fetched real GRB reference counts: Olen 1,952, Lille 1,839, Oud-Turnhout 2,691 and Kasterlee 1,831; all are
recommended_split=train. - Exported
/app/storage/operator-data/yolo-building-aoi1024-expanded-minpx4vis035:- 171 retained tiles;
- 153 positive and 18 negative tiles;
- 45,892 labels;
- 144 train and 27 validation tiles;
- 9 low-variance negatives skipped;
- validation holdouts Turnhout, Retie, Westerlo and Arendonk-heide recorded in summary provenance.
- Dataset audit status
ok: no warnings, invalid labels or missing files; median normalized box area0.000694274766, small-box share0.3832694151486098. - Improved the visual contact-sheet selector after the first live sheet overrepresented dense AOIs. The balanced rerun selected 40 tiles across all 19 retained source samples with zero invalid labels, missing images, missing label files or low-variance selections.
- Started one 50-epoch CPU YOLOv8s candidate as inactive runtime evidence:
geointel-building-yolov8s-aoi1024expandedminpx4vis035e50.pt.
Known limitations
- No new model has been trained or activated.
- The inactive training run must finish and pass positive-AOI plus split-background promotion gates before it can be considered for activation.
Next recommended pass
- Finish the inactive candidate, run fixed-threshold positive evidence and split pure-empty/sparse-context background matrices, and preserve the current production default unless the promotion report passes every gate.
Sprint 172 - CPU AI image build hardening
What changed
- Reordered
deploy/unraid/Dockerfile.all-in-onesopyproject.tomland minimal package metadata are installed before the complete backend source is copied. - Code-only backend changes can now reuse the expensive GIS/AI dependency layer; dependency metadata changes still invalidate it.
- The opt-in CPU AI build now installs the same validated PyTorch
2.13.0/ torchvision0.28.0versions from the official CPU wheel index before installing theaiextra. - Kept the full GIS and YOLO import/preflight smoke after the complete backend source copy.
Validation so far
- RED: the new Docker ordering/CPU-wheel regression test failed against the old Dockerfile.
- GREEN:
python -m pytest backend/tests/test_docker_runtime_config.py -q: 26 passed. python -m pip index versionsconfirmedtorch 2.13.0+cpuandtorchvision 0.28.0+cpuare available from the configured CPU index for the workstation platform.
Remaining validation
- Build the AI-enabled all-in-one image on Tower after the current inactive model training run finishes, verify Torch reports a CPU build and rerun live migration/browser smokes before replacing the runtime.
Sprint 171.1 - Validation coverage provenance
- The expanded live export exposed that Arendonk-heide remained configured as a holdout while all of its low-variance tiles were correctly filtered out.
- Added
retained_validation_sample_slugsandempty_validation_sample_slugsto tile dataset summaries so configured and actual validation coverage cannot be confused. - Added a focused regression test and kept filtering behavior unchanged; no blank tile was reintroduced.
Sprint 173 - Expanded building model promotion
Runtime evidence
- Completed inactive 50-epoch CPU training for
geointel-building-yolov8s-aoi1024expandedminpx4vis035e50.ptfrom the expanded 20-source real-data corpus. - Trained-model SHA256:
a8a79cf5b0bdc19a0245acc322cf77232c335e222bd5f3c00a17d5f29402c196. - Training summary recorded 45,892 labels across 171 retained tiles; final training metrics were precision
0.55558, recall0.35206, mAP500.27440and mAP50-950.10107. - The persisted seven-AOI positive matrix recommended tile size
512, overlap64and threshold0.15: mean precision0.6470590036, recall0.4699913837, F10.5432865391, and minimum per-AOI F10.4897494305. - The strict pure-empty gate covered Postel, Lommel and Arendonk across all tested thresholds and produced zero detections. Sparse-building contextual AOIs remained review-only evidence because real GRB buildings are present there.
- Fixed-threshold persisted false-negative comparison used identical reference feature populations and reduced the false-negative rate in all seven positive AOIs versus the previous active
0.35profile. - The guarded activation helper first returned
ready_to_apply, resolved the exact local model asset and reported no downloads or inference. The reviewed--applypass updated onlyGEOINTEL_INSTALL_AI,YOLO_ENABLED,YOLO_MODELS_DIRandYOLO_MODEL_PATHin the Tower environment.
UI and operator behavior
- Detection Lab now recommends the promoted expanded-AOI model at threshold
0.15and surfaces its seven-AOI coverage plus QA metrics. - The previous AOI1024 background-aware model remains mounted as an explicit legacy high-precision
0.35review profile. - Profile selection remains deliberate: it selects a mounted local asset and run threshold only; it does not mutate runtime environment, download a model or start inference automatically.
Remaining limitation
- Persistent small-building misses remain the weakest quality bucket. Continue with targeted evidence review and data coverage before considering another training run; do not infer production accuracy from aggregate F1 alone.
Tower deployment verification
- Pushed commit
1c16313and rebuilt the all-in-one runtime athttp://192.168.10.150:1202. - The opt-in AI image installed
torch 2.13.0+cpuandtorchvision 0.28.0+cpufrom the official CPU wheel index; runtime CUDA availability isfalse. Ultralytics reports version8.4.93. - The live model catalog exposes 23 local files and marks only
geointel-building-yolov8s-aoi1024expandedminpx4vis035e50-ptactive with the expected SHA256. - Explicit
--check-model-loadpreflight passed against an existing nine-tile manifest: dependencies, model load, manifest structure, tile paths and tile limit were all valid; no inference or download ran. - Embedded PostGIS live migration smoke passed with PostGIS
3.6, required tables/indexes, database collation and the single Alembic head202606120900. - Browser validation confirmed that the recommended profile selects the exact active asset and threshold
0.15, while live preflight displays CPU dependency/model readiness and the expected missing-manifest guard before dataset handoff. - Browser console warnings/errors:
0.
Sprint 174 - Focused small-building recovery and promotion
Data and training evidence
- Converted the Sprint 173 persistent false-negative audit into one focused real-data experiment instead of extending the same corpus blindly.
- Added Beerse, Rijkevorsel, Hoogstraten and Vorselaar as training AOIs and Vosselaar/Grobbendonk as independent tile-level validation AOIs.
- Kept Turnhout, Retie and Westerlo outside the tile corpus as operation-level holdouts.
- Exported
/app/storage/operator-data/yolo-building-aoi1024-smallbld-minpx3vis035from an explicit 23-sample manifest subset:- 198 retained tiles;
- 180 positive and 18 negative tiles;
- 58,820 real GRB-derived labels;
- 48 visually reviewed tiles;
- zero invalid labels, missing images, missing label files or low-variance review selections.
- The accepted
min-label-px=3corpus retained 1,228 more genuine small-building labels than the comparablemin-label-px=4export. - Trained one inactive 30-epoch CPU candidate from the previous active local model:
- model:
geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt; - model SHA256:
a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1; - dataset-summary SHA256:
49b2a07d2105d08356431757b83eafc1498eaf1fb76965b1efe05b776824942a; - dataset-YAML SHA256:
3a2ea97c35a18072a1ab6738cd673c0ecec5344b19461c91d72a15e138d46e8d; - no model download and no fake training or QA data.
- model:
Persisted promotion evidence
- Evaluated the exact fixed profile
tile=512,overlap=64,confidence=0.15with QA match IoU explicitly fixed at0.25. - Seven positive AOIs produced:
- mean precision
0.5898197518; - mean recall
0.5769921004; - mean F1
0.5824578632; - minimum per-AOI F1
0.5527837436.
- mean precision
- Every AOI improved F1 relative to the previous balanced model. Turnhout improved from
0.4897494305to0.5527837436. - The strict pure-empty gate covered Postel, Lommel and Arendonk and produced zero detections for every sample.
- The formal promotion report recommended the exact key
geointel-building-yolov8s-smallbld-minpx3-img640-ft30-pt|512|64|0.15. - Fixed-reference object evidence used identical GRB feature identities and reduced false negatives from
7,753to6,182:- 1,571 fewer total false negatives;
- 745 fewer misses in the 25-100 m2 bucket;
- 181 fewer misses below 25 m2;
- all seven AOIs improved.
- Remaining persistent misses total
5,838, concentrated in Turnhout, Herentals and Geel and still dominated by small buildings. - Mean precision decreased from
0.6470590036to0.5898197518. The new profile is therefore a recall-balanced operator default with a higher false-positive review load, not ground truth.
Repository hardening
- Added explicit
--samples/OPERATOR_YOLO_SAMPLEScorpus selection with selected/excluded sample provenance and unknown-sample rejection. - Added persistent false-negative area statistics, size buckets and combined GeoJSON review evidence.
- Copied the complete operator evaluation/promotion toolchain into the all-in-one image and added a regression that rejects every Docker
COPY scripts/...source that does not exist. - Removed Pydantic protected-namespace warnings for legitimate
model_*API fields while preserving all schema field names and response contracts. - Updated Detection Lab profiles: the new small-building profile is recommended, the previous expanded profile remains the higher-precision legacy choice, and the background-aware
0.35profile remains conservative. - Live
2560x1080inspection found that two-panel AI/QA/Export workspaces inherited four ultrawide columns and left half of the main canvas empty. Those workspaces now remain explicit two-column grids while the three-panel Data workspace keeps three columns. - The all-in-one dependency layer now copies only
pyproject.tomlplus a stable build-only package README before installation; the realbackend/README.mdstill enters with the complete backend source, so documentation-only edits no longer invalidate Torch/GIS dependencies. - Guarded activation first returned
ready_to_apply; the reviewed--applypass updated onlyGEOINTEL_INSTALL_AI,YOLO_ENABLED,YOLO_MODELS_DIRandYOLO_MODEL_PATHin the Tower environment.
Local validation
python -m compileall backend/app: passed.python -m pytest: 472 passed.python -m ruff checkfor all changed Python modules/tests: passed.npm run typecheck: passed.npm run build: passed; app bundle215.64 kB, MapLibre bundle801.82 kBbefore gzip.bash scripts/run_readiness_check.sh: passed with 472 tests.python -m alembic heads: one head,202606120900.python -m alembic upgrade head --sql: complete migration chain rendered successfully.- Shell syntax checks passed for live migration and the full operator evaluation/promotion chain.
Next recommended pass
- After redeploy, verify the active model SHA, local model-load preflight, live PostGIS migration smoke and browser profile selection. Then review false-positive evidence and the remaining 5,838 persistent misses before any further training.
Sprint 175 - Detection result scale and false-positive evidence review
UI hardening
- Confirmed that Detection Lab rendered every persisted detection row at once; Westerlo alone produced 1,172 body rows in the browser.
- Added local 25/50/100-row pagination with a default of 50 rows, bounded page controls and automatic page-one reset after run/filter/result changes.
- Live visual inspection exposed tall rows caused by full container paths; source-tile cells now show the filename and retain the full persisted path as a tooltip.
- Kept the full persisted collection unchanged for the existing MapLibre GeoJSON overlay and detection QA/QC. No endpoint, response envelope or persistence contract changed.
Persisted false-positive evidence
- Added
scripts/audit_detection_false_positive_evidence.pyas a read-only evidence consumer. - The audit validates FeatureCollection/polygon geometry, compares declared portfolio role counts with actual evidence, computes WGS84 geodesic areas, preserves original feature provenance and emits combined
false_positives.geojson. - Source tile summaries are qualified by AOI because
tile_indexis local to each raster manifest. - The active fixed-threshold seven-AOI portfolio produced:
- 5,568 false positives among 13,613 candidate detections (
0.4090false-positive share); - median false-positive geometry area
184.5 m2, p90607.7 m2; - 52 below 25 m2, 1,382 between 25-100 m2, 3,412 between 100-500 m2 and 722 at or above 500 m2;
- largest AOI review volumes: Turnhout
1,102, Herentals917, Geel913; - largest AOI-qualified tile hotspot:
turnhout:0with 236 false positives.
- 5,568 false positives among 13,613 candidate detections (
- Existing persisted QA evidence carries run threshold and tile index but no per-detection confidence. The audit reports confidence coverage
0/5,568and does not invent confidence statistics. - Added focused regression coverage, readiness compilation and all-in-one image inclusion. No training, inference, provider fetch, model download or activation occurred.
Local validation
python -m compileall backend/app: passed.python -m pytest: 475 passed.python -m ruff checkfor the new audit/test modules: passed.npm run typecheck: passed.npm run build: passed; app bundle217.00 kB, MapLibre bundle801.82 kBbefore gzip.bash scripts/run_readiness_check.sh: passed with 475 tests and all release-critical syntax gates.python -m alembic heads: one head,202606120900.python -m alembic upgrade head --sql: complete migration chain rendered successfully.- Local
docker compose configcould not run because Docker CLI is not installed on the Windows host; live image/PostGIS validation is delegated to the Docker-enabled Tower deployment.
Tower deployment verification
- Pushed runtime commits
4455e24andd188014; Tower rebuilt the all-in-one image frommainwith the GIS/CPU-AI dependency layer cached. - Live PostGIS migration smoke passed with PostGIS
3.6, required runtime tables/indexes and single Alembic head202606120900. - The active local model remained
/app/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.ptwith SHA256a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1. - Local model-load preflight passed against a persisted nine-tile manifest with Torch
2.13.0+cpu, Ultralytics8.4.93, CUDA disabled, no inference and no download. - The new false-positive audit ran successfully inside the live all-in-one container against the persisted seven-AOI evidence portfolio.
- Browser verification against the persisted Westerlo run confirmed 1,172 loaded detections, 50 rendered rows,
1-50 of 1172, page1/24, working next-page and 100-row controls, and reset back to the 50-row default. - Final cells display
tile_0001.tifwhile the full persisted path remains available through thetitleattribute. - At
2560x1080, the Detection results surface used about 871 px, its table client/scroll widths both measured 827 px and the document did not overflow the viewport. - Browser console warnings/errors:
0.
Next recommended pass
- Visually classify a stratified false-positive sample from Turnhout, Herentals and Geel before deciding whether any confirmed examples belong in a new hard-negative corpus. Review the remaining 5,838 persistent false negatives in the same evidence-led pass; do not start another blind training run.
Sprint 176 - Detection false-positive visual review gate
Persisted provenance
- Extended the existing read-only QA evidence GeoJSON conversion so detection-backed evidence carries the persisted detection id, job id, confidence, model name/version, source tile path and pixel bbox.
- Added equivalent persisted segmentation provenance fields without changing the endpoint, canonical envelope, ORM or migration chain.
- Historical
QualityCheckevidence can be re-exported against existing persistedDetectionrows; no QA rerun or data rewrite is required.
Manual visual review
- Added a storage-root-confined contact-sheet renderer for persisted detection false-positive evidence.
- The renderer validates portfolio role counts, polygon geometry, source imagery and persisted provenance, then selects deterministically across AOI, WGS84 area bucket and confidence band.
- Source imagery is rendered with the candidate pixel bbox plus persisted matched-reference and missed-reference overlays.
- Live orthophoto inspection exposed stretched non-square edge tiles and overly distant full-tile context; the renderer now uses candidate-centred crops, preserves aspect ratio and limits reference overlays to the crop.
- Added an explicit five-state review CSV:
confirmed_model_false_positive,reference_gap_or_change,qa_alignment_mismatch,uncertainandunreviewed. - Added a separate validator that rejects missing, duplicate, unexpected or invalid decisions.
--require-completeexits with code2while any record remains unreviewed. - Only explicitly confirmed model false-positives are emitted to
confirmed_model_false_positives.geojson; no QA result is automatically converted into a model label or training artifact.
Validation
python -m compileall backend/app: passed.python -m pytest: 478 passed.- Focused provenance/render/path-confinement/incomplete-review/export tests: passed.
python -m ruff checkfor changed Python services, scripts and tests: passed.- Generated fixture contact sheet was visually inspected at 128 px thumbnails; candidate/reference/missed-reference overlays and header provenance remained readable.
npm run typecheck: passed.npm run build: passed; app bundle217.00 kB, MapLibre bundle801.82 kBbefore gzip.bash scripts/run_readiness_check.sh: passed with 478 tests and the new operator-script compile gates.python -m alembic heads: one head,202606120900.python -m alembic upgrade head --sql: complete migration chain rendered successfully.- Local Docker validation remains unavailable because Docker CLI is not installed on the Windows host; live all-in-one/PostGIS validation follows on Tower after deployment.
Tower deployment evidence
- Deployed commit
1322a5dthrough the repository-driven all-in-one build with the existing CPU-AI dependency layer cached. - PostGIS
3.6, required tables/indexes, Alembic head202606120900, frontend proxy, API proxy and icon checks passed. - Re-exported all seven persisted fixed-threshold QualityChecks into an enriched portfolio containing 27,840 evidence features.
- The false-positive audit now reports persisted confidence coverage
5,568/5,568rather than inventing values for the older static export. - Rendered an initial 48-case Turnhout/Herentals/Geel review spanning all four area buckets and all three confidence bands with no missing provenance or source tiles.
- All 48 decisions remain explicitly
unreviewed; validation status isreview_requiredand the confirmed-model-false-positive GeoJSON is empty.
Next recommended pass
- Re-export the seven-AOI evidence portfolio from the deployed backend, render the Mol/Geel/Turnhout sheets and inspect the real orthophoto evidence. Keep all CSV decisions
unrevieweduntil an operator makes an explicit visual classification; do not start another model training run yet.
Sprint 177 - Mol-first operating context
Product and workbench focus
- Declared Mol as the primary operational context while preserving the broader Kempen for cross-area validation and regional interoperability.
- Centralized Mol coordinates, default region and a compact 1 km EPSG:4326 MultiPolygon AOI in the frontend focus configuration.
- Initial project discovery now recognizes Mol from project metadata or persisted dataset provenance and inspects those candidates first.
- Explicitly selected and newly created projects still take precedence, so the focus rule does not fight operator intent.
- The empty MapLibre workbench starts over Mol; loaded AOIs and data continue to determine map bounds normally.
Operator provenance
- Moved Mol to the first position in default real-data sample preparation without dropping any existing Kempen sample.
- Multi-sample quality runs now forward their AOI slug, and future persisted matrix project names retain that origin instead of appearing as anonymous model/tile runs.
- No provider fetch, AI output, QA metric, migration, API contract or model configuration was changed.
Validation
- Focused Mol-primary regression coverage:
3 passed. bash scripts/run_readiness_check.sh: passed with481backend tests, API-contract audit, single Alembic head, frontend typecheck and production build.- Frontend production bundles: app
217.69 kB, React vendor140.74 kB, MapLibre801.82 kBbefore gzip. python -m alembic upgrade head --sql: complete migration chain rendered through single head202606120900.- Both changed matrix scripts pass
bash -n; no migration file changed.
Tower deployment evidence
- Deployed commit
e8eecb2through the repository-driven all-in-one build on port1202with the existing CPU-AI dependency layer cached. - Live migration smoke passed with PostGIS
3.6, required runtime tables/indexes and single Alembic head202606120900. - Renamed persisted project
d25206c0-dcba-46e5-aba9-66ace1122a30to an explicit Mol operating context and added a real 1 km Mol AOI (999,796.69 m2) without changing its datasets or analysis results. - Live Mol context contains a ready EPSG:31370 1024x1024 orthophoto and
1,993ready EPSG:4326 GRB reference buildings. - Persisted detection QA remains unchanged: precision
0.6011, recall0.5891, F10.5950, mean IoU0.4554,779false positives and819false negatives. - In-app browser verification selected the Mol project, Mol AOI and Mol reference dataset automatically. MapLibre rendered the existing
1,953-feature detection layer over the road basemap with one canvas, zero browser warnings/errors and no horizontal document overflow at1265x720.
Sprint 178 - Mol multi-zone operational validation
Implementation
- Added Mol center, Achterbos, Gompel, Donk and Postel as explicit operator contexts with municipality and operational-zone provenance.
- Marked Achterbos, Gompel, Donk and Postel as validation holdouts to keep them outside future training exports unless the split policy is deliberately changed.
- Kept Postel-bos as a separate background control, so an empty/sparse context is never assigned fabricated precision, recall or F1.
- Extended the existing real-data workflow with optional project region and EPSG:4326 AOI bounds; manifest-backed positive and background projects now open map-ready with persisted Areas.
- Added
run_mol_operational_validation.shto compose the existing positive QA matrix and background detection-pressure matrix and emit one evidence summary. - Included the new runner in the all-in-one runtime and release-readiness syntax gate. No API route, ORM model, migration, model activation or frontend behavior changed.
Initial validation
- Focused Mol/operator/workflow/Docker regressions:
43 passed. - Changed Python operator preparer compiled successfully.
- All five affected shell workflows passed
bash -n. git diff --check: clean apart from the existing Windows line-ending notice for the all-in-one Dockerfile.bash scripts/run_readiness_check.sh: passed with485backend tests, contract audit, single Alembic head, frontend typecheck and production build.- Frontend bundle sizes are unchanged: app
217.69 kB, React vendor140.74 kBand MapLibre801.82 kBbefore gzip.
Live Tower completion
- Deployed through Gitea commit
720ad71; the all-in-one browser/API smoke, PostGIS3.6, required runtime schema and Alembic head202606120900passed. - Prepared real 1024 px orthophoto/GRB samples for Mol center, Achterbos, Gompel, Donk, Postel and Postel-bos. Positive reference counts are
1,993,1,388,1,070,1,234and137; the background control contains exactly0GRB buildings. - Fixed two manifest-path type errors found by the first live multi-sample aggregation and moved all-in-one evidence defaults from the replaceable container layer to
/app/storage/operator-evidence. - Completed the persistent four-zone configured-YOLO benchmark at confidence
0.15, tile512, overlap64and QA IoU0.25: mean precision0.6286, mean recall0.5370, mean F10.5768,2,239matches,1,215false positives and1,590false negatives. - Per-zone F1 is Achterbos
0.6433, Gompel0.6333, Donk0.5823and Postel0.4483. Postel is the explicit weakest-zone review priority; no automatic promotion or retraining decision was made. - The real empty Postel-bos control produced
0detections and therefore0.0false-positive pressure without fabricated QA metrics. - Verified through the browser that the complete Postel project wins initial selection over the newer raster-only background project, with one AOI, one ready raster, one ready GRB reference, one detection run, one QualityCheck and one export.
- MapLibre rendered the OSM road basemap, AOI and
95persisted detections without browser warnings or horizontal overflow at1280x720and2560x1080; the ultrawide canvas measured1772x830CSS pixels. - Ran the interactive PostGIS AOI query against
vector_features:126GRB buildings returned with no truncation. The guided GIS smoke persisted a derived dataset and GeoJSON export, then produced candidate/reference QA F10.9582with126matches,0false positives and11false negatives;263persisted evidence features rendered back on the map. - Remaining evidence caveat: the dataset QA result reports weak CRS-assumption warnings, so those geometry metrics remain explicitly approximate until CRS provenance handling is reviewed.
- Host observation outside GeoIntel: Unraid recovered after reboot and serves the app, but still reports one disabled/invalid array device. Storage administration should resolve that independently of application development.
Sprint 179 - Mol Donk/Postel detection evidence diagnosis
Implementation
- Added
render_detection_false_negative_review_contact_sheets.pyas a read-only counterpart to the persisted false-positive review workflow. - Resolved each sample's exact persisted tile manifest from its fixed-threshold run summary; manifests and source tiles are confined to
/app/storage. - Projected WGS84 missed-reference geometry onto the real inference tiles and rendered nearby persisted candidate detections plus matched-reference context.
- Added deterministic AOI/area stratification and an explicit five-state manual decision CSV. No decision is inferred and no training input is exported automatically.
- Separated references outside every persisted source tile into
false_negatives_outside_tile_coverage.geojsoninstead of hiding them or calling them model misses. - Added focused rendering, manifest, source-coverage and storage-confinement regression tests; wired the script into readiness compilation and the all-in-one image.
Live Mol evidence
- Re-exported the four-zone fixed-threshold portfolio from existing persisted QualityChecks without rerunning inference or mutating application data.
- The complete portfolio contains
7,283evidence features. Donk contributes424false positives and553false negatives; Postel contributes43and85. - Rendered and inspected 48 stratified false-positive cases over Donk/Postel. Explicit decisions:
37QA alignment mismatches,7confirmed model false positives,3reference gaps/changes and1uncertain. The existing validator passed with statuscomplete. - Rendered and inspected 48 stratified false-negative cases. Explicit decisions:
27QA alignment mismatches,6confirmed model false negatives,3reference gaps/changes and12imagery-obscured/uncertain. - Found
41/638false-negative evidence records outside every persisted inference tile: Donk28, Postel13. Directionally excluding those records raises Donk recall from0.5519to0.5647and Postel from0.3796to0.4194; these are audit diagnostics only and no persisted metric was changed. - The dominant visual mode is rectangle-to-footprint mismatch on large industrial roofs and dense residential blocks, often with a blue persisted candidate already overlapping the red missed GRB footprint. Postel additionally contains many tiny/vegetation-obscured references.
- Persistent evidence and the assessment are stored below
/app/storage/operator-evidence/mol-operational-review/20260713.
Decision and next pass
- NO-GO for immediate retraining. Only
7/48reviewed false positives and6/48reviewed false negatives were confirmed model errors; evaluation alignment and coverage defects dominate the selected evidence. - Next harden detection QA to restrict candidate/reference populations to persisted raster/tile coverage and expose best-IoU/overlap/unmatched diagnostics. Rerun Donk/Postel QA against the unchanged persisted detections before deciding whether the confirmed model-error subset justifies curated training.
Validation
- Focused false-positive/false-negative audit and visual-review coverage:
8 passed. - Ruff passed for the changed Python renderer and regression tests.
bash scripts/run_readiness_check.sh: passed with487backend tests, the 81-route API contract audit, one Alembic head, frontend typecheck and production build.python -m alembic upgrade head --sqlrendered the complete migration chain through202606120900; no migration changed.- Local
docker compose configwas unavailable because the Windows workstation has no Docker CLI. The repository-driven Tower deployment remains the required live Docker validation.
Tower deployment evidence
- Pushed and deployed commits
50952e1and191d7aathrough the repository-driven all-in-one flow with the existing CPU AI dependency layer cached. - Tower
docker compose -f docker-compose.unraid.yml config, live PostGIS migration smoke, required schema/index checks and Alembic head202606120900passed. - The definitive image contains the false-negative renderer under
/app/scripts; persisted review artifacts remained available after both container replacements. - Precomputing source-tile footprints in EPSG:4326 reduced the deployed 12-card Donk/Postel smoke from minutes to
2.06 swhile preserving638evidence records,597reviewable records and41explicit outside-coverage exclusions. - Browser verification on
http://192.168.10.150:1202selected the complete Mol Postel workspace and showed ready project/AOI/dataset/QA/export state. - The Map workspace rendered one
1033x542MapLibre canvas, the OSM road basemap, AOI and95persisted detections with no browser warnings/errors, no visible dialog and no horizontal document overflow at a1280 pxviewport. - No API contract, migration, QualityCheck/Metric row, Detection row, model asset, active-model configuration or inference result changed in this pass.
Sprint 180 - Premium workbench UX hardening
Implementation
- Reworked the workbench shell into a calmer operational hierarchy with grouped Workspace, Analyze and Deliver navigation, a compact Mol/Kempen context header and a centered content canvas.
- Replaced the permanently reserved inspector column with an on-demand detail drawer. Dataset inspection still invokes the existing detail-loading callback and now opens the drawer explicitly.
- Made Data operational at scale by disclosing create/upload forms on demand, arranging Project, AOI and Dataset panels side by side on desktop and bounding their long collections with internal scrolling.
- Promoted MapLibre to the primary Map surface. Layer provenance and low-frequency BBox/raw-feature controls remain available in collapsed detail surfaces without removing any GIS action.
- Reordered Detection and Segmentation Labs around run controls and result review; model registry and YOLO preflight remain fully available as secondary disclosures.
- Added a dedicated
premium.csspresentation layer with a restrained neutral/teal palette, consistent controls, stable panel dimensions and an actual full-width mobile shell. The former narrow sidebar-plus-content split is removed below920 px. - Added focused static regression coverage for navigation grouping, optional inspector wiring, scalable Data panels, map hierarchy, AI Lab ordering and responsive behavior.
Behavior preservation
- Existing React state hooks, API clients, service calls, map callbacks, QA actions, uploads, exports and AI run handlers were retained.
- No backend application code, endpoint contract, database model, migration, geospatial algorithm, model configuration or persisted evidence was changed.
- Legacy UI contract strings and callback signatures remain present for the existing Sprint 1-179 regression suite.
Visual audit
- At
1280x720, the Overview now uses one compact readiness row and no permanent inspector reservation; Map controls, canvas and secondary layer details follow the intended visual order. - At
2560x1080, the main workbench uses a centered1680 pxmaximum content width while the map can expand independently; the previous permanently empty416 pxinspector column is gone. - At
390x844, navigation becomes a horizontal full-width rail and the main workspace occupies the viewport instead of sharing it with a152 pxsidebar. - A live 50-project Data state now keeps project and dataset panels within the viewport with internal scrolling instead of pushing the Dataset panel thousands of pixels below the fold.
- Detection and Segmentation run controls appear before registry diagnostics, reducing the distance to the primary task while retaining honest model-state detail.
Local validation
- React best-practice review found no new conditional hooks, effect synchronization, unstable list keys or non-semantic interactive controls.
- Focused premium-workbench and legacy UI regression coverage passed.
python -m compileall backend/app: passed.- Full backend suite:
492 passed. - Frontend typecheck and production build: passed; app bundle
219.76 kB, React vendor140.74 kBand MapLibre801.82 kBbefore gzip. bash scripts/run_readiness_check.sh: passed with the 81-route API contract audit, single Alembic head, all backend tests, frontend typecheck/build and live-smoke syntax gate.
Tower deployment evidence
- Pushed and deployed commit
a2d9cefthrough the repository-driven all-in-one flow on port1202. - The production image rebuilt the frontend successfully and retained the existing cached CPU AI/GIS dependency layer.
- Live PostGIS
3.6, database collation, required tables/indexes and the single Alembic head202606120900passed the migration smoke. - The frontend, proxied projects API and Unraid icon passed the deployed browser runtime smoke.
- At
1280x720, the populated Data workspace rendered three bounded columns; the 50-project panel remained552 pxhigh with internal scrolling instead of extending its8575 pxcontent into the document. - At
2560x1080, MapLibre rendered one nonblank1678x734canvas in a centered1680 pxmap surface with no permanently reserved inspector. - At
390x844, the sidebar became a375 pxfull-width horizontal navigation rail, the main workspace remained375 pxwide and document width stayed within the viewport. The detail drawer opened full-screen and closed correctly. - The live Map workspace preserved layer selection, AOI controls and persisted 95-feature detection overlay. Browser console verification returned zero warnings and zero errors across desktop, ultrawide, mobile, Data, Map and AI Labs checks.
Next pass
- Harden detection QA coverage and matching diagnostics before making a retraining decision; keep that work separate from this presentation-only sprint.
Sprint 181 - Complete Mol municipality workspace
Implementation
- Added an explicit operator provisioner for the official VRBG
Refgemmunicipality geometry for Mol (NIS13025) and the complete paged GRBGBGbuilding collection clipped to that exact boundary. - Added deterministic persistent source artefacts and a manifest containing source URLs, checksums, page/feature counts, boundary bounds and area, and an explicit truncation flag. Pagination and identity checks fail closed.
- Declared EPSG:4326 in both generated GeoJSON FeatureCollections so the
importer records
crs_assumed=falsefor this known official OGC source. - Added bounded retries for safe source GETs after the live refresh exposed a transient GRB HTTP 500 on page 66. Mutating GeoIntel API requests are not retried automatically.
- Kept the provider boundary honest: provisioning is an operator action and
imports through canonical Project, Area and Dataset HTTP routes. It does not
enable the dormant live GRB provider or write directly to
vector_features. - Optimized the existing vector persistence path by replacing one ORM refresh per feature with a single flush and commit. Persistence shape and API behavior remain unchanged.
- Made
Mol Municipality Workbenchthe preferred fresh-session context once its official boundary is ready. The boundary opens first; the much larger building layer remains explicitly selectable from the Map database-layer control. - Replaced spread-based map extent calculations with a streaming, memoized GeoJSON bounds helper and added municipality/building layer styling. This avoids large coordinate arrays while keeping the existing MapLibre path.
Initial validation
- Exact clipping, pagination/truncation, persistence-scaling and frontend wiring regression coverage passed locally.
- Final full backend suite and readiness gate passed with
497tests and the81-route API contract audit. Frontend typecheck/build, Ruff, shell syntax, single Alembic head202606120900and the complete offline migration chain also passed. - No API route, ORM model, migration, QA metric, detection result or model configuration changed.
Tower and live GIS evidence
- Pushed and deployed the implementation through commits
490325e,480634cande8a35b9; live PostGIS3.6, required schema/indexes, Alembic head, frontend proxy, API proxy and icon checks passed. - Provisioned definitive project
d74c1f87-29c0-4c67-adfc-560764f2b80eand official area6551ee61-0bc7-47cd-8e38-94aefb815997with bounds[5.035357, 51.1534809, 5.24218961, 51.32265943]and projected area114.546677 km2. - The complete source bbox returned
89,153unique GRB candidates over90pages. Exact municipality clipping retained36,941buildings, rejected52,212outside features and clipped24boundary-crossing features. The manifest is complete and explicitly reportsreference_truncated=false. - PostGIS contains
36,941vector feature rows and36,941distinct source IDs, with zero invalid geometries and zero non-EPSG:4326 geometries. Strict coverage reports 18 floating-point boundary artefacts whose combined outside area is only5.75e-9 m2; no material building area falls outside Mol. - The definitive boundary dataset
a8be7de2-e9e1-437a-959c-a18d9a454886and building dataset9b829bcb-eff5-48c2-baf9-ff6f8675fe7eboth persistEPSG:4326withcrs_assumed=false. The retry-hardened refresh completed all 90 pages after the earlier transient source failure. - A fresh browser session selected the municipality project, official area
and one-feature boundary automatically instead of a historical Postel
validation context. Selecting the complete building layer rendered all
36,941features and a live AOI PostGIS query returned250persisted features with dataset/export actions enabled. - Browser verification at
1280x720and2560x1080found one nonblank MapLibre canvas, no console warnings/errors and no horizontal overflow. The widescreen map canvas measured1678x734CSS pixels.
Next pass
- Add viewport/zoom-aware vector delivery before expanding beyond Mol or layering additional municipality-wide reference classes. Then acquire and tile georeferenced imagery only for an explicitly selected Mol analysis zone and run configured-YOLO plus QA/QC against the persisted GRB reference.