From 6fb92362a4396a209b9cf8c7314f0b06c90931c4 Mon Sep 17 00:00:00 2001 From: Ty Date: Thu, 24 Sep 2026 13:44:53 -0700 Subject: [PATCH] docs(m4): M4 goals + task breakdown Goals: polish M3 + #99 tape-line, human-driven taxonomy review (thumb-first UI, Call 1 deferred), Call 2 inference refinement, real SLAB-UAT-* Woo draft exit. Tasks: 9-task / 5-phase breakdown with detail bar (skills, starting point, verification, sequence, stop condition, evidence boundary per task). Kickoff decisions folded in: full polish wave (#91-#100 minus #96), tape-line confined to calibration step, single-slab multi-photo exit walk. --- .planning/milestones/v0.5/M4/goals.md | 185 +++++++++++++++++++++++++ .planning/milestones/v0.5/M4/tasks.md | 188 ++++++++++++++++++++++++++ 2 files changed, 373 insertions(+) create mode 100644 .planning/milestones/v0.5/M4/goals.md create mode 100644 .planning/milestones/v0.5/M4/tasks.md diff --git a/.planning/milestones/v0.5/M4/goals.md b/.planning/milestones/v0.5/M4/goals.md new file mode 100644 index 0000000..c7648e4 --- /dev/null +++ b/.planning/milestones/v0.5/M4/goals.md @@ -0,0 +1,185 @@ +# M4 — Goals (DRAFT — not accepted) + +Role: goals for Milestone 4. Cites requirement IDs and Gitea issue numbers; defines none +new until accepted. Source of truth for scope will be `docs/MILESTONES.md` (M4 ID subset) +and `docs/REQUIREMENTS.md` (rows) after acceptance. + +**Base:** builds on branch `m4` (commit `818874e`, `feat(m4): crop_fill setting + tape-line +prototype (#99)`), which is 1 ahead of `origin/main`. #99 is in scope. + +**Objective:** Ship a polished, stable M3 experience with the tape-line calibration model, +a **human-driven taxonomy review** (Call 1 deferred; owner picks everything on a thumb-first +UI), **refined Call 2 long descriptions**, and a verified real WooCommerce draft submission. + +**Exit criterion:** A real `SLAB-UAT-*` Woo **draft** matching the reviewed ready set exists +in the store, created end-to-end through the M4 UI (tape-line calibration → human taxonomy +review → Call 2 long description → publish), with **no Call 1** in the path (inference +settings need not be vision-enabled). Call 2 is exercised on a live call at least once. +Raw runner evidence recorded; Ty owns gate exit (QUALITY-25/30). + +## Goals (accepted direction) + +1. **Stabilize + polish the M3 experience (A) — includes the #99 tape-line calibration (B).** + - **Tape-line calibration (#99):** replace the axis-rectangle calibration with a draggable + tape-line (black line + two rifle-scope end ticks). Declared length = distance between + ticks (owner-declared); `maskSpanAlong` demoted to an optional sanity check. New + requirement row(s); supersedes the as-built length model in CAPTURE-60/75. The `m4` + branch already carries `crop_fill` + `TapePrototype.svelte` (`?tape-prototype`); M4 + promotes it from prototype to shipped. + - **UX polish:** photo-picker look/feel (#91), photo filenames on submit (#92), capture + gated on a tested Woo connection (#93), review UI is always the human-pick flow (#94), + debug mode (#95), required-photo lock glyph (#100). (#96 Call 1/2 prompt viewer drops + with Call 1.) + - Post-launch issue work + the tape-line feature; no other new feature surface. + +2. **Human-driven taxonomy review + thumb-first UI (Call 1 deferred; Call 2 kept).** + - **Call 1 (vision) → deferred to future work.** Not in the MVP: no "Suggest with AI" + button, no auto-pre-fill, no confidence pre-fill, no AI markers on fields. The + inference settings need not be vision-enabled. + - **Owner picks everything Call 1 used to propose**, via a thumb-first, on-phone usable + UI: species (1 leaf), wood categories (primary + optional secondaries), Edge, Figure + (multi), Grade (owner judgment), Thickness band (derived, no pick), Moisture, and + `feat-*` / `fig-*` tags. All from the synced Woo taxonomy (METADATA-5/10/15/30). + - **Call 2 (text) stays** — writes the long description from the human-picked values + + dimension fact block; brand/geo context, primary + secondary categories. (Refining its + output quality is its own goal, #3 below.) + - **Title + short description remain deterministic** from the primary wood category + + dimension fact block (METADATA-80/85) — they depend only on the human's primary pick + + fact block, not on Call 1. + - **All METADATA requirements remain in scope** — the human collects the same data + Call 1 previously suggested, just by hand. + - **Wireframe first (a sprint task in this milestone):** before any review-UI coding, + produce a wireframe (2-3 HTML variants) to align on the overall flow — how the + thumb-first taxonomy collection, primary/secondary selection, and Call 2 generate + control compose on a phone. This is the design gate for the review work. + **Starting point (saved, recent):** `docs/design/issue-99-tape-line-overlay.html` + (approved #99 tape-line overlay wireframe, committed 2026-09-24 on + `issue-99-tape-line-overlay`). Do **not** build on the older `pre-simplification` + wireframes or the 2026-09-18 `ux-design.md` coverage matrix — those are stale. + - *To be scoped:* the exact thumb-first interaction model (wizard vs single-scroll, + chips vs pickers) — settled by the wireframe. + +3. **Refine Call 2 so it delivers better long descriptions.** + - Call 2 (text) stays in the MVP and is the inference work of this milestone: improve + how it turns the human-picked taxonomy + dimension fact block + brand/geo context into + a long description that reads well for the store. + - Levers (task-level, settled during the sprint): prompt revision (METADATA-105/106), + the dimension fact block as the only numbers it may print (METADATA-65/90/95), + primary + secondary category weighting, brand voice / geo context settings + (SETTINGS-30), and recoverable/unrecoverable failure (METADATA-115). + - Success is judged on the exit-walk description quality (Ty reads it), not on a proxy + metric. Raw evidence recorded. + +4. **Exit: real Woo draft submission.** + - PUBLISH-5 sequence, PUBLISH-10 (`SLAB-UAT-*` force draft), PUBLISH-25 (woo_product_id, + purge photos, discard local row, clear device draft). QUALITY-110 exit evidence. + +## Non-goals (excluded from M4) + +- **Call 1 (vision) inference** — deferred to future work. No auto-suggest, no confidence + pre-fill, no AI markers. METADATA-35/40/45/100 rows are out of the M4 active set. +- TLS on LAN transports (#78) — production-readiness, deferred. +- Backup/restore (OPS-30/35) — deferred ("Later"). +- Instrumentation: Prometheus metrics, alerting, log retention (#7/#16) — deferred. +- Store-admin species-leaf creation (#13), shared validation module (#17), 409/422 + field-level recovery (#18) — post-launch designs, deferred. +- Offline capture (CAPTURE-15), U2Net server matting (CAPTURE-165) — "Later". +- Browser e2e on all five clients (QUALITY-115) — "Later". +- Prompt-revision auth beyond trusted network (METADATA-107) — "Later". +- App login (relies on trusted LAN/Tailscale + HTTPS, OPS-55) — out of scope. + +## Assumptions + +- M4 does **not** add an app-level login; the trusted-network model (OPS-55) holds. +- The `m4` branch is the working base; `main` is the merge target once M4 is accepted and green. +- Inference endpoint is a remote, configurable endpoint (OPS-45); M4 refines prompts/calls, + not the endpoint transport. +- Real Woo for the exit walk; Woo mock is a dishonest proxy (QUALITY-105/110). +- Existing M3 requirement rows that the tape-line model supersedes (CAPTURE-60, CAPTURE-75) + are updated in place; new rows are added for the tape-line behavior. No row is deleted. + +## Requirements delta (draft — rows written at execution, after acceptance) + +- **New rows (draft):** tape-line calibration behavior (overlay, draggable ticks, + owner-declared length, sanity check). ~1–3 rows under CAPTURE. +- **New rows (draft):** the **manual taxonomy selection UI** — owner picks species / wood + categories (primary + secondary) / edge / figure / grade / moisture / tags by hand, + thumb-first, with no inference pre-fill. ~1 row under METADATA or REVIEW. +- **Superseded/updated rows (draft):** CAPTURE-60 (length axis), CAPTURE-75 (scale model) — + rewritten to the tape-line model. +- **Deferred rows (out of M4 active set):** METADATA-35/40/45/100 (Call 1 vision + suggestions + confidence gate) — moved to "Later"/future work. The rows stay in + REQUIREMENTS.md; only their M4 scope drops. +- **Refined rows (draft):** METADATA-55/60/65 (Call 2) — if the human-picked flow changes + normative Call 2 inputs (it shouldn't materially; Call 2 already receives the metadata + confirmed in review). +- **Refined rows (draft):** REVIEW-15/20/25/40 (review-workflow usability) — field layout, + nudge behavior, primary/secondary category interaction, generate-text control placement, + if the usability changes alter normative review behavior. #94 (conditional review UI) + now means: the review screen is **always** the human-pick flow (no inference on/off + branch for Call 1). +- **Unchanged (in M4 ID subset):** all PUBLISH, REVIEW, SETTINGS, APP, OPS-40, QUALITY rows + that M3 already shipped and M4 re-uses for the exit; METADATA-5/10/15/30/85 (the data the + human collects + the deterministic title/short-desc). + +## Acceptance criteria (draft) + +1. **Tape-line calibration + M3 polish ship together (Goal 1):** the `?tape-prototype` + sandbox is replaced by the shipped calibration path (owner drags both ticks; declared + length = tick distance; as-built length model no longer the source of truth), and the + M3 polish issues (#91–#100, excluding #96 which drops with Call 1) are closed with + passing tests and raw runner evidence. +2. **The review flow is human-driven, thumb-first, and Call 1-free:** the owner can pick + species, wood categories (primary + secondary), edge, figure, grade, moisture, and tags + by hand on a phone, with no "Suggest with AI" surface and no AI pre-fill. The wireframe + was accepted before coding (design gate). +3. **Call 2 (text) is exercised on a live call** during the exit walk and delivers a + description that reads well (Ty judges it); content-gen control visibility (METADATA-110), + recoverable/unrecoverable classification (METADATA-115), and prompt-revision API + (METADATA-105/106) all pass their tests. +4. **A real `SLAB-UAT-*` Woo draft** exists in the store matching the reviewed ready set + (QUALITY-110), with `woo_product_id` set, photos purged, local row discarded, device + draft cleared (PUBLISH-25). +5. **Gates pass:** `python tools/check_requirements.py` and `python tools/check_coverage.py` + exit 0; full suite passes with inference **and** off (QUALITY-20) — now including the + human-pick flow with Call 1 removed; raw evidence recorded. + +## Verification strategy (smallest that proves the claim) + +- **Deterministic core:** unit tests for tape-line geometry + `crop_fill` (existing + `frontend/src/png/*` test surface). +- **Integration:** Woo mock for the PUBLISH-5 sequence (success, duplicate SKU, stale field, + taxonomy anchor) — QUALITY-35/50. +- **Exit walk:** `deploy/uat_walk.sh` on the real store for the `SLAB-UAT-*` draft + (QUALITY-105/110) — the only proof that counts for the submission claim. +- **Ty owns gate exit** (QUALITY-30); agents record raw evidence, never declare green. + +## Task-level decisions (settled during the sprint, not at planning) + +These are implementation details the task breakdown and wireframe settle — not plan-level: +the exact thumb-first interaction model (wizard vs single-scroll, chips vs pickers), which +of #91–#100 are M4-must vs nice, whether #99 touches the photos-ready lineup (CAPTURE-130), +and the exit-walk shape (single slab vs QUALITY-110 pair; test-inference is text-only now +that Call 1 is out). + +## Task breakdown detail bar + +The task breakdown is not a list of goal names. Every task carries, at minimum: + +- **Goal it serves** (G1–G4) and the requirement IDs / issue numbers it touches. +- **Skills to load** for that task — named and ordered (e.g. UI task: `sketch` + + `wireframe-review-iteration` → `omh-frontend` + `omh-design-quality-gate` → + `omh-visual-qa` + `omh-accessibility-audit`). +- **Starting point / references** — the specific saved artifact, file, or branch the task + builds from (e.g. `docs/design/issue-99-tape-line-overlay.html`, the live + `Review.svelte`, the M3 `MultiSelect.svelte`). +- **Verification** — the smallest check that proves the task's claim (unit test paths, + `tsc --noEmit`, Woo mock, `deploy/uat_walk.sh`, 375/768/1280 visual captures, keyboard / + contrast audit). Ty owns gate exit. +- **Sequence / dependencies** — what must land first (wireframe accepted before review-UI + coding; requirements rows before the code that implements them; Call 2 refinement after + the human-pick flow feeds it real data). +- **Stop condition** — when the task is done (e.g. "wireframe accepted by Ty," "gates + green + raw evidence recorded," "real `SLAB-UAT-*` draft matches the ready set"). +- **Evidence boundary** — what is prepared vs observed; no task claims done without the + raw runner / capture / store evidence named above. diff --git a/.planning/milestones/v0.5/M4/tasks.md b/.planning/milestones/v0.5/M4/tasks.md new file mode 100644 index 0000000..059cda6 --- /dev/null +++ b/.planning/milestones/v0.5/M4/tasks.md @@ -0,0 +1,188 @@ +# M4 Task Breakdown + +Companion to `goals.md` (accepted direction). Detail bar per task: goal, skills, +starting point, verification, sequence, stop condition, evidence boundary. + +Phase order: P0 (requirements first) → P1 (G1 polish + #99, parallel-safe) → P2 (G2 +review-UI, wireframe-gated) → P3 (G3 Call 2) → P4 (G4 exit walk). Ty owns every gate +exit (QUALITY-30); agents record raw evidence, never declare green. + +--- + +## P0 — Requirements baseline (must land before code it enables) + +### T1. Requirements delta for M4 +- **Goal:** G2/G4 (unblocks G3). **IDs:** REQS (whole doc), REQS-30. **Issues:** —. +- **Skills:** `document-to-action-items` (extract obligations), `ocr-and-documents` + (read current REQUIREMENTS.md), OMH `omh-routing` (evidence boundaries). +- **Starting point:** `docs/REQUIREMENTS.md` (current), `goals.md` requirements-delta + section. +- **Work:** add rows for the human-pick flow (REVIEW-*, CAPTURE-*, METADATA-*), the + Call 2 taxonomy-input row, and the `SLAB-UAT-*` exit-walk row; note the Call 1 + deferral (METADATA-40/45/55) and drop #96; keep the "draft only" PUBLISH-40 invariant; + confirm #99 is tracked. Every new/changed row is the gate for the code that implements it. +- **Verification:** `python tools/check_requirements.py` exit 0; coverage matrix + consistent. +- **Sequence:** first task of the sprint. +- **Stop:** rows merged + gate green. **Evidence:** runner output. + +### T2. #99 tape-line calibration (folded into G1) +- **Goal:** G1. **IDs:** CAPTURE (dimensions), REQS-50. **Issues:** #99. +- **Skills:** `systematic-debugging` (verify the prototype assumption), + `wireframe-review-iteration` (reference the overlay interaction), `svelte-core-bestpractices`. +- **Starting point:** `frontend/src/capture/TapePrototype.svelte` + `?tape-prototype` + sandbox on the `m4` branch; `docs/design/issue-99-tape-line-overlay.html` (approved + wireframe); `frontend/src/png/crop.ts` (projection logic). +- **Work:** promote the prototype to the shipped calibration path (owner drags both + ticks), adopt the as-built length model (maskSpanAlong projection), delete the + sandbox + query-param gating, keep `crop_fill` (already landed in 818874e). + **Scope (Ty confirmed):** confined to the calibration step — the photos-ready + lineup (CAPTURE-130) stays as-is; #99 does not touch it. +- **Verification:** unit tests in `frontend/src/png/*` (tape geometry), `tsc --noEmit`, + manual calibration on one slab at 375px. +- **Sequence:** parallel with T3–T5; no dependency on T1. +- **Stop:** prototype shipped, `?tape-prototype` removed, tests green. + **Evidence:** test output + a 375px capture of the calibration drag. + +--- + +## P1 — M3 polish (G1), parallel-safe once T1 lands + +### T3. Polish wave (full set #91–#100) +- **Goal:** G1. **IDs:** UX (various). **Issues:** all of #91–#100 — #91 (photo-picker + look/feel), #92 (photo filenames on submit), #93 (capture gated on tested Woo + connection), #94 (review layout), #97 (settings), #98 (publish), #100 (UX general). + **Excluded:** #96 (drops with Call 1). Ty confirmed: full polish wave, no triage. +- **Skills:** `svelte-core-bestpractices`, `omh-frontend` (component states), + `omh-visual-qa` (rendered evidence per screen). +- **Starting point:** the live screens named in each issue; `frontend/src/create/*`. +- **Work:** per-issue fixes. Each is a small, individually-verifiable unit; sequence + by dependency (e.g. #93 gate before #98 publish flow touches it). +- **Verification:** per-issue acceptance (capture at 375/768/1280, or the named + behavior), full suite green. +- **Sequence:** after T1; independent of T2. +- **Stop:** each issue's acceptance captured. **Evidence:** captures + test run. + +--- + +## P2 — Human-driven taxonomy review + thumb-first UI (G2) + +### T4. Wireframe (design gate) +- **Goal:** G2. **IDs:** REVIEW-*, UX (phone). **Issues:** #100 (UX). +- **Skills:** `sketch` (variants) + `wireframe-review-iteration` (paradigms, serve on + LAN IP, iterate on Ty's feedback) → `omh-frontend` + `omh-design-quality-gate` + (lock the chosen variant). +- **Starting point:** `docs/design/issue-99-tape-line-overlay.html` (approved overlay + wireframe, 2026-09-24) for the visual language + the interaction model. +- **Work:** 2–3 HTML variants of the thumb-first review flow. Standing paradigms: + *no tap-bubble chip clouds for long lists → collapsible searchable checklist*; + leftmost-kept-is-primary for wood (primary + optional secondaries); AI-assist + labeled as "suggested, confirm"; every metadata requirement present (primary + wood-category required, secondaries optional). +- **Verification:** Ty reviews the served variants and accepts one (375/768/1280). +- **Sequence:** before T5/T6. **Stop:** Ty accepts a variant. + **Evidence:** the accepted `docs/design/*` file + Ty's acceptance. + +### T5. Review-UI implementation +- **Goal:** G2. **IDs:** REVIEW-*, CAPTURE-*. **Issues:** #100. +- **Skills:** `svelte-core-bestpractices`, `svelte-code-writer` (Svelte 5 lookups), + `omh-frontend`, `omh-visual-qa`, `omh-accessibility-audit` (keyboard, 44px targets, + contrast, 320px reflow). +- **Starting point:** accepted T4 wireframe; `frontend/src/create/review/Review.svelte` + (current single-column form); the M3 `MultiSelect.svelte` pattern (reused, not the + tap-bubble pattern). +- **Work:** replace the review form with the accepted thumb-first flow; primary + wood-category + optional secondaries; remove the "Suggest with AI" bar (#96 drops + with Call 1); keep all metadata requirements present and editable. +- **Verification:** `tsc --noEmit`; `omh-visual-qa` at 375/768/1280 (PASS); + `omh-accessibility-audit` (keyboard-reachable, 44px, contrast, 320px reflow); + full suite green with inference on **and** off (QUALITY-20). +- **Sequence:** after T4 accepted. **Stop:** flow renders, all requirements present, + audits pass. **Evidence:** captures + audit output. + +### T6. Taxonomy → title/shortdesc (server-side) +- **Goal:** G2. **IDs:** METADATA-*. **Issues:** —. +- **Skills:** `systematic-debugging` (verify the title/shortdesc builders), + `evidence-based-code-review`. +- **Starting point:** the title/short description builders in `backend/` (review.py / + publish.py path); the new human-pick fields from T5. +- **Work:** ensure title + short description are built from the human-picked primary + wood + form (not from the removed Call 1). Confirm the server_description + (inference-off) path stays intact. +- **Verification:** unit tests for title/shortdesc from human picks; inference-off + path covered. **Sequence:** with/after T5. **Stop:** tests green. + **Evidence:** test output. + +--- + +## P3 — Refine Call 2 long description (G3) + +### T7. Wire human-picked taxonomy into the Call 2 prompt +- **Goal:** G3. **IDs:** METADATA-*. **Issues:** —. +- **Skills:** `systematic-debugging`, `evidence-based-code-review`, + `local-llm-benchmarking` (endpoint behavior), `omh-ask` (prompt-engineering consult + if the owner wants an external pass). +- **Starting point:** `backend/inference.py` `call2` (line 467) — the prompt today is + the **dimension fact block + brand voice + geo only; taxonomy is NOT in the prompt**. + `CALL2_SEED` (line 112), `_active_prompt`, `brand_voice`/`geo_context` settings. +- **Work:** add the human-picked primary/secondary wood + form to the Call 2 fact + block so the long description is grounded in what the owner picked; keep the + "invent no numbers" constraint; keep the dimension block exact. +- **Verification:** `test_inference.py` updated for the new input; a recorded call2 + with a known taxonomy set shows the wood/form in the output. **Sequence:** after T5 + (needs the human-pick data shape). **Stop:** test passes + sample output grounded. + **Evidence:** test output + a sample Call 2 response. + +### T8. Exit-walk quality gate +- **Goal:** G3. **IDs:** QUALITY-105/110. **Issues:** —. +- **Skills:** `omh-verification-gate` (record the gate), `omh-visual-qa`. +- **Starting point:** `deploy/uat_walk.sh`; the refined Call 2 from T7. +- **Work:** Ty reads the Call 2 long description on the exit walk for 2–3 real slabs; + pass = "sounds like a good product description." This is the only proof that counts + for the Call 2 quality claim. +- **Verification:** Ty's judgment on 2–3 outputs, recorded. **Sequence:** after T7. + **Stop:** Ty passes the gate. **Evidence:** Ty's recorded judgment. + +--- + +## P4 — Exit: real Woo draft (G4) + +### T9. `SLAB-UAT-*` draft submission + walk +- **Goal:** G4. **IDs:** PUBLISH-*, QUALITY-105/110. **Issues:** —. +- **Skills:** `omh-deploy-and-monitor` (release checklist + monitor), + `omh-verification-gate`, `docker-uat-deploy` (if the UAT host needs staging). +- **Starting point:** `backend/publish.py` (draft create path), the Woo mock + (`test_integration_woo_mock.py`) for the PUBLISH-5 sequence, `deploy/uat_walk.sh`. +- **Work:** run the full create → review (human pick) → Call 2 → publish path on the + real store, producing **one** `SLAB-UAT-*` draft; walk it (draft only, PUBLISH-40); + confirm the draft matches the ready set. **Shape (Ty confirmed):** single slab, and + the draft carries **multiple photos** of that slab — not a QUALITY-110 pair. +- **Verification:** `deploy/uat_walk.sh` on the real store; draft present in Woo with + the correct fields — including **multiple photos** on the single `SLAB-UAT-*` draft; + full suite green inference on **and** off (QUALITY-20). +- **Sequence:** last; after T3–T8. **Stop:** real draft matches the ready set + Ty + passes the walk. **Evidence:** store screenshot + walk transcript + suite output. + +--- + +## Dependency map + +``` +T1 ──┬─ T3 (polish) + ├─ T4 ─ T5 ─┬─ T6 + │ └─ T7 ─ T8 ─ T9 + └─ T2 (tape-line, parallel) +T9 is the milestone exit. +``` + +- T2 is independent of T1 (prototype already on `m4`). +- T4 must be accepted before T5. +- T7 needs T5's data shape; T8/T9 need T7. +- Nothing in P2/P3 blocks T2/T3 (polish + tape-line ship independently). + +## Resolved at kickoff (deep-interview, 2026-09-24) +- **Polish scope:** full wave — all of #91–#100, no triage (only #96 drops with Call 1). +- **Tape-line scope:** confined to the calibration step; photos-ready lineup + (CAPTURE-130) untouched. +- **Exit-walk shape:** single slab; the `SLAB-UAT-*` draft carries multiple photos of + that slab (not a QUALITY-110 pair).