diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c5cf655..0173ab33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ # Changelog +## Sprint 90 workflow guidance polish (2026-06-20) + +- Added an Overview workflow guidance rail for the V1 path: Project & AOI, Data, Map, QA / AI and Export. +- The guidance rail uses existing workspace navigation only; it does not add API calls, backend behavior or persistence. +- Added compact ready/waiting/next visual states based on already loaded project, dataset, map, QA/AI and export state. +- Added regression coverage for the guidance rail, existing workspace routing and responsive CSS contracts. +- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed. + ## Sprint 89 Export/System density polish (2026-06-20) - Grouped Export Center summary, handoff readiness, artifact actions, state cards and history into focused surfaces. diff --git a/backend/tests/test_sprint90_workflow_guidance.py b/backend/tests/test_sprint90_workflow_guidance.py new file mode 100644 index 00000000..d6f2e859 --- /dev/null +++ b/backend/tests/test_sprint90_workflow_guidance.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_overview_exposes_end_to_end_workflow_guidance() -> None: + app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") + + assert 'aria-label="V1 workflow guidance"' in app + assert 'className="workflow-guidance-panel"' in app + assert 'className="workflow-guidance-steps"' in app + assert "workflowGuidanceSteps.map" in app + assert "Project & AOI" in app + assert "Data" in app + assert "Map" in app + assert "QA / AI" in app + assert "Export" in app + + +def test_workflow_guidance_routes_to_existing_workspaces() -> None: + app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") + + assert "target: 'data'" in app + assert "target: 'map'" in app + assert "target: 'analysis'" in app + assert "target: 'exports'" in app + assert "onOpenAiWorkspace={() => setActiveWorkspace('ai')}" in app + assert "onClick={() => setActiveWorkspace(step.target)}" in app + + +def test_workflow_guidance_has_responsive_contracts() -> None: + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert ".workflow-guidance-panel" in css + assert ".workflow-guidance-steps" in css + assert ".workflow-guidance-step" in css + assert ".workflow-guidance-step-active" in css + assert ".workflow-step-status" in css + assert "grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));" in css diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 7b65c151..b39ffa86 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -3245,3 +3245,34 @@ Limitations: 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-panel` that 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 `setActiveWorkspace` navigation only. +- Added compact responsive CSS for the guidance rail. +- Added `backend/tests/test_sprint90_workflow_guidance.py`. +- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`. + +Tested: +- Red step: `python -m pytest backend/tests/test_sprint90_workflow_guidance.py -q` failed 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 typecheck` +- `cd frontend && npm run build` +- `bash scripts/run_readiness_check.sh` (`306 passed`; frontend typecheck/build passed; Alembic head `202606120900`; live smoke syntax passed) +- Local browser UI check against `http://127.0.0.1:5174` passed 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.ps1` rebuilt and restarted the all-in-one container on `http://192.168.10.150:1202` from commit `2a0e7e7`. +- Tower deploy live migration smoke passed with PostGIS `3.6 USE_GEOS=1 USE_PROJ=1 USE_STATS=1` and 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:1202` passed 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. diff --git a/docs/TODO.md b/docs/TODO.md index be60f671..8fc0397b 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -361,3 +361,4 @@ This file now starts with the current implementation status. Older preparation/b - [x] Add QA/QC metric card polish for precision, recall, F1, IoU and error counts. - [x] Add mobile overflow hardening for workbench navigation, inspector and long QA identifiers. - [x] Add QA/QC result filtering and density controls for long-running demo projects. +- [x] Add Overview workflow guidance for the V1 project -> data -> map -> QA/AI -> export path. diff --git a/frontend/README.md b/frontend/README.md index 8cdc6fab..72ce1462 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -248,6 +248,7 @@ Detection Lab and Segmentation Lab now share the same AI workspace hierarchy: mo - The workbench shell includes a compact command bar, consistent raised/sunken surfaces, structured empty states and scroll-safe AI result tables to keep the V1 workflow usable across desktop and mobile widths. - The shell includes a keyboard skip link, an explicit primary workspace navigation label and compact horizontal context/navigation rails on narrow screens so active workspace content is reachable without a tall preamble. - The Overview workspace separates readiness, status tiles and recommended next actions into distinct visual hierarchy regions, keeping the first screen scannable without changing workflow behavior. +- The Overview workspace now also shows a compact workflow guidance rail for the V1 path from project and AOI setup through data, map review, QA/AI validation and export handoff. - The Data workspace surfaces selected project, AOI and dataset context before creation/upload forms, then separates form and catalog/list regions for faster scanning. - The Export Center includes a handoff readiness summary, grouped artifact actions and provenance-rich export cards so report/GeoJSON handoff stays understandable in long-running demo projects. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ac88dcdd..83094cb2 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -449,6 +449,67 @@ function App(): JSX.Element { } setActiveWorkspace('exports') } + const hasAnalysisOutput = qualityChecks.length > 0 || Boolean(changeDetectionResult) || detectionItems.length > 0 || segmentationItems.length > 0 + const recommendedWorkflowTarget: WorkspaceKey = !selectedProjectId + ? 'data' + : datasets.length === 0 + ? 'data' + : mapFeatureCount === 0 && areaFeatureCount === 0 + ? 'map' + : !hasAnalysisOutput + ? 'analysis' + : exports.length === 0 + ? 'exports' + : 'exports' + const workflowGuidanceSteps: Array<{ + step: string + title: string + detail: string + status: string + ready: boolean + target: WorkspaceKey + }> = [ + { + step: '1', + title: 'Project & AOI', + detail: selectedProjectId ? `${areas.length} AOI record${areas.length === 1 ? '' : 's'} available` : 'Create or load a project context', + status: selectedProjectId ? 'ready' : 'next', + ready: Boolean(selectedProjectId), + target: 'data', + }, + { + step: '2', + title: 'Data', + detail: datasets.length > 0 ? `${datasets.length} dataset${datasets.length === 1 ? '' : 's'} loaded` : 'Upload source and reference datasets', + status: datasets.length > 0 ? 'ready' : 'waiting', + ready: datasets.length > 0, + target: 'data', + }, + { + step: '3', + title: 'Map', + detail: mapFeatureCount > 0 || areaFeatureCount > 0 ? `${mapFeatureCount + areaFeatureCount} active map feature${mapFeatureCount + areaFeatureCount === 1 ? '' : 's'}` : 'Inspect AOI and selected layer', + status: mapFeatureCount > 0 || areaFeatureCount > 0 ? 'ready' : 'waiting', + ready: mapFeatureCount > 0 || areaFeatureCount > 0, + target: 'map', + }, + { + step: '4', + title: 'QA / AI', + detail: hasAnalysisOutput ? 'QA, change, detection or segmentation output exists' : 'Run checks after data is ready', + status: hasAnalysisOutput ? 'ready' : 'waiting', + ready: hasAnalysisOutput, + target: 'analysis', + }, + { + step: '5', + title: 'Export', + detail: exports.length > 0 ? `${exports.length} export artifact${exports.length === 1 ? '' : 's'} recorded` : 'Package validated project outputs', + status: exports.length > 0 ? 'ready' : 'waiting', + ready: exports.length > 0, + target: 'exports', + }, + ] return (
@@ -539,6 +600,40 @@ function App(): JSX.Element { activeLayerFeatureCount={mapFeatureCount} selectedAreaHasGeometry={Boolean(areaFeatureCollection)} /> +
+
+
+

Workbench flow

+

Project to export path

+
+ + Next: {workspaceNavItems.find((item) => item.key === recommendedWorkflowTarget)?.label ?? 'Overview'} + +
+
+ {workflowGuidanceSteps.map((step) => ( + + ))} +
+

Recommended flow

diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index da2828d4..59d998c4 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -835,6 +835,62 @@ section li strong + div { align-self: stretch; } +.workflow-guidance-panel { + display: grid; + gap: 0.72rem; + border-left: 4px solid #2563eb; + background: linear-gradient(180deg, #ffffff, #f7fbf8); +} + +.workflow-guidance-panel .panel-title-row { + margin-bottom: 0; +} + +.workflow-guidance-steps { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); + gap: 0.55rem; +} + +.workflow-guidance-step { + display: grid; + align-content: start; + gap: 0.28rem; + min-height: 5.35rem; + border-color: var(--line); + padding: 0.62rem 0.68rem; + background: #ffffff; + text-align: left; + box-shadow: none; +} + +.workflow-guidance-step small { + color: var(--muted); + font-size: 0.78rem; + font-weight: 600; + line-height: 1.3; +} + +.workflow-guidance-step-active { + border-color: rgba(15, 118, 110, 0.46); + background: var(--accent-soft); + box-shadow: inset 0 0 0 1px rgba(15, 118, 110, 0.12); +} + +.workflow-guidance-step-ready { + border-color: rgba(21, 128, 61, 0.28); + background: #f2fbf5; +} + +.workflow-step-status { + color: var(--muted); + font-size: 0.68rem; + font-weight: 850; + letter-spacing: 0.05em; + line-height: 1.2; + text-transform: uppercase; +} + .overview-actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(16rem, 24rem);