diff --git a/apps/web/README.md b/apps/web/README.md index e8fc77f..39de616 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -94,7 +94,9 @@ is running on a non-default port. The shell labels all demo content as simulator-backed data and states that the scenario is synthetic local data, not real plant data. The pages include loading -states, empty states, and simple user-readable API error states. +states, empty states, and simple user-readable API error states. Empty and +missing demo-data states show a short `Next step:` line so a presenter can +recover without treating local setup drift as a product failure. ## Governance Decision Feedback diff --git a/apps/web/app/components/demo-state.tsx b/apps/web/app/components/demo-state.tsx index 598e657..61dbb3c 100644 --- a/apps/web/app/components/demo-state.tsx +++ b/apps/web/app/components/demo-state.tsx @@ -1,3 +1,5 @@ +import type { ReactNode } from "react"; + import type { HealthResponse } from "../../lib/api-client"; import { getApiBaseUrl } from "../../lib/api-client"; @@ -16,6 +18,7 @@ type DemoDataBadgeProps = { }; type EmptyStateProps = { + nextStep?: string; title: string; text: string; }; @@ -24,6 +27,12 @@ type LoadingStateProps = { title?: string; }; +type MissingDataPanelProps = { + nextStep: string; + title: string; + text: ReactNode; +}; + type StatusBadgeProps = { label?: string; tone?: @@ -106,20 +115,31 @@ export function DemoDataBadge({ ); } -export function EmptyState({ title, text }: EmptyStateProps) { +export function EmptyState({ nextStep, title, text }: EmptyStateProps) { + return ( +
{detectionId}. Open the detection list and choose a
current demo detection.
- {buildTimelineMeaning(evidenceItems)}
Run the demo simulator and Process Sentinel to populate this panel.
+
+ Run make demo, start the local API, and refresh this
+ page to populate this panel.
+
{result.detectionId}. Open a current demo detection and
use its RCA/CAPA draft link.
- make demo<\/code>/);
+ assert.match(detections, /The local API is reachable, but it did not return any Process Sentinel detections/);
+ assert.match(detections, /Run make demo from the repository root/);
+ assert.match(detail, /Detection not found/);
+ assert.match(detail, /No evidence available/);
+ assert.match(detail, /rerun make demo if local state was reset/);
+ assert.match(recommendations, /No recommendations returned/);
+ assert.match(recommendations, /No linked recommendation found/);
+ assert.match(recommendations, /Run make demo so Process Sentinel can create the demo recommendation/);
+ assert.match(draft, /Draft not found/);
+ assert.match(draft, /No detection available for draft preview/);
+ assert.match(draft, /Run make demo, then open the draft/);
+ assert.match(styles, /missing-data-panel/);
+ assert.match(styles, /min-height: 260px/);
+});
+
test("operations workbench docs link to the demo runbook", async () => {
const rootReadme = readFileSync(join(root, "..", "..", "README.md"), "utf8");
const appReadme = readFileSync(join(root, "README.md"), "utf8");
diff --git a/docs/LEARNING_LOG.md b/docs/LEARNING_LOG.md
index e4c8290..222665b 100644
--- a/docs/LEARNING_LOG.md
+++ b/docs/LEARNING_LOG.md
@@ -3370,3 +3370,51 @@ npm run typecheck
Practice the demo with the API intentionally stopped once, then confirm the
presenter can recover using only the visible target and recovery guidance.
+
+## 2026-05-22 - Workbench empty and error state audit
+
+### What changed
+
+Tightened the Operations Workbench loading, empty, missing-data, and API-error
+states for issue #177. Empty and missing demo-data panels now use status
+semantics and short `Next step:` recovery copy, while API connection failures
+remain alert panels with local API guidance.
+
+### Why it was built that way
+
+The Workbench already had the required routes and most state panels, so the
+smallest useful change was to refine existing components and route copy instead
+of adding a global error boundary or production monitoring feature. Missing demo
+data is separated from API connectivity to keep local rehearsal issues from
+looking like product failures.
+
+### How data flows through it
+
+Each route still calls the existing local FastAPI endpoints. Empty arrays and
+404-style missing IDs render local demo recovery panels. Network/API failures
+flow through `ApiErrorPanel`, preserving `role="alert"` and the configured API
+target guidance.
+
+### How to run it
+
+```bash
+make demo
+make api
+cd apps/web
+npm run dev
+```
+
+### How to test it
+
+```bash
+cd apps/web
+npm test
+npm run lint
+npm run typecheck
+make test-e2e
+```
+
+### What to learn next
+
+During rehearsal, intentionally visit a stale detection URL and confirm the
+presenter can recover from the visible `Next step:` text without opening docs.
diff --git a/docs/demo/TROUBLESHOOTING.md b/docs/demo/TROUBLESHOOTING.md
index 70691d3..85271a4 100644
--- a/docs/demo/TROUBLESHOOTING.md
+++ b/docs/demo/TROUBLESHOOTING.md
@@ -104,7 +104,7 @@ make demo
- `make demo-sentinel-run` prints `detections=0`.
- `/sentinel/detections` returns an empty list.
-- The Workbench detection list has no Process Sentinel case.
+- The Workbench detection list shows `No detections returned`.
- The recommendation queue is empty because no detection was created.
### Common causes
@@ -149,6 +149,9 @@ Confirm:
sentinel complete: detections=1 evidence=2 recommendations=1
```
+Refresh the Workbench after the API is started. Empty-state panels indicate the
+local API is reachable but the expected simulator-backed demo state is missing.
+
## API Not Running
### Symptoms
@@ -319,6 +322,29 @@ Expected fields include:
The draft is advisory decision support only. It does not create, close, or
submit a CAPA.
+## Workbench Missing-State Panels
+
+### Symptoms
+
+- A page shows `Detection not found`, `No evidence available`,
+ `No linked recommendation found`, or `No detection available for draft
+ preview`.
+- The API target is reachable, but the selected ID or generated local state does
+ not match the current demo run.
+
+### Recovery
+
+Use the visible `Next step:` line in the Workbench panel first. For a clean
+manufacturer demo reset, rebuild deterministic state:
+
+```bash
+make demo
+```
+
+Restart the API if it was already running, then refresh the Workbench. These
+missing-state panels are local demo recovery states; they are not production
+incident handling or real plant failure modes.
+
## Recommendation Decision Not Updating
### Symptoms