From 3ac5e36dc3c73148d81640d7d94252db8c1dfef8 Mon Sep 17 00:00:00 2001 From: grokbot_ty Date: Tue, 1 Sep 2026 05:28:03 +0000 Subject: [PATCH] docs: factual CONTENT-WOO/DATA-MODEL fixes + hybrid Phases 3-5 CONTENT-WOO: PNG media, fig-*/feat-* tags, five locked attributes, AGENTS-cited Woo safety. DATA-MODEL/OPENAPI drop server sheet prefs and PWA wording. ARCHITECTURE status reflects locked hybrid topology. IMPL Phases 3-5 rewritten for hybrid (all-photos@1024, confidence 0.7, no offline-era paths). --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 9 ++-- docs/CONTENT-WOO.md | 44 +++++++++-------- docs/DATA-MODEL.md | 14 ++++-- docs/IMPL-PLAN.md | 112 ++++++++++++++++++++++--------------------- docs/OPENAPI.md | 5 +- 6 files changed, 100 insertions(+), 86 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 05c7e5c..3d33fb6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,7 @@ When docs disagree, use this order until stale docs are rewritten: 2. **`docs/ARCHITECTURE.md`** — hybrid topology, what-runs-where, secrets, status machine 3. This **`AGENTS.md`** — hard rules for agents 4. **`docs/DATA-MODEL.md`**, **`docs/OPENAPI.md`**, **`docs/CONTENT-WOO.md`**, **`docs/PROMPTS.md`**, **`docs/DEPLOYMENT.md`** -5. **`docs/IMPL-PLAN.md`** — Phase 0 and rewritten Gate C / Phase 1–2 / Phase 6 sections are authoritative. Implement only Phase 0 plus sections marked rewritten. Do not implement deferred stubs (offline PWA, OCR, ruler) or any leftover server happy-path pipeline language. +5. **`docs/IMPL-PLAN.md`** — Hybrid-aligned Phases 0–6 are authoritative. Phase 2 is a deferred stub only (offline PWA / OCR / ruler). Do not implement deferred stubs or any server happy-path measure/crop as SoT. 6. **PRD / README** — product intent only; do **not** implement lines that contradict TECH-SPEC, ARCHITECTURE, or this file Known stale / do-not-implement without rewrite: diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index e9e04d9..cdd4582 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,9 +1,12 @@ # Architecture -Status: SPEC · 2026-08-27 · SlabUploader -Locked so far: topology C (hybrid), swimlane, what-runs-where. Remaining sections TBD. +Status: SPEC · hybrid topology locked at Gate A freeze (2026-08-31) · SlabUploader -Companion: PRD (root), TECH-SPEC-PIPELINE.md. +Normative for hybrid split, swimlane, what-runs-where, secrets **why**, and status +transitions. Ops depth lives in DEPLOYMENT. Schema enums live in DATA-MODEL. +Agent-facing hard rules live in AGENTS.md (verbatim locks stay there). + +Companion: TECH-SPEC-PIPELINE.md. PRD is historical intent only (see AGENTS precedence). ## 1. Topology (hybrid) diff --git a/docs/CONTENT-WOO.md b/docs/CONTENT-WOO.md index 086798c..593722a 100644 --- a/docs/CONTENT-WOO.md +++ b/docs/CONTENT-WOO.md @@ -75,15 +75,17 @@ Rebuilds the cache table (delete + insert, single transaction). Returns counts. Failure → `502 woo_error`; previous cache retained (never delete-then-fail). ### 2.3 Auto-assign taxonomy (FR26) -- **Category**: species value is matched to a Woo category by name (case-insensitive, - trimmed). Match → that category id. No match → the slab's `category_override` - (user picks in review) or empty (Woo required-field validation will surface it). -- **Tags**: `[character]` plus optional `[species]` if present as a tag. - Call 1 feat-* observations are mapped to Woo feat-* tags (e.g., Crack/Check, - Resin Ready). WooCommerce is authoritative for tag definitions. -- **Attributes**: species/character/length/thickness as product attributes if the - corresponding Woo attributes exist in the cache (by name). Missing attributes are - skipped, not created (v1: no attribute creation). +- **Categories**: species leaf category (1 required) plus wood-category leaf ids (1+). + Match by name against the synced Woo category cache (case-insensitive, trimmed). + No match → user override in review, or empty (Woo required-field validation surfaces it). +- **Tags**: `fig-*` only for figure tags (1+ required) and `feat-*` only for feature tags + (0+). Call 1 free-text observations (character / inclusions / voids / checks) map to + existing Woo `feat-*` tags. Do not invent generic character or species product tags. + WooCommerce is authoritative for tag definitions. +- **Attributes**: the five locked Woo attributes only — Edge Type, Figure, Grade, + Thickness, Moisture — using term ids from the cache. Do not publish species, character, + length, or free-text thickness as product attributes. Missing attributes are skipped, + not created (v1: no attribute creation). - Every assignment is overridable in the review screen (FR26). ### 2.4 Product create payload (FR27) @@ -98,7 +100,7 @@ Failure → `502 woo_error`; previous cache retained (never delete-then-fail). "description": "{description}", "short_description": "{short_title}", "categories": [ { "id": } ], - "tags": [ { "id": }, … ], + "tags": [ { "id": }, { "id": }, … ], "images": [ { "src": "", "alt": "{species} {character} slab" } ], @@ -110,15 +112,17 @@ Failure → `502 woo_error`; previous cache retained (never delete-then-fail). ``` **Image upload strategy** (Woo v3): `images[].src` accepts a URL or a data URL. For reliability the server: -1. For each customer-facing (inventory, normalized) photo in `seq` order: - `POST /media` with the JPEG bytes → get attachment `source_url`. -2. Reference those `source_url` values in `images` (≤5, per PRD 1–5 inventory photos). -3. Calibration photos are excluded (FR2). +1. For each customer-facing inventory photo in `seq` order (processed transparent PNGs + from the client TECH-SPEC path): `POST /media` with the **PNG bytes** → get attachment + `source_url`. Woo accepts `image/*`; keep alpha. Do not re-encode to JPEG and drop alpha. +2. Reference those `source_url` values in `images` (≤5 inventory photos). +3. Only `kind=inventory` photos. Calibration photos do not exist in this design. **Status** comes from Settings key **`woo_create_status`** (`draft` | `publish`, default -**`draft`**). UAT on PROD uses Woo **draft** plus SKU prefix `SLAB-UAT-*` (hard rule: -`SLAB-UAT-*` always creates as Woo draft even if Settings say publish). Flip to -`publish` only for intentional live inventory after Ty review. Do not conflate with +**`draft`**). Woo **safety policy** (UAT draft default, `SLAB-UAT-*` force draft even when +Settings say publish, no edit-same-SKU, purge originals + processed images after successful +publish) is owned by **AGENTS.md §5**. This file owns payload shape and publish sequence +only. Do not diverge from AGENTS on force-draft. Do not conflate Woo create status with slab lifecycle status `published` (means Woo create succeeded locally). ### 2.5 Dedupe & idempotency (FR24a) @@ -142,9 +146,9 @@ Before create: `GET /products?sku={sku}`. 2. dedupe by SKU (GET /products?sku=) → 409 duplicate_sku if exists 3. (re)sync taxonomy if cache older than 1h → best-effort; use existing cache on fail 4. resolve category/tags/attributes (auto-assign + overrides) -5. upload normalized inventory images → media → source_urls -6. POST /products (status=woo_create_status) → woo_product_id -7. write sync_log(success), set slab published, purge images +5. upload processed PNG inventory images → media → source_urls +6. POST /products (status per AGENTS §5 + woo_create_status) → woo_product_id +7. write sync_log(success), set slab published, purge originals + processed images on any failure at 2–6: write sync_log(failed), slab=failed, (images retained for retry) ``` diff --git a/docs/DATA-MODEL.md b/docs/DATA-MODEL.md index cfd961c..c71e2ab 100644 --- a/docs/DATA-MODEL.md +++ b/docs/DATA-MODEL.md @@ -4,7 +4,7 @@ Status: SPEC · 2026-08-27 · SlabUploader Storage: single SQLite file. Schema portable to Postgres. Conventions: -- IDs: client-generated UUIDv4 for slabs so the PWA can reference a slab before it exists server-side. +- IDs: client-generated UUIDv4 for slabs so the SvelteKit client can reference a slab before it exists server-side. - Timestamps: UTC ISO-8601 TEXT. - Soft state via status column; no hard deletes for slabs (audit). - Money: float64 USD, rounded half-up to cents at write. @@ -174,20 +174,26 @@ authoritative source for tag definitions; this table caches synced Woo tags. | `value_enc` | BLOB | AES-GCM ciphertext | | `updated_at` | TEXT | | -Keys: +Keys (server settings; secrets encrypted at rest): - `woo_base_url`, `woo_consumer_key`, `woo_consumer_secret` - `inference_base_url`, `inference_api_key`, `inference_model` - `inference_enabled`, `content_llm_enabled` - `brand_voice`, `geo_context` -- `woo_create_status` ('draft' | 'publish'), default `draft` — Woo product create status; not slab lifecycle +- `woo_create_status` ('draft' | 'publish'), default `draft` — Woo product create status key only; safety policy lives in AGENTS.md §5 - `aspect_ratio` ('3:4'), `output_px` (1600), `output_px_min` (1600), `fill_target` (0.80) -- `user_sensitivity`, `user_edge_offset`, `user_feather`, `user_sheet_mode` + +Sheet/slider prefs (`sheet_mode`, sensitivity, edge offset, feather) are **not** server +settings keys in POC. Client localStorage is source of truth (AGENTS §4 / ARCHITECTURE §5). +Optional server sync of those prefs is out of scope for POC. **Prompt files** — not in the settings table. Stored as text files in `/data/prompts/` (server volume). Read fresh on each invocation. Default prompts shipped with the app; owner edits directly. A reset-to-default script restores originals. +This table is the ciphertext **key inventory** and schema only. The never-browser / +AES-GCM / `SLAB_AES_KEY` env policy lives in AGENTS.md §4; flow lives in ARCHITECTURE §5. + AES master key is an env var (`SLAB_AES_KEY`, 32 bytes base64). Never in the DB. Each `value_enc` = `nonce(12) || ciphertext`. diff --git a/docs/IMPL-PLAN.md b/docs/IMPL-PLAN.md index 5ae92a6..cf4da36 100644 --- a/docs/IMPL-PLAN.md +++ b/docs/IMPL-PLAN.md @@ -1,11 +1,9 @@ # Implementation Plan -Status: SPEC · Gate A freeze 2026-08-31 · hybrid rewrite pass 2026-09-01 · SlabUploader +Status: SPEC · Gate A freeze 2026-08-31 · hybrid rewrite complete 2026-09-01 · SlabUploader -Phase 0 and the Gate C / Phase 1–2 / Phase 6 sections below are authoritative for hybrid -topology. Phases 3–5 still need a full hybrid rewrite in a later docs commit; until then -implement only Phase 0 plus sections marked rewritten here. Do not implement deferred -stubs (offline PWA, OCR, ruler) or any server happy-path measure/crop as SoT. +Phases 0–6 below are hybrid-aligned. Phase 2 remains a deferred stub only. Do not +implement offline PWA, OCR, ruler, or any server happy-path measure/crop as SoT. The build plan a professional (or a fresh Hermes session) executes against. Each phase has: goal, deliverables, acceptance criteria (testable), and exit gate. Ordering is by @@ -149,50 +147,57 @@ No airplane-mode acceptance. No OCR or ruler exit gate in POC. --- -## Phase 3 — Frontend: enrich, review, publish UI +## Phase 3 — Frontend: enrich, review, publish UI (rewritten) -> **Partial hybrid rewrite pending (docs commit 3).** Goal and intent below stay valid. -> Do not reintroduce offline capture, server measure/crop, or a `processing` status. -> Prefer AGENTS + ARCHITECTURE + OPENAPI over any leftover offline-era wording. - -Goal: the enriched review screen and publish action, wired to Phase 1 API. +Goal: online review + publish UI on top of Gate C calibrated drafts. Hybrid only. +Client already owns mask/numbers/PNGs. This phase does not re-measure on the server. Deliverables: -- Review screen: all fields editable (dimensions, species/character with confidence - + manual override, price with recommendation, content with "Generate text" when - inference is on, client-processed PNGs). -- Species/character inference UI (calls server; shows confidence; manual confirm below - threshold). Call 1 uses all inventory photos @1024 when inference is enabled. -- Publish button (online-only), status polling, success/failure states, error detail. -- Settings UI: Woo creds + test, inference endpoint + test (vision check), - pricing rules editor, brand voice/GEO. Prompts are server files, not UI settings. +- Review screen after calibrated upload: all fields editable (length, thickness, SKU, + widths/sqft/bdft shown as client-computed with manual override paths, species and + wood categories, five attributes, fig-*/feat-* tags, price with species $/bdft + recommendation, title/short/description). +- Show client-processed transparent PNGs (and originals while retained). No server + re-crop UI as SoT. +- Inference UI (only meaningful after Gate C and when `inference_enabled`): Call 1 + results with confidence; manual confirm required below threshold **0.7** + (configurable). "Generate text" triggers Call 2; never auto. +- Publish button (online-only), poll `publishing` → `published` | `failed`, surface + error detail from sync_log. +- Settings UI: Woo creds + test, inference endpoint + test (vision check), pricing + rules editor, brand voice/GEO, `woo_create_status`. Sheet/slider prefs stay in + client localStorage. Prompts are server files, not UI settings. +- Secrets never appear in GET settings responses (masked `*_configured` only). Acceptance: -- Full round-trip in browser: capture → upload → review → edit → publish → local - `published` (against a Woo sandbox/mock in tests; against real store in Phase 6). -- Inference disabled → review screen fully functional with manual species/character. -- Every field is editable and the override persists (asserted in a test). +- Browser round-trip: online capture → mask/axis confirm → calibrated upload → + review → edit → publish → local `published` (Woo mock in tests; real store Phase 6). +- Inference OFF → full manual taxonomy + content path works; no inference network calls. +- Field overrides persist across poll/refresh (asserted). +- No offline/IndexedDB requirement. No OCR/ruler UI. -Exit gate: Ty publishes a test slab to the real store as a **Woo draft** (`SLAB-UAT-*`) product. +Exit gate: Ty publishes a test slab to the real store as a **Woo draft** (`SLAB-UAT-*`). (Gate A lock: not pending/published for UAT.) --- -## Phase 4 — WooCommerce integration (real) +## Phase 4 — WooCommerce integration (rewritten) -> **Partial hybrid rewrite pending (docs commit 3).** Payload and safety locks already -> match AGENTS. Keep `woo_create_status` + `SLAB-UAT-*` force-draft. No server happy-path -> image pipeline as SoT. - -Goal: production Woo sync, taxonomy, dedupe, logging (FR24–28). +Goal: production Woo sync, taxonomy, dedupe, logging. Browser never calls Woo. +Media bytes are client-processed **PNGs**. Safety policy from AGENTS §5. Deliverables: -- Woo client (httpx, Basic auth, timeouts), taxonomy sync, auto-assign, media upload, - product create via `woo_create_status` (default **draft**; `SLAB-UAT-*` forces draft), - dedupe, sync_log. +- Woo client (httpx, Basic auth, timeouts), taxonomy sync into cache tables, auto-assign + per CONTENT-WOO §2.3 (categories + five attributes + fig-*/feat-* tags only). +- Media upload of processed PNG inventory photos; product create via `woo_create_status` + (default **draft**). If SKU matches `SLAB-UAT-*`, force Woo **draft** even when + Settings say publish. +- Dedupe by SKU before create; `409 duplicate_sku`; no edit-same-SKU path in MVP. +- `sync_log` with payload_hash; on success set local `published`, purge originals + + processed images on server. - `POST /api/admin/taxonomy/sync` against the real store. - Integration tests against a Woo mock (respx) for success + error + duplicate paths. - Partial-failure handling (orphaned media noted, per CONTENT-WOO §2.6). @@ -200,8 +205,8 @@ Deliverables: Acceptance: - Real UAT publish: product appears in store admin as **draft** under `SLAB-UAT-*`, - correct SKU/price/images/category/tags; `woo_product_id` stored; `sync_log` written - with payload_hash. + correct SKU/price/PNG images/category/tags/attributes; `woo_product_id` stored; + `sync_log` written with payload_hash. - Duplicate SKU publish → 409, no second product created. - Woo error (bad creds / 500) → slab `failed` with detail; retry path works. - All Woo integration tests green (mock + one live smoke). @@ -210,33 +215,30 @@ Exit gate: Ty verifies a real **Woo draft** `SLAB-UAT-*` product in the store is --- -## Phase 5 — Inference (vision + optional content) +## Phase 5 — Inference (vision + optional content) (rewritten) -> **Partial hybrid rewrite pending (docs commit 3).** Sequencing lock stands: inference -> OFF until Gate C is green; Call 1/2 still inside POC after Gate C. Call 1 = all photos -> @1024 (not top-down-only). Confidence threshold 0.7 (configurable) lives here. - -Goal: scoped, toggleable inference with guardrails. Starts only after Gate C is green. +Goal: scoped, toggleable inference **after Gate C is green**, still inside POC. +Does not gate publish. Full suite must pass with inference OFF. Deliverables: -- Vision wrapper: species/character (and related taxonomy) from **all inventory photos** - downscaled to 1024 via the configurable OpenAI-compatible endpoint; model constrained - to Woo taxonomy cache; returns confidence (threshold **0.7**, configurable); logs - request/response. -- Content wrapper: Call 2 reads `prompts/call2.txt`; LLM writes prose only, - dimensions injected by deterministic templates. See `docs/PROMPTS.md`. -- `test-inference` endpoint (vision capability check). -- All inference code behind feature flags; suite passes with everything OFF. +- Call 1 (vision) proxy: **all inventory photos** downscaled to 1024 + Woo taxonomy + snapshot + user metadata; OpenAI-compatible endpoint; model constrained to cached + taxonomy; confidence threshold **0.7** (configurable; relocate from older PRD FR22a). + Auto-run on calibrated create only if `inference_enabled`. Not top-down-only. +- Call 2 (text) proxy: never auto. User taps Generate text. LLM prose only; templates + inject deterministic numbers. See `docs/PROMPTS.md`. +- `test-inference` endpoint (vision capability check) before Call 2 is allowed. +- Feature flags; `inference_log` audit rows; prompt files read fresh each call. +- No numeric/dimension invention by the LLM. LoRA deferred. Acceptance: -- With a local vision model configured: species/character suggestion appears with - confidence; low confidence → manual confirm required. -- With inference OFF: full app works, tests green (explicit test asserts no network - calls to the inference endpoint). -- Inference payloads stored for audit (asserted present after a call). -- Call 1 prompt file edits survive server restart (read fresh each invocation). +- Local vision model configured: taxonomy suggestions appear with confidence; below + 0.7 → manual confirm required. +- Inference OFF: app works end-to-end; tests assert zero calls to the inference endpoint. +- Audit payloads present after a call; prompt file edits apply without server restart. +- Gate C path remains green with inference OFF. Exit gate: Ty runs species detection on 3 real slabs; results acceptable or manually corrected (that is the design). diff --git a/docs/OPENAPI.md b/docs/OPENAPI.md index 682c61b..97f251d 100644 --- a/docs/OPENAPI.md +++ b/docs/OPENAPI.md @@ -128,11 +128,10 @@ the call returns. WooCommerce is the authoritative source for `feat-*` definitio "brand_voice": "...", "geo_context": "...", "woo_create_status": "draft", "aspect_ratio": "3:4", "output_px": 1600, "output_px_min": 1600, - "fill_target": 0.80, - "user_sensitivity": 0.5, "user_edge_offset": 0, "user_feather": 1, - "user_sheet_mode": "auto" } + "fill_target": 0.80 } ``` Secrets (keys) are never returned. Only a `*_configured` boolean. +Sheet/slider prefs are client localStorage only in POC (not in SettingsView). ---