From 5a210c47b072e487f1d58d8712cddfff56eb9029 Mon Sep 17 00:00:00 2001 From: Ty Balascio Date: Sat, 19 Sep 2026 12:38:39 -0700 Subject: [PATCH] docs(m3): reconcile the remaining docs with the settled design Docs written before this thread still carried the three-source copy model and the Call 2 fields it implied. - REQUIREMENTS.md REVIEW-10: title and short description are deterministic; the description comes from the model or the server. - CREATE.md: primary category declared before Call 2; deterministic copy; the prompt revision interface; the slug; auth row in out-of-scope. - API.md: infer-content inputs and result are the long description only. - UAT-PRACTICE.md: the walk no longer tells the owner to leave copy for templates. - README.md: the deploy section duplicated docs/DEPLOYMENT.md and deploy/INVENTORY.md; it now points at them. - DEPLOYMENT.md: the prompt seed is stated per METADATA-105. Both gates pass. --- docs/DEPLOYMENT.md | 3 ++- docs/README.md | 12 ++++----- docs/REQUIREMENTS.md | 2 +- docs/UAT-PRACTICE.md | 6 +++-- docs/capabilities/CREATE.md | 49 +++++++++++++++++++------------------ docs/contracts/API.md | 11 ++++++--- 6 files changed, 44 insertions(+), 39 deletions(-) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 2dca83f..65d4994 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -33,7 +33,8 @@ If access is broken, fix it here before touching compose. Do not commit credenti Precondition: the M3 scaffold exists on the branch being deployed — `frontend/Dockerfile`, `backend/Dockerfile`, and `deploy/.env` on the host. `main` currently has `frontend/Dockerfile` only; `backend/` lands with M3 implementation. -Prompts live in SQLite (`docs/contracts/PROMPTS.md`); no prompt files ship with the image. +Prompts live in SQLite with all revisions, seeded from the text in `docs/contracts/PROMPTS.md` §6 on +first run; no prompt files ship with the image (`METADATA-105`). 1. Push the branch to Gitea from the dev box. 2. On the UAT host: diff --git a/docs/README.md b/docs/README.md index 7f99a74..5581e71 100644 --- a/docs/README.md +++ b/docs/README.md @@ -48,14 +48,12 @@ Technical detail for Woo sync, metadata, pricing, and inference is in `docs/capa | `capabilities/CAPTURE.md` | Milestone 1 Capture (shipped). | | `capabilities/PHOTOS.md` | Milestone 2 Photos (shipped). | | `capabilities/CREATE.md` | Milestone 3 Create. Read this before task breakdown or coding. | -| `contracts/CONTENT-WOO.md` | Listing copy templates and Woo payload intent. | +| `contracts/CONTENT-WOO.md` | Listing copy and payload intent; the deterministic title and short-description patterns. | +| `DEPLOYMENT.md` | Ops runbook: hosts, build, smoke checks, rollback. | | `UAT-PRACTICE.md` | Human practice walk for a `SLAB-UAT-*` listing. Defers to `capabilities/CREATE.md` on conflict. | | `archive/` | Historical only. Not M3 scope. | -## Deploy reminders for this branch +## Deployment -- Dev-test env Docker: ubudual5060 `http://192.168.1.202:10881` (LAN) · `http://100.64.0.9:10881` (Tailscale) -- Port block `10880`–`10889` is this project's; never bind `:10880` (Ty Node/SvelteKit) -- Dev-test env binds `0.0.0.0` — reachable from any machine on `192.168.1.0/24` -- Store URL (`WOO_BASE_URL`) lives in compose / host `.env` -- Woo application password and inference URL live in encrypted Settings, not in compose +Hosts, ports, build and rollback steps, and the dev-test port block live in `docs/DEPLOYMENT.md`; +`deploy/INVENTORY.md` is the only source for what runs where. This map does not repeat them. diff --git a/docs/REQUIREMENTS.md b/docs/REQUIREMENTS.md index 5dc141f..c5cb3c4 100644 --- a/docs/REQUIREMENTS.md +++ b/docs/REQUIREMENTS.md @@ -88,7 +88,7 @@ The listing is built in two inference calls, both optional. Call 1 (vision) read | ID | Requirement | Scope | Test | |---|---|---|---| | REVIEW-5 | Submission-ready requires at least two images (clean first pic plus its dimension-overlay copy), SKU, length, thickness, computed widths and sqft and bdft, exactly one species leaf, at least one wood-category leaf, one Edge Type, at least one Figure, exactly one Grade, one Thickness band, one Moisture, and a price. | M3 | — | -| REVIEW-10 | Title, short_description, and description are required on the product and are satisfied by typed, generated, or templated text. | M3 | — | +| REVIEW-10 | Title, short_description, and description are required on the product; title and short_description are assembled deterministically and the description is written by the model or the server. | M3 | — | | REVIEW-15 | In review the owner declares one primary wood category and any secondary ones before Call 2 runs; primary drives the title and primary plus secondary drive the description; the default primary is the first category selected. | M3 | — | | REVIEW-20 | Every empty required field shows an inline nudge as the owner works; the slab cannot reach ready until the full set is filled, and there is no single submit-time gap list. | M3 | — | | REVIEW-25 | The price suggestion is bdft times the species rate from Settings; when no rate exists the price starts empty and the owner must enter one before create; the owner may override and the override sticks. | M3 | — | diff --git a/docs/UAT-PRACTICE.md b/docs/UAT-PRACTICE.md index 6dcee53..21b0878 100644 --- a/docs/UAT-PRACTICE.md +++ b/docs/UAT-PRACTICE.md @@ -128,8 +128,10 @@ hard stop. Switch to a supported browser. 9. **Price.** A recommendation fills from the species $/bdft rule times board feet. You can override it. If there is no rule for the species, the price starts empty. Type it. Publish is still allowed with a manual price. -10. **Title and description.** You can type them, or leave them for templates at publish. - Templates inject the deterministic numbers. Generate text is OFF for this walk. +10. **Title and short description.** These are built for you from the primary wood category's + pattern and the measurements. You can edit either before publish (`REVIEW-10`, `METADATA-80`). +11. **Description.** With Generate text OFF the server produces it (`METADATA-70`). When inference + is on you can trigger Generate text to have the model write it (`METADATA-55`). Every empty required field shows an inline nudge where it sits. The slab cannot reach `ready` until the full set is filled. diff --git a/docs/capabilities/CREATE.md b/docs/capabilities/CREATE.md index 8eddd24..335bd59 100644 --- a/docs/capabilities/CREATE.md +++ b/docs/capabilities/CREATE.md @@ -14,9 +14,9 @@ lives in `docs/contracts/` (`API.md`, `WOO-API.md`, `DATA-MODEL.md`, `PROMPTS.md | REVIEW-25, REVIEW-30, REVIEW-35, REVIEW-40, REVIEW-45, REVIEW-50 | price, read-only math, stale picks, editability, SKU and caps | | METADATA-5, METADATA-10, METADATA-15, METADATA-20, METADATA-25, METADATA-30 | synced taxonomy, cardinality, no term creation | | METADATA-35, METADATA-40, METADATA-45, METADATA-50 | Call 1 inputs, results, confidence gate, precedence | -| METADATA-55, METADATA-60, METADATA-65, METADATA-66 | Call 2, context, dimension safety, logging | +| METADATA-55, METADATA-60, METADATA-65, METADATA-66 | Call 2, inputs, dimension safety, logging | | METADATA-70, METADATA-75, METADATA-80, METADATA-85, METADATA-90, METADATA-95 | deterministic copy, inference-off path, pattern selection, fact block | -| METADATA-100, METADATA-105, METADATA-110, METADATA-115 | feat mapping, prompt storage, Generate text control, failure triage | +| METADATA-100, METADATA-105, METADATA-106, METADATA-107, METADATA-110, METADATA-115 | feat mapping, prompt storage, revision interface, Generate text control, failure triage | | PUBLISH-5, PUBLISH-10, PUBLISH-15, PUBLISH-20 | create sequence, draft rule, duplicate, stale | | PUBLISH-25, PUBLISH-30, PUBLISH-31, PUBLISH-35, PUBLISH-36, PUBLISH-37, PUBLISH-38 | success, failure, partial failure, triage | | PUBLISH-40, PUBLISH-45, PUBLISH-50, PUBLISH-55, PUBLISH-60 | images, lineup, meaning of published, payload, quantity | @@ -34,13 +34,13 @@ required field shows an inline nudge as they work, and the slab cannot reach `re full set is filled (`REVIEW-5`, `REVIEW-20`). Widths, sqft, and bdft are read-only client math (`REVIEW-30`); every other field stays editable until create (`REVIEW-40`). -The owner declares one primary wood category and any secondary ones; the first selected is -primary (`REVIEW-15`). Price is the bdft times the species rate; with no rate it starts empty and -the owner must enter one; an override sticks (`REVIEW-25`). SKU is 3–24 alphanumeric and hyphen -(`REVIEW-45`). Title, short_description, and description are required and satisfy typed, -generated, or templated text (`REVIEW-10`); title and short_description warn past 60 and 160 -characters (`REVIEW-50`). A picked id that vanished shows as no longer valid and is never -silently swapped (`REVIEW-35`). +The owner declares one primary wood category and any secondary ones before Call 2 runs; the first +selected is primary (`REVIEW-15`). Price is the bdft times the species rate; with no rate it starts +empty and the owner must enter one; an override sticks (`REVIEW-25`). SKU is 3–24 alphanumeric and +hyphen (`REVIEW-45`). Title and short_description are assembled deterministically and the +description is written by the model or the server (`REVIEW-10`, `METADATA-80`); title and +short_description warn past 60 and 160 characters (`REVIEW-50`). A picked id that vanished shows as +no longer valid and is never silently swapped (`REVIEW-35`). ## 2. Inference assist @@ -51,19 +51,19 @@ or above the threshold (default 0.7) a field pre-fills and stays editable; below stays empty (`METADATA-45`). Typed values always win (`METADATA-50`). Free-text observations map to synced `feat-*` tags only (`METADATA-100`). -Call 2 is user-triggered only and produces the product description (`METADATA-55`). It receives the -processed photos, the review-confirmed metadata, the primary and secondary wood categories, the -parent-category path, the dimension fact block, and brand/geo context; the model never invents a -dimension (`METADATA-60`, `METADATA-65`, `METADATA-90`). The Generate text control appears only -when content generation is enabled and the endpoint is reachable (`METADATA-110`). All generation -is logged (`METADATA-66`). +Call 2 is user-triggered only and produces the long description (`METADATA-55`); the name and short +description are already assembled from the primary wood category's patterns (`METADATA-80`, +`METADATA-85`). Call 2 receives the processed photos, the review-confirmed metadata, the primary and +secondary wood categories, the parent-category path, the dimension fact block, and brand/geo +context; the model never invents a dimension (`METADATA-60`, `METADATA-65`, `METADATA-90`). The +Generate text control appears only when content generation is enabled and the endpoint is reachable +(`METADATA-110`). All generation is logged (`METADATA-66`). -With inference off, the server produces the long description (`METADATA-70`). The name and short -description are assembled from the primary wood category's patterns (`METADATA-80`, -`METADATA-85`). Prompts live in the database with -all revisions (`METADATA-105`). Inference never blocks create and never auto-publishes -(`METADATA-75`); a runtime failure offers Retry when recoverable or explains when it is not -(`METADATA-115`). +With inference off, the server produces the long description (`METADATA-70`). Prompts live in the +database with all revisions, and the revision used is recorded with each call; the revision +interface is REST only (`METADATA-105`, `METADATA-106`). Inference never blocks create and never +auto-publishes (`METADATA-75`); a runtime failure offers Retry when recoverable or explains when it +is not (`METADATA-115`). ## 3. Settings prerequisite @@ -98,7 +98,8 @@ unrecoverable (`PUBLISH-36`, `PUBLISH-37`, `PUBLISH-38`) and never shows a raw c (`PUBLISH-35`). Partial failure leaves orphaned media with a cleanup note (`PUBLISH-31`). Images upload as processed PNGs in photos-ready order with no cap (`PUBLISH-40`, `PUBLISH-45`). Published means the store create succeeded, not that it is live (`PUBLISH-50`). The payload is per -`docs/contracts/WOO-API.md` (`PUBLISH-55`) and each product is one slab (`PUBLISH-60`). +`docs/contracts/WOO-API.md` (`PUBLISH-55`) and each product is one slab (`PUBLISH-60`). The payload +carries an explicit slug: the sanitized product name plus the lowercased SKU (`PUBLISH-55`). ## 5. Acceptance @@ -116,5 +117,5 @@ means the store create succeeded, not that it is live (`PUBLISH-50`). The payloa ## 6. Out of scope Offline capture and U2Net matting (`CAPTURE-15`, `CAPTURE-165`), backup and restore (`OPS-30`, -`OPS-35`), and cross-browser end-to-end verification (`QUALITY-115`). The V1 instrumentation work -is out of M3. +`OPS-35`), cross-browser end-to-end verification (`QUALITY-115`), and authentication for the prompt +revision interface (`METADATA-107`). The V1 instrumentation work is out of M3. diff --git a/docs/contracts/API.md b/docs/contracts/API.md index 3ac4bfb..aec9d41 100644 --- a/docs/contracts/API.md +++ b/docs/contracts/API.md @@ -137,16 +137,19 @@ taxonomy, and the user metadata. Returns `202`; the client polls. A failure or t runtime failure rule (recoverable offers Retry, unrecoverable explains). ### `POST /api/v1/slabs/{id}/infer-content` -Runs Call 2 on user action only. Fresh request carrying the full Call 1 context; no provider -thread id. Requires `test-inference` `ok`. Returns `202`; the client polls. The model writes prose -only and never touches dimensions. +Runs Call 2 on user action only. Fresh request carrying the processed photos, the review-confirmed +metadata, the primary and secondary wood categories, the parent-category path, the dimension fact +block, and brand/geo context; no provider thread id and no raw Call 1 result. Requires +`test-inference` `ok`. Returns `202`; the client polls. The model writes the long description only +and never touches dimensions. Call 1 result fields: `species_id`, `species_confidence`, `wood_category_ids`, `edge_type_term_id`, `figure_term_ids`, `figure_confidence`, `grade_term_id`, `grade_confidence`, `character`, `inclusions`, `voids`, `checks`. Free-text observations map to synced `feat-*` tags only. -Call 2 result fields: `title`, `short_description`, `description`. +Call 2 result field: `description`. The name and short description are assembled by the server from +the primary wood category's patterns, not returned by the call. ## 7. Publish