diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6b557b9..f33a44eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,13 @@
# Changelog
+## Sprint 100 raster tile Segmentation Lab handoff (2026-06-24)
+
+- Added Segmentation Lab tile manifest state and wired it into the existing segmentation run request `tile_manifest_path`.
+- Added a raster inspector handoff action that fills the selected raster dataset and tile manifest path in Segmentation Lab.
+- Mirrored the existing Detection Lab manifest input pattern without adding new backend routes, migrations, AI dependencies or model behavior.
+- Added regression coverage for the segmentation handoff wiring.
+
## Sprint 99 raster tile Detection Lab handoff (2026-06-23)
- Surfaced the latest persisted `raster.tile` manifest path in the raster dataset inspector.
diff --git a/backend/tests/test_sprint100_segmentation_manifest_handoff.py b/backend/tests/test_sprint100_segmentation_manifest_handoff.py
new file mode 100644
index 00000000..9256662f
--- /dev/null
+++ b/backend/tests/test_sprint100_segmentation_manifest_handoff.py
@@ -0,0 +1,28 @@
+from pathlib import Path
+
+
+ROOT = Path(__file__).resolve().parents[2]
+
+
+def test_raster_tile_manifest_can_handoff_to_segmentation_lab() -> None:
+ app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8")
+ hook = (ROOT / "frontend" / "src" / "hooks" / "useSegmentationWorkflow.ts").read_text(encoding="utf-8")
+ detail_panel = (ROOT / "frontend" / "src" / "components" / "datasets" / "DatasetDetailPanel.tsx").read_text(encoding="utf-8")
+ raster_controls = (ROOT / "frontend" / "src" / "components" / "datasets" / "RasterControls.tsx").read_text(encoding="utf-8")
+ segmentation_lab = (ROOT / "frontend" / "src" / "components" / "segmentation" / "SegmentationLab.tsx").read_text(
+ encoding="utf-8",
+ )
+
+ assert "segmentationTileManifestPath" in hook
+ assert "setSegmentationTileManifestPath" in hook
+ assert "tile_manifest_path: segmentationTileManifestPath.trim() || null" in hook
+ assert "segmentationTileManifestPath={segmentationTileManifestPath}" in app
+ assert "onSetTileManifestPath={setSegmentationTileManifestPath}" in app
+ assert "onUseTileManifestForSegmentation: useRasterTileManifestForSegmentation" in app
+ assert "setSegmentationTileManifestPath(manifestPath)" in app
+ assert "setSelectedSegmentationDatasetId(selectedDataset.id)" in app
+ assert "onUseTileManifestForSegmentation" in detail_panel
+ assert "Use in Segmentation Lab" in raster_controls
+ assert "disabled={!latestRasterTileManifestPath}" in raster_controls
+ assert "Tile manifest" in segmentation_lab
+ assert "Raster tile manifest path" in segmentation_lab
diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md
index a5917c6d..844f8920 100644
--- a/docs/CODEX_EXECUTION_LOG.md
+++ b/docs/CODEX_EXECUTION_LOG.md
@@ -1,3 +1,34 @@
+## Sprint 100 raster tile Segmentation Lab handoff (2026-06-24)
+
+Changed:
+- Added `segmentationTileManifestPath` state to `frontend/src/hooks/useSegmentationWorkflow.ts`.
+- Sent `tile_manifest_path` in existing segmentation run requests when the field is populated.
+- Added a `Tile manifest` input to `frontend/src/components/segmentation/SegmentationLab.tsx`.
+- Added a `Use in Segmentation Lab` handoff beside the existing Detection Lab handoff in `frontend/src/components/datasets/RasterControls.tsx`.
+- Wired the handoff through `frontend/src/components/datasets/DatasetDetailPanel.tsx` and `frontend/src/App.tsx`.
+- Updated `frontend/README.md` and `CHANGELOG.md`.
+- Added `backend/tests/test_sprint100_segmentation_manifest_handoff.py`.
+
+Validation:
+- RED: `python -m pytest backend\tests\test_sprint100_segmentation_manifest_handoff.py -q` failed before implementation because segmentation manifest state and handoff wiring did not exist.
+- `python -m pytest backend\tests\test_sprint100_segmentation_manifest_handoff.py -q` passed.
+- `cd frontend && npm run typecheck` passed.
+- `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 -q` passed: 17 tests.
+- `cd frontend && npm run build` passed.
+- `python -m compileall backend/app` passed.
+- `python -m pytest -q` from `backend/` passed: 323 tests.
+- `bash scripts/run_readiness_check.sh` passed.
+- `cd backend && python -m alembic heads` passed: `202606120900 (head)`.
+- `cd backend && python -m alembic upgrade head --sql` passed.
+- `bash -n scripts/live_migration_smoke.sh` passed.
+
+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:
+- Run full readiness, redeploy, then validate live bundle markers and raster demo smoke on `http://192.168.10.150:1202`.
+
## Sprint 99 raster tile Detection Lab handoff (2026-06-23)
Changed:
diff --git a/frontend/README.md b/frontend/README.md
index 6d4322b0..85f3f512 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -277,7 +277,7 @@ AI Lab run controls explicitly explain when no raster dataset is available, inst
- When the Map workspace has no active result layer, it lists ready vector/GeoJSON datasets as direct quick actions so populated demo projects can jump straight from the empty state to map inspection.
- The Data catalog shows a compact selected/reference/candidate/source summary and scan-friendly badges. Persisted `reference` datasets are shown as Reference, non-reference vector/GeoJSON layers are shown as QA Candidates for workbench scanning, and raster/other uploads remain Source.
- Dataset cards explain the recommended next action and use compact two-line action buttons for inspect, map, export/QA and metadata refresh. Disabled actions keep a visible reason, such as `Vector/GeoJSON only`.
-- Raster controls show the latest generated tile manifest path from persisted `raster.tile` jobs and can hand that path directly to Detection Lab with the selected raster dataset.
+- Raster controls show the latest generated tile manifest path from persisted `raster.tile` jobs and can hand that path directly to Detection Lab or Segmentation Lab with the selected raster dataset.
- The QA/QC workspace shows candidate/reference handoff cards and resolves persisted quality-check dataset IDs back to dataset names when the datasets are loaded in the current project context.
- The QA/QC workspace includes a selected-check evidence drilldown with candidate/reference provenance, false-positive/negative metric evidence, map handoff context and parameters/findings JSON.
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index ccb73835..26b69ed5 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -271,6 +271,7 @@ function App(): JSX.Element {
selectedSegmentationDatasetId,
selectedSegmentationModelId,
selectedSegmentationModel,
+ segmentationTileManifestPath,
segmentationConfidenceThreshold,
runningSegmentation,
segmentationRunResult,
@@ -294,6 +295,7 @@ function App(): JSX.Element {
resetSegmentationForProject,
setSelectedSegmentationDatasetId,
setSelectedSegmentationModelId,
+ setSegmentationTileManifestPath,
setSegmentationConfidenceThreshold,
setSelectedSegmentationRunId,
setSegmentationClassFilter,
@@ -306,6 +308,15 @@ function App(): JSX.Element {
loadProjectData,
loadQualityChecks,
})
+ const useRasterTileManifestForSegmentation = () => {
+ const manifestPath = latestRasterTileManifestPath.trim()
+ if (!manifestPath || !selectedDataset || selectedDataset.dataset_type !== 'raster') {
+ return
+ }
+ setSegmentationTileManifestPath(manifestPath)
+ setSelectedSegmentationDatasetId(selectedDataset.id)
+ setActiveWorkspace('ai')
+ }
const {
exports,
latestExport,
@@ -859,6 +870,7 @@ function App(): JSX.Element {
segmentationModelError={segmentationModelError}
selectedSegmentationDatasetId={selectedSegmentationDatasetId}
selectedSegmentationModelId={selectedSegmentationModelId}
+ segmentationTileManifestPath={segmentationTileManifestPath}
segmentationConfidenceThreshold={segmentationConfidenceThreshold}
runningSegmentation={runningSegmentation}
segmentationRunResult={segmentationRunResult}
@@ -881,6 +893,7 @@ function App(): JSX.Element {
onLoadModels={loadSegmentationModels}
onSelectDataset={setSelectedSegmentationDatasetId}
onSelectModel={setSelectedSegmentationModelId}
+ onSetTileManifestPath={setSegmentationTileManifestPath}
onSetConfidenceThreshold={setSegmentationConfidenceThreshold}
onRunSegmentation={runSegmentation}
onLoadRuns={() => loadSegmentationRuns()}
@@ -999,6 +1012,7 @@ function App(): JSX.Element {
onRunRasterClip: runRasterClip,
onRunRasterTile: runRasterTile,
onUseTileManifestForDetection: useRasterTileManifestForDetection,
+ onUseTileManifestForSegmentation: useRasterTileManifestForSegmentation,
onRunRasterNdvi: runRasterNdvi,
onRunRasterNdwi: runRasterNdwi,
onRunRasterNdbi: runRasterNdbi,
diff --git a/frontend/src/components/datasets/DatasetDetailPanel.tsx b/frontend/src/components/datasets/DatasetDetailPanel.tsx
index ba7365f6..6f64a2b8 100644
--- a/frontend/src/components/datasets/DatasetDetailPanel.tsx
+++ b/frontend/src/components/datasets/DatasetDetailPanel.tsx
@@ -59,6 +59,7 @@ export interface DatasetDetailPanelProps {
onRunRasterClip: () => void
onRunRasterTile: () => void
onUseTileManifestForDetection: () => void
+ onUseTileManifestForSegmentation: () => void
onRunRasterNdvi: () => void
onRunRasterNdwi: () => void
onRunRasterNdbi: () => void
@@ -142,6 +143,7 @@ export function DatasetDetailPanel({
onRunRasterClip,
onRunRasterTile,
onUseTileManifestForDetection,
+ onUseTileManifestForSegmentation,
onRunRasterNdvi,
onRunRasterNdwi,
onRunRasterNdbi,
@@ -209,6 +211,7 @@ export function DatasetDetailPanel({
onRunRasterClip={onRunRasterClip}
onRunRasterTile={onRunRasterTile}
onUseTileManifestForDetection={onUseTileManifestForDetection}
+ onUseTileManifestForSegmentation={onUseTileManifestForSegmentation}
onRunRasterNdvi={onRunRasterNdvi}
onRunRasterNdwi={onRunRasterNdwi}
onRunRasterNdbi={onRunRasterNdbi}
diff --git a/frontend/src/components/datasets/RasterControls.tsx b/frontend/src/components/datasets/RasterControls.tsx
index f7d57142..8234ec93 100644
--- a/frontend/src/components/datasets/RasterControls.tsx
+++ b/frontend/src/components/datasets/RasterControls.tsx
@@ -40,6 +40,7 @@ interface RasterControlsProps {
onRunRasterClip: () => void
onRunRasterTile: () => void
onUseTileManifestForDetection: () => void
+ onUseTileManifestForSegmentation: () => void
onRunRasterNdvi: () => void
onRunRasterNdwi: () => void
onRunRasterNdbi: () => void
@@ -93,6 +94,7 @@ export function RasterControls({
onRunRasterClip,
onRunRasterTile,
onUseTileManifestForDetection,
+ onUseTileManifestForSegmentation,
onRunRasterNdvi,
onRunRasterNdwi,
onRunRasterNdbi,
@@ -168,6 +170,9 @@ export function RasterControls({
+
diff --git a/frontend/src/components/segmentation/SegmentationLab.tsx b/frontend/src/components/segmentation/SegmentationLab.tsx
index a404c488..b8bbb02d 100644
--- a/frontend/src/components/segmentation/SegmentationLab.tsx
+++ b/frontend/src/components/segmentation/SegmentationLab.tsx
@@ -13,6 +13,7 @@ interface SegmentationLabProps {
segmentationModelError: string | null
selectedSegmentationDatasetId: string
selectedSegmentationModelId: string
+ segmentationTileManifestPath: string
segmentationConfidenceThreshold: number
runningSegmentation: boolean
segmentationRunResult: SegmentationRunResponse | null
@@ -35,6 +36,7 @@ interface SegmentationLabProps {
onLoadModels: () => void
onSelectDataset: (datasetId: string) => void
onSelectModel: (modelId: string) => void
+ onSetTileManifestPath: (value: string) => void
onSetConfidenceThreshold: (value: number) => void
onRunSegmentation: () => void
onLoadRuns: () => void
@@ -52,6 +54,7 @@ export function SegmentationLab({
segmentationModelError,
selectedSegmentationDatasetId,
selectedSegmentationModelId,
+ segmentationTileManifestPath,
segmentationConfidenceThreshold,
runningSegmentation,
segmentationRunResult,
@@ -74,6 +77,7 @@ export function SegmentationLab({
onLoadModels,
onSelectDataset,
onSelectModel,
+ onSetTileManifestPath,
onSetConfidenceThreshold,
onRunSegmentation,
onLoadRuns,
@@ -183,6 +187,15 @@ export function SegmentationLab({
/>
+