V1 readiness
+Workbench status
+{nextAction(items)}
+{item.detail}
+diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c65ea4c..3bfaf10f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ # Changelog +## Sprint 22 V1 workbench status strip (2026-06-17) + +- Added a compact frontend status strip for project, AOI, datasets, active map layer, QA/QC and exports. +- The strip is driven by existing App state and suggests the next operator action in the V1 loop. +- Added regression coverage to ensure the strip remains wired without introducing new API calls. +- No backend behavior, migrations, API contracts, provider downloads, AI inference or new dependencies were introduced. + ## Sprint 21 V1 demo workflow smoke hardening (2026-06-17) - Hardened the browser-facing demo/export smoke to verify connected V1 state: project area GeoJSON, fixture datasets, vector FeatureCollection content, vector feature summary, persisted QA/QC metrics and export downloads. diff --git a/backend/tests/test_sprint22_workbench_status_strip.py b/backend/tests/test_sprint22_workbench_status_strip.py new file mode 100644 index 00000000..aa982046 --- /dev/null +++ b/backend/tests/test_sprint22_workbench_status_strip.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_frontend_wires_v1_workbench_status_strip() -> None: + app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") + component = (ROOT / "frontend" / "src" / "components" / "WorkbenchStatusStrip.tsx").read_text(encoding="utf-8") + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert "WorkbenchStatusStrip" in app + assert "selectedProject={selectedProject}" in app + assert "qualityChecks={qualityChecks}" in app + assert "activeLayerFeatureCount={mapFeatureCount}" in app + assert "selectedAreaHasGeometry={Boolean(areaFeatureCollection)}" in app + assert "V1 readiness" in component + assert "Workbench status" in component + assert "Workbench has the core V1 loop populated." in component + assert "workbench-status-strip" in css + assert "status-tile-ready" in css + + +def test_workbench_status_strip_summarizes_existing_v1_loop_only() -> None: + component = (ROOT / "frontend" / "src" / "components" / "WorkbenchStatusStrip.tsx").read_text(encoding="utf-8") + + assert "ProjectRead" in component + assert "AreaRead" in component + assert "DatasetCreateResponse" in component + assert "QualityCheckRead" in component + assert "ExportRead" in component + assert "fetch(" not in component + assert "api" not in component.lower() diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index eb6015fd..49391cd5 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -1,3 +1,20 @@ +## Sprint 22 V1 workbench status strip (2026-06-17) + +Changed: +- Added `frontend/src/components/WorkbenchStatusStrip.tsx` to summarize existing V1 state for project, AOI, datasets, active map layer, QA/QC and exports. +- Wired the status strip into `frontend/src/App.tsx` using existing orchestration state only. +- Added compact status-strip styling and regression tests for the frontend wiring contract. +- 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: diff --git a/docs/TODO.md b/docs/TODO.md index 974514e5..9232e8d6 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -31,6 +31,7 @@ This file now starts with the current implementation status. Older preparation/b - [x] Persisted export foundation for vector/detection/segmentation GeoJSON and project metadata JSON. - [x] Lightweight HTML project report artifact export. - [x] Browser-facing demo/export workflow smoke script with connected V1 state checks. +- [x] Compact V1 workbench status strip for project, AOI, datasets, map, QA/QC and exports. - [x] Live Docker/PostGIS validation on Tower/Unraid. - [ ] Real YOLO compatibility smoke with optional AI extras and local model file. - [ ] Further frontend state/module decomposition beyond Sprint 10 extraction. diff --git a/frontend/README.md b/frontend/README.md index f544d6ca..616da9d9 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -156,6 +156,13 @@ React + TypeScript + MapLibre foundation for project/area/dataset workflow. - Loading the explicit demo workflow now opens the candidate vector fixture dataset directly, so the Map Workbench shows the demo vector layer without an extra manual dataset click. - The demo/export verification script now checks connected V1 state: area GeoJSON, fixture datasets, vector FeatureCollection content, vector feature summary, persisted QA/QC metrics and export downloads through the frontend proxy. +## Sprint 22 additions + +- Added a compact V1 Workbench status strip above the main panels. +- The strip summarizes existing connected state for project, AOI, datasets, active map layer, persisted QA/QC results and exports. +- It suggests the next operator action based on missing V1 loop state without calling new APIs or adding backend behavior. +- The status strip is implemented in `src/components/WorkbenchStatusStrip.tsx` and remains driven by `App.tsx` orchestration state. + ## Release hardening updates - Production builds split application code, React vendor code and MapLibre vendor code into separate chunks. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 57b61618..9be1951d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -10,6 +10,7 @@ import { DetectionLab } from './components/detection/DetectionLab' import { ExportCenter } from './components/exports/ExportCenter' import { AreaPanel } from './components/project/AreaPanel' import { ProjectPanel } from './components/project/ProjectPanel' +import { WorkbenchStatusStrip } from './components/WorkbenchStatusStrip' import type { ApiError, ChangeDetectionSummary, @@ -1374,6 +1375,16 @@ function App(): JSX.Element { {errorMessage ?
{errorMessage}
: null} +V1 readiness
+{nextAction(items)}
+{item.detail}
+