[M3] No UI path creates a slab: capture → slab handoff is missing (APP-15, APP-20) #81

Closed
opened 2026-09-20 18:16:47 +00:00 by grokbot_ty · 0 comments
Owner

Summary

Nothing in the frontend ever creates a slab. POST /api/v1/slabs exists and is green in tests, but no screen calls it, and the capture flow (M2, fully built) never posts anything. The result is that every M3 screen — Photos, Review, Publish, Generate — requires the owner to hand-type a slab UUID, and there is no way to arrive at Review from a Photos-ready capture. This is the mechanical reason #77's flow cannot be walked end to end.

Found in a read-only review of main @ b99cbdf (2026-09-20). 63 backend tests pass and both docs gates pass at that commit; these are gaps the green suite does not cover.

Observed evidence

Every /api/v1 call site in frontend/src (exhaustive grep):

api/slabs.ts:46            GET  /api/v1/slabs                (list)
api/slabs.ts:50            GET  /api/v1/slabs/{id}
create/photos/PhotoAttach  GET/POST /api/v1/slabs/{id}/photos[...]
create/review/Review       POST /api/v1/slabs/{id}/review
create/publish/Publish     POST /api/v1/slabs/{id}/publish
create/inference/GenerateText  POST .../inference/call1|call2
create/settings/Settings   GET/PUT /api/v1/settings, test-woo, test-inference

There is no POST /api/v1/slabs. frontend/src/capture/session.ts contains no fetch/POST at all — the capture draft lives only in IndexedDB. frontend/src/App.svelte:61-102 renders the capture states and nothing on the "continue" path hands a slab id to any create screen; App.svelte:103-128 mounts the six M3 components as (dev) toggles with no props and no shared state (each has its own local slabId text input).

Compounding: backend/slabs.py:100-102 rejects a create unless all 29 ALLOWED_FIELDS are present, including the client-derived math (sqft, bdft, widths) — so the handoff has to send the full calibrated slab, not an id.

Acceptance

  • "Continue" from a Photos-ready capture creates the slab (APP-15/APP-20: client-generated id, device draft retained) and carries the id into the next screen.
  • The M3 screens receive the slab by id via one owner of navigation state; no screen asks the owner to type a UUID.
  • An E2E drives capture → slab row created → Review loads the same slab. Until that exists, QUALITY-50 has no honest evidence.

Related

  • #77 (Review/Publish UI rebuild), #42, #46
  • Requirements: APP-5, APP-10, APP-15, APP-20, QUALITY-50
  • Harness prerequisite: frontend/vite.config.ts declares no /api proxy and playwright.config.ts runs npm run build && npm run preview on :4173, so any E2E written today would 404 against the API — fix the harness with this work.
## Summary Nothing in the frontend ever creates a slab. `POST /api/v1/slabs` exists and is green in tests, but no screen calls it, and the capture flow (M2, fully built) never posts anything. The result is that every M3 screen — Photos, Review, Publish, Generate — requires the owner to hand-type a slab UUID, and there is no way to arrive at Review from a Photos-ready capture. This is the mechanical reason `#77`'s flow cannot be walked end to end. Found in a read-only review of `main` @ `b99cbdf` (2026-09-20). 63 backend tests pass and both docs gates pass at that commit; these are gaps the green suite does not cover. ## Observed evidence Every `/api/v1` call site in `frontend/src` (exhaustive grep): ``` api/slabs.ts:46 GET /api/v1/slabs (list) api/slabs.ts:50 GET /api/v1/slabs/{id} create/photos/PhotoAttach GET/POST /api/v1/slabs/{id}/photos[...] create/review/Review POST /api/v1/slabs/{id}/review create/publish/Publish POST /api/v1/slabs/{id}/publish create/inference/GenerateText POST .../inference/call1|call2 create/settings/Settings GET/PUT /api/v1/settings, test-woo, test-inference ``` There is **no** `POST /api/v1/slabs`. `frontend/src/capture/session.ts` contains no `fetch`/POST at all — the capture draft lives only in IndexedDB. `frontend/src/App.svelte:61-102` renders the capture states and nothing on the "continue" path hands a slab id to any create screen; `App.svelte:103-128` mounts the six M3 components as `(dev)` toggles with no props and no shared state (each has its own local `slabId` text input). Compounding: `backend/slabs.py:100-102` rejects a create unless **all 29 `ALLOWED_FIELDS`** are present, including the client-derived math (`sqft`, `bdft`, widths) — so the handoff has to send the full calibrated slab, not an id. ## Acceptance - "Continue" from a Photos-ready capture creates the slab (`APP-15`/`APP-20`: client-generated id, device draft retained) and carries the id into the next screen. - The M3 screens receive the slab by id via one owner of navigation state; no screen asks the owner to type a UUID. - An E2E drives capture → slab row created → Review loads the same slab. Until that exists, `QUALITY-50` has no honest evidence. ## Related - `#77` (Review/Publish UI rebuild), `#42`, `#46` - Requirements: APP-5, APP-10, APP-15, APP-20, QUALITY-50 - Harness prerequisite: `frontend/vite.config.ts` declares no `/api` proxy and `playwright.config.ts` runs `npm run build && npm run preview` on :4173, so any E2E written today would 404 against the API — fix the harness with this work.
grokbot_ty added the blocking label 2026-09-20 18:16:47 +00:00
Sign in to join this conversation.
No Label blocking
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Ty_Tech/SlabUploader#81