From a719fa9fc6359cecd4a653e7a21e26c5e6d7bb98 Mon Sep 17 00:00:00 2001 From: Ty Date: Fri, 11 Sep 2026 13:47:25 +0000 Subject: [PATCH] docs: remove live UX.md --- docs/UX.md | 235 ----------------------------------------------------- 1 file changed, 235 deletions(-) delete mode 100644 docs/UX.md diff --git a/docs/UX.md b/docs/UX.md deleted file mode 100644 index b1bfc91..0000000 --- a/docs/UX.md +++ /dev/null @@ -1,235 +0,0 @@ -# Mill-owner UX — phone and PC browsers - -Status: SIGNED · 2026-09-06 PT · Ty approved with PC browsers in the compatibility matrix · SlabUploader - -This is the presentation spec for the mill-owner flow. It says what a mill owner sees and does, in the -order they do it. The rules behind each screen live elsewhere: `AGENTS.md` locks the product -decisions, `docs/TECH-SPEC-PIPELINE.md` owns the math and image prep, `docs/DATA-MODEL.md` owns -the store row and its statuses, `docs/CONTENT-WOO.md` owns listing copy and the Woo payload, -and `docs/OPENAPI.md` owns the wire. This file names what shows up on screen; it does not restate -those rules. - -The reader is a mill owner photographing one slab at a time, online, from a supported browser on a -phone or a PC. The app is a single column of screens, top to bottom: capture, then review, then -publish. There is no dashboard and no batch view in this version. Capture often starts on a phone -camera; the same flow must also run on a PC browser. - -## Jobs - -Five jobs cover the whole flow. Each section below names what the owner does, what they see, and -the lock that governs it. - -1. **Phone photo to a store listing.** Photograph the slab, confirm the cut and the numbers on - the browser, review the listing, create the WooCommerce product. The happy path stays in the - browser until the owner confirms the mask and the numbers. -2. **Practice drafts customers never see.** A practice run creates a WooCommerce draft with an SKU - that starts `SLAB-UAT-`. Customers cannot open it. It is always a draft, even when Settings say - publish. -3. **Retake when the overlay cut looks wrong.** The mask overlay on the source photo is the only - quality check. If the edge is off after tuning the four knobs, the owner retakes the photo. -4. **Fill or override store fields.** On review, the owner fills every required field by hand, or - keeps what vision filled when it was confident enough. Typed values always win. -5. **Publish.** The owner taps publish. The server creates the product in the store and reports the - result back on the same screen. - -## Capture: photo to numbers - -The capture flow is one continuous screen with a few confirmations, not separate pages. The owner -stays on it from first photo through confirmed mask and axis. - -### Photos - -The owner takes 1 to 5 inventory photos of the slab. The first should be top-down, lens parallel -to the broad face; a tilted shot makes square feet and board feet wrong, and retake is the fix. -There are no calibration photos in this design. Only inventory photos exist. - -### Mask overlay and four knobs - -The app removes the background sheet and draws the mask as an overlay on the source photo, showing -which pixels count as slab and which do not. The owner reviews that edge against the real wood. -This is the only quality check in the pipeline. There is no confidence score, no auto-gate, and no -photo-quality checker. A clipped or over-inclusive mask shifts every downstream number with nothing -later to catch it, so the eye on the overlay is what stands behind the measurement. - -Four knobs sit on this same screen, next to the overlay: - -- **Sheet** — auto, green, or black. Auto samples the borders and picks; the owner overrides when - the sheet is an odd color. -- **Sensitivity** — one slider from tighter to looser detection. -- **Edge offset** — pulls the cut in or out a few pixels so it sits on the wood, not in the sheet - or into the grain. -- **Feather** — hard edge versus a couple of pixels of blend. - -Changing any knob re-runs background removal immediately and refreshes the overlay. There is no -apply step and no server round trip for mask tuning in this version. The four values persist on the -browser until reset to default; they are not Settings fields. - -If the edge still looks wrong after tuning, the owner retakes the photo. That is the resolution in -this version. A server-side matting path exists in the architecture for awkward backgrounds later, -but it is deferred and has no control here. - -### Length axis - -After the mask is confirmed, the app draws the bounding rectangle and the length axis over the slab, -with width sample lines perpendicular to that axis. The owner confirms the axis follows the -slab's prevailing length. If it is skewed, they rotate it; samples and square feet update live. On a -nearly square slab the owner says which way is length. - -### Numbers - -The owner enters length (in 1/8" steps), thickness (a 1/8" pick), and the SKU by hand. The browser -then computes square feet, board feet, and width samples from the confirmed mask and axis: - -- Board feet = square feet × thickness in inches. One square foot at one inch thick is one board - foot. There is no divide-by-12. -- Widths are sampled every 6" along the length axis; the listing carries min, max, and average. -- Square feet and board feet show to two decimals. - -These numbers are computed in the browser and stored as sent. The server does not recompute them. - -### Photo prep - -Each inventory photo is cropped to a 3:4 portrait frame with the slab centered at 80% fill, saved as -a transparent PNG. If the source has enough pixels, the shorter side lands at 1600 or more after -crop. If it cannot reach that, the app warns and asks for a retake; it does not invent pixels. The -owner sees the processed result alongside the original while the draft is retained. - -### Continue - -When the mask, axis, length, thickness, and SKU are set, the owner continues. That uploads the -originals plus the processed PNGs plus the numbers to the server as a calibrated draft, and moves to -review. The slab status becomes `calibrated`. - -## Review: fill or override store fields - -Review is where the listing row gets filled. Every field below maps to a column in the `slabs` table -in `docs/DATA-MODEL.md`. The owner can type any of them; vision may have pre-filled some, but typed -values always win and every value stays editable. - -### What vision fills, and when - -When inference is on, Call 1 runs after the calibrated draft uploads. It sends all inventory photos -downscaled to 1024 plus the store's synced species and attribute lists, and returns a guess -with a confidence per field. The threshold is 0.7 by default: - -- A field at or above 0.7 pre-fills on review. It stays editable; the owner can change or clear it. -- A field below 0.7 starts empty. The app does not show the model's low-confidence guess as a - default, and an empty start is not the same as a finished listing. - -With inference off, every field starts empty and the owner fills all of them by hand. Inference -never blocks publish and never auto-publishes. Call 2 (Generate text) does not run on its own; it -fires only when the owner taps it. - -### The fields - -The required set for a list-ready slab is the full store row, not species plus one figure: - -- **SKU** — `[A-Z0-9-]{3,24}`. Practice runs use `SLAB-UAT-*`. -- **Length and thickness** — from capture; still editable here. -- **Square feet, board feet, widths** — shown as the client-computed values, with a manual override - path. The owner's typed number wins over the computed one. -- **Species** — exactly one leaf category from the synced store list. No hardcoded or invented - species; a new store species appears only after the next sync. -- **Wood categories** — at least one, from the synced list. -- **Edge type** — one term from the synced attributes. -- **Figure** — at least one term. -- **Grade** — at least one term. -- **Thickness band** — the Woo range that the measured thickness rounds up into (for example, a 1" - pick lands in the `1"–1 1/2"` band). The exact labels come from the synced store attribute. -- **Moisture** — one term, defaulting to kiln-dried. It is never inferred; the owner sets or keeps it. -- **fig-* tags** — at least one. -- **feat-* tags** — zero or more (character, inclusions, voids, checks map to existing `feat-*` - tags only). -- **Price** — a recommendation pre-fills from the species $/bdft rule times board feet; the owner may - override and that sticks. With no rule for the species, the price starts empty and the owner types - it. Publish is still allowed with a manual price. - -Title, short title, and description are not required to reach ready. They can be typed by hand, -generated from templates at publish, or written by Generate text (Call 2) when enabled. Templates -always run; they inject the deterministic numbers so the model never touches dimensions. - -### How missing fields show up - -A field that is still empty and required shows its nudge inline, in place, the moment it is empty. -The owner sees each gap where it sits rather than learning about a problem after scrolling past it. -There is no single submit-time check that lists everything at once; the nudges are per-field as the -owner works. The slab cannot reach `ready` until the full set above is filled, whether by hand or by -a confident Call 1 the owner kept. - -### Generate text - -When content generation is enabled, a **Generate text** button runs Call 2 and fills title, short -title, and description with model prose plus template numbers. The owner can edit the result freely. -If the endpoint is missing or down, the button is disabled; templates still work and publish is never -blocked by a failed Generate text. - -## Publish: create the store listing - -The owner taps **Publish** when review is complete. What happens next depends on the SKU and Settings. - -### Draft versus live - -- A normal SKU publishes according to the `woo_create_status` setting, which defaults to draft. -- Any SKU matching `SLAB-UAT-*` always creates a WooCommerce draft, even if Settings say publish. - That is how practice runs stay invisible to customers. - -The app's "published" means the store create succeeded and the local row plus photos were cleaned up. -That is not the same as the product being live in the store; a draft is created but hidden until Ty -promotes it. - -### What the owner sees on each outcome - -- **Success.** The screen shows that the listing was created, with the store's product reference when - available. The local draft and its photos are gone from the app. -- **SKU already exists.** Under the SKU field: "This SKU already exists in the store (any status)." - Two paths appear: edit the SKU to a new value, or open the existing listing. This version does not - update the other product in place. The draft stays in the browser; nothing is lost. -- **A value no longer valid.** If a category, attribute, or price was removed from the store between - sync and publish, that field shows "This value is no longer valid. Pick from the current list," with - the current options. The owner re-picks and retries. -- **Store unreachable or other failure.** A plain message on the screen says the listing could not be - created and to try again. No status number, no stack trace, no raw error code reaches the owner. - -The server keeps a log of every attempt either way, so a failed publish can be retried from the same -screen without re-photographing. - - -## Browser compatibility - -Ty signed this walk on 2026-09-06 PT with one amendment: the compatibility matrix includes PC -browsers as well as phones. This app is not mobile-only. - -Supported families (matrix): - -- **Phone:** iOS Safari, Android Chrome -- **PC:** desktop Chrome, desktop Edge, desktop Firefox (Windows and macOS at minimum) - -Exact minimum version pins are still tracked under issue #4. The matrix above is the product lock -for which classes of client are in scope. - -Unsupported browser behavior: hard stop. Show a clear message that this browser is not supported, -with a link to update or switch to a supported browser. No polyfill -strategy in this version. - -Load-bearing client surfaces that must remain: canvas-based mask overlay and live knob re-run, -image crop/prep to 3:4 transparent PNG, file/photo intake for inventory shots, and the online API -calls for draft upload, review, and publish. Depth for APIs stays in `docs/TECH-SPEC-PIPELINE.md` -and `docs/OPENAPI.md`. - -## Deferred features - -Photo quality, OCR, ruler detection, server-side measuring, U2Net control, and offline capture are -deferred post-POC. The overlay edge plus the owner's eye is the only quality gate. SKU is typed by -hand. Length is entered by hand; the browser derives its own pixel-to-inch scale. The browser owns -the happy path for measuring and cropping. The U2Net one-photo contract stays in the architecture -for later. Capture is online only. - -## Where each job lives - -| Job | Screen(s) | Governing lock | -|---|---|---| -| Photo to listing | Capture through review to publish | AGENTS §1, TECH-SPEC, ARCHITECTURE swimlane | -| Practice drafts (`SLAB-UAT-*`) | Review (SKU field), Publish outcome | AGENTS §5, CONTENT-WOO payload status | -| Retake on bad cut | Capture mask overlay | TECH-SPEC §3.4–3.5, issue #15 | -| Fill or override fields | Review | DATA-MODEL `slabs`, AGENTS §6/7, issue #9 | -| Publish and recovery | Publish outcome states | CONTENT-WOO §2.5–2.6, OPENAPI 409/422, issue #18 |