diff --git a/CHANGELOG.md b/CHANGELOG.md index dd4d27e6..543cfd9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - At tile `512`, overlap `64`, threshold `0.15` and QA match IoU `0.25`, seven persisted AOIs reached mean precision `0.5898`, recall `0.5770`, F1 `0.5825` and minimum F1 `0.5528`; all three pure-empty controls remained at zero detections. - Fixed-reference evidence reduced false negatives from 7,753 to 6,182, including 745 fewer 25-100 m2 misses and 181 fewer sub-25 m2 misses. Precision is lower, so the UI states the increased false-positive review load explicitly. - Added persistent false-negative area summaries/GeoJSON, explicit tile-corpus sample selection provenance, missing runtime evaluation scripts, Docker COPY-source regression checks and warning-free Pydantic model-field schemas. +- Fixed ultrawide two-panel workspaces so AI Labs, QA/QC and Exports use the available main width instead of leaving empty third/fourth columns, and decoupled backend README edits from the expensive all-in-one GIS/AI dependency cache layer. - Guarded activation updated only the Tower AI/model environment values; no fake outputs, provider fetching, API contract or database migration changed. ## Sprint 173 Expanded building model promotion (2026-07-13) diff --git a/backend/tests/test_docker_runtime_config.py b/backend/tests/test_docker_runtime_config.py index 7206ecac..9160648d 100644 --- a/backend/tests/test_docker_runtime_config.py +++ b/backend/tests/test_docker_runtime_config.py @@ -46,6 +46,9 @@ def test_all_in_one_dockerfile_can_opt_into_ai_dependencies_without_base_install dockerfile = (ROOT / "deploy" / "unraid" / "Dockerfile.all-in-one").read_text(encoding="utf-8") assert "ARG GEOINTEL_INSTALL_AI=false" in dockerfile + assert "COPY backend/pyproject.toml /app/" in dockerfile + assert "COPY backend/pyproject.toml backend/README.md /app/" not in dockerfile + assert "GeoIntel backend package metadata" in dockerfile assert 'extras=".[gis]"' in dockerfile assert 'extras=".[gis,ai]"' in dockerfile assert "python scripts/gis_import_smoke.py" in dockerfile @@ -90,7 +93,7 @@ def test_all_in_one_dockerfile_copies_operator_scripts_for_runtime_use() -> None def test_all_in_one_dockerfile_copies_operator_scripts_after_dependency_install() -> None: dockerfile = (ROOT / "deploy" / "unraid" / "Dockerfile.all-in-one").read_text(encoding="utf-8") - dependency_install_index = dockerfile.index('RUN /usr/bin/python3.11 -m venv /opt/geointel/venv \\') + dependency_install_index = dockerfile.index('/usr/bin/python3.11 -m venv /opt/geointel/venv \\') operator_copy_index = dockerfile.index( "COPY scripts/render_operator_yolo_label_qa_contact_sheets.py " "/app/scripts/render_operator_yolo_label_qa_contact_sheets.py" @@ -287,12 +290,13 @@ def test_backend_docker_context_contains_gis_import_smoke_script() -> None: def test_all_in_one_dockerfile_caches_dependencies_and_uses_cpu_torch_for_ai_runtime() -> None: dockerfile = (ROOT / "deploy" / "unraid" / "Dockerfile.all-in-one").read_text(encoding="utf-8") - metadata_copy_index = dockerfile.index("COPY backend/pyproject.toml backend/README.md /app/") - dependency_install_index = dockerfile.index('RUN /usr/bin/python3.11 -m venv /opt/geointel/venv \\') + metadata_copy_index = dockerfile.index("COPY backend/pyproject.toml /app/") + placeholder_readme_index = dockerfile.index("GeoIntel backend package metadata") + dependency_install_index = dockerfile.index('/usr/bin/python3.11 -m venv /opt/geointel/venv \\') backend_copy_index = dockerfile.index("COPY backend/ /app/") smoke_index = dockerfile.index("RUN python scripts/gis_import_smoke.py") - assert metadata_copy_index < dependency_install_index < backend_copy_index < smoke_index + assert metadata_copy_index < placeholder_readme_index < dependency_install_index < backend_copy_index < smoke_index assert "GEOINTEL_TORCH_INDEX_URL=https://download.pytorch.org/whl/cpu" in dockerfile assert "GEOINTEL_TORCH_VERSION=2.13.0" in dockerfile assert "GEOINTEL_TORCHVISION_VERSION=0.28.0" in dockerfile diff --git a/backend/tests/test_sprint161_widescreen_workbench.py b/backend/tests/test_sprint161_widescreen_workbench.py index 620751fa..2ceaa32b 100644 --- a/backend/tests/test_sprint161_widescreen_workbench.py +++ b/backend/tests/test_sprint161_widescreen_workbench.py @@ -12,6 +12,10 @@ def test_workbench_adds_widescreen_layout_contracts() -> None: assert "grid-template-columns: 14rem minmax(0, 1fr) 24rem;" in css assert ".workbench-main {\n padding: 1.1rem 1.35rem 1.35rem;" in css assert ".workspace-grid-data {\n grid-template-columns: repeat(3, minmax(0, 1fr));" in css + assert ( + ".workspace-grid-analysis,\n .workspace-grid-ai,\n .workspace-grid-exports {\n" + " grid-template-columns: repeat(2, minmax(0, 1fr));" + ) in css assert ".workspace-grid-data > section:nth-child(3) {\n grid-column: auto;" in css assert ".workbench-main .map-container,\n .map-frame-surface .map-container" in css assert "height: calc(100vh - 18rem);" in css @@ -23,7 +27,10 @@ def test_workbench_adds_ultrawide_map_priority_contracts() -> None: assert "@media (min-width: 2200px)" in css assert "grid-template-columns: 15rem minmax(0, 1fr) 26rem;" in css - assert ".workspace-grid-data,\n .workspace-grid-analysis,\n .workspace-grid-ai,\n .workspace-grid-exports" in css - assert "grid-template-columns: repeat(4, minmax(0, 1fr));" in css + assert ".workspace-grid-data {\n grid-template-columns: repeat(3, minmax(0, 1fr));" in css + assert css.count( + ".workspace-grid-analysis,\n .workspace-grid-ai,\n .workspace-grid-exports {\n" + " grid-template-columns: repeat(2, minmax(0, 1fr));" + ) == 2 assert "height: calc(100vh - 15.5rem);" in css assert "min-height: 42rem;" in css diff --git a/deploy/unraid/Dockerfile.all-in-one b/deploy/unraid/Dockerfile.all-in-one index 2573facd..e0e58005 100644 --- a/deploy/unraid/Dockerfile.all-in-one +++ b/deploy/unraid/Dockerfile.all-in-one @@ -47,10 +47,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /app -COPY backend/pyproject.toml backend/README.md /app/ +COPY backend/pyproject.toml /app/ COPY backend/app/__init__.py /app/app/__init__.py -RUN /usr/bin/python3.11 -m venv /opt/geointel/venv \ +RUN printf '# GeoIntel backend package metadata\n' > /app/README.md \ + && /usr/bin/python3.11 -m venv /opt/geointel/venv \ && pip install --no-cache-dir --upgrade pip setuptools \ && if [ "$GEOINTEL_INSTALL_AI" = "true" ]; then \ pip install --no-cache-dir \ diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index eeca2304..38128ae4 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -7119,6 +7119,8 @@ Open: - 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.35` profile remains conservative. +- Live `2560x1080` inspection 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.toml` plus a stable build-only package README before installation; the real `backend/README.md` still 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 `--apply` pass updated only `GEOINTEL_INSTALL_AI`, `YOLO_ENABLED`, `YOLO_MODELS_DIR` and `YOLO_MODEL_PATH` in the Tower environment. ## Local validation diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 3cf37e06..490ed509 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -5231,7 +5231,7 @@ section { .workspace-grid-analysis, .workspace-grid-ai, .workspace-grid-exports { - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(2, minmax(0, 1fr)); } .workspace-grid-data > section:nth-child(3) { @@ -5266,11 +5266,14 @@ section { padding: 1.2rem 1.65rem 1.5rem; } - .workspace-grid-data, + .workspace-grid-data { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .workspace-grid-analysis, .workspace-grid-ai, .workspace-grid-exports { - grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-template-columns: repeat(2, minmax(0, 1fr)); } .workbench-main .map-container,