docs(phase2): reconcile requirements and migrate capabilities/contracts

Surface-matrix sweep of every source doc; added nine missed behaviors (METADATA-115, REVIEW-50, APP-55/60/65, SETTINGS-45 mode, Generate-text availability, defaults-off). 153 requirements, 0 coverage gaps.

Migrated capabilities to docs/capabilities/ and contracts to docs/contracts/; added WOO-API, API, DATA-MODEL, PROMPTS, UX, TEST-SPEC. Populated MILESTONES; branch-neutral trunk docs; renamed umbrella term to Woo Slab Taxonomy. Archived reconciliation working records under .audit/archive/.
This commit is contained in:
2026-09-18 21:02:06 -07:00
parent a8cc2f7596
commit 01aa4c52c3
53 changed files with 3186 additions and 817 deletions
+8
View File
@@ -0,0 +1,8 @@
# Coverage ledger — cur:CONTENT-WOO
Source `cur:CONTENT-WOO` (`docs/CONTENT-WOO.md`, current branch). Seeded by the
settings/auth/health pilot 2026-09-18.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| cur:CONTENT-WOO | httpx-timeouts | httpx connect 10s, read 60s | dropped | — | connection detail; recorded in docs/contracts in step 3 |
+9
View File
@@ -0,0 +1,9 @@
# Coverage ledger — cur:CREATE
Source `cur:CREATE` (`docs/CREATE.md`, current branch). Seeded by the settings/auth/health
pilot 2026-09-18.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| cur:CREATE | settings-url | WOO_BASE_URL from env, read-only; change means edit .env and recreate | ported | SETTINGS-5 | — |
| cur:CREATE | test-inference-shape | test-inference returns ok, mode, vision_capable, detail | ported | SETTINGS-45 | mode removed by ruling; SETTINGS-45 now returns ok, vision_capable, detail |
+19
View File
@@ -0,0 +1,19 @@
# Coverage ledger — README.md (docs map)
Source `cur:README` (`docs/README.md`, role: index). Walked 2026-09-18. Navigation-heavy;
only the testable statements carry PoR IDs.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| cur:README | high-level-goal | one slab is one unit and one listing; capture flow | dropped | — | intent restatement; listing invariant covered by PUBLISH-60 |
| cur:README | implemented-m1-m2 | M1/M2 shipped, UAT on `:10881` | ported | OPS-40 | — |
| cur:README | no-woo-create-yet | no Woo create, backend stub, inference unwired | dropped | — | historical branch state, not a requirement |
| cur:README | m3-exit-criteria | ready set plus a real `SLAB-UAT-*` draft with inference off | ported | QUALITY-110, REVIEW-5, METADATA-70 | — |
| cur:README | app-password-server-side | WordPress application password, server-side only | ported | SETTINGS-15, SETTINGS-20, APP-25 | — |
| cur:README | sync-taxonomy | sync and use the synced taxonomy | ported | METADATA-5 | — |
| cur:README | pricing-species-rate | price from species `$/bdft` with user override | ported | REVIEW-25, SETTINGS-35 | — |
| cur:README | inference-settings-calls | inference Settings and Call 1 / Call 2 rules | ported | SETTINGS-30, SETTINGS-45, METADATA-35, METADATA-55 | — |
| cur:README | review-ready-create | review to the ready set, then create, force draft | ported | REVIEW-5, PUBLISH-10 | — |
| cur:README | copied-from-main | technical detail copied from `main` | dropped | — | branch-neutral migration, not a requirement |
| cur:README | folder-map | how to read the folder table | dropped | — | navigation |
| cur:README | deploy-reminders | UAT `:10881` not `:10880`; env vs encrypted settings | ported | OPS-40, OPS-10, SETTINGS-5, SETTINGS-20, SETTINGS-30 | — |
+11
View File
@@ -0,0 +1,11 @@
# Coverage ledger — issues
Source `issue:#n` (Gitea `Ty_Tech/SlabUploader` design issues). Seeded by the
settings/auth/health pilot 2026-09-18. The issue Source column distinguishes each issue.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| issue:#5 | app-password | app password, dedicated user, AES-GCM, browser never holds it, sole caller | ported | SETTINGS-15, SETTINGS-20, APP-25 | — |
| issue:#11 | url-compose | WOO_BASE_URL declared in compose, not user-editable | ported | SETTINGS-5 | — |
| issue:#14 | taxonomy-refresh | taxonomy refresh triggers and anchor | ported | SETTINGS-50, SETTINGS-55, SETTINGS-60 | — |
| issue:#6 | instrument-health | health checks and instrumentation | ported | APP-45 | — |
+185
View File
@@ -0,0 +1,185 @@
# Coverage matrix — ARCHITECTURE.md
Source: `docs/ARCHITECTURE.md` at tag `pre-simplification`.
Method: subagent extracted every surface entry; PoR home assigned here.
Dispositions: `ported`, `superseded`, `dropped`, `ui`, `missing`.
## SETTINGS KEYS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| inference_enabled | SETTINGS-30, SETTINGS-90 | ported | default off added |
| Species $/bdft | SETTINGS-35 | ported | — |
| prompts (as settings) | METADATA-105 | superseded | prompts live in the DB, not settings |
| Inference endpoint base URL | SETTINGS-30 | ported | — |
| Inference API key | SETTINGS-30 | ported | — |
| Woo credentials | SETTINGS-15, SETTINGS-20 | ported | — |
| publish status | SETTINGS-65 | ported | — |
| Store URL env, read-only | SETTINGS-5 | ported | — |
| SLAB_AES_KEY | SETTINGS-25 | ported | — |
| WOO_BASE_URL | SETTINGS-5, SETTINGS-10 | ported | — |
| sheet mode | CAPTURE-40, CAPTURE-145 | ported | — |
| sensitivity | CAPTURE-41, CAPTURE-145 | ported | — |
| edge offset | CAPTURE-40 | superseded | removed control |
| feather | CAPTURE-40 | superseded | removed control |
| reset-to-default | CAPTURE-145 | ported | — |
| Species list with $/bdft | SETTINGS-35 | ported | — |
| Taxonomy snapshot | SETTINGS-50 | ported | — |
## CONTROLS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| New Wood 1–5 photos | CAPTURE-25 | superseded | no cap |
| Four mask knobs | CAPTURE-40 | superseded | two knobs |
| Mask edge OK | CAPTURE-50 | ported | — |
| Retune knobs / Retake | CAPTURE-50, CAPTURE-155 | ported | — |
| Length axis rotate/confirm | CAPTURE-60, CAPTURE-65 | ported | — |
| User length/thickness/SKU | CAPTURE-70 | ported | — |
| Call 1 pre-fill / manual taxonomy | METADATA-45, METADATA-50 | ported | — |
| Generate text button | METADATA-55, METADATA-110 | ported | availability added |
| Publish | PUBLISH-5 | ported | — |
| Settings "Refresh taxonomy" control | SETTINGS-60 | ui | optional; not required for POC |
| Inline nudges | REVIEW-20 | ported | — |
## LISTING FIELDS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Photos 1–5 | CAPTURE-25 | superseded | no cap |
| SKU | REVIEW-45 | ported | — |
| length / thickness | CAPTURE-70 | ported | — |
| sqft / bdft / 6in widths | CAPTURE-80, CAPTURE-85, CAPTURE-90 | ported | — |
| 3:4 PNG | CAPTURE-95, CAPTURE-100 | ported | — |
| title / short_title / description | REVIEW-10 | ported | short_title naming migrated |
| species | METADATA-10 | ported | — |
| wood categories | METADATA-10 | ported | — |
| edge / figure | METADATA-15 | ported | — |
| grade | METADATA-15 | ported | cardinality superseded |
| feat-* | METADATA-30 | ported | — |
| fig-* | METADATA-30 | ported | cardinality superseded |
| price | REVIEW-25 | ported | — |
| moisture | METADATA-15 | ported | — |
| originals | PUBLISH-25, PUBLISH-40 | ported | purge after publish |
| woo_product_id | PUBLISH-25 | ported | — |
## STATUSES
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| draft | APP-5 | ported | — |
| calibrated | APP-5 | ported | — |
| ready | APP-5, REVIEW-5 | ported | fig/grade cardinality superseded |
| publishing | APP-5 | ported | — |
| published | APP-5, PUBLISH-25 | ported | — |
| failed | APP-5, PUBLISH-30 | ported | — |
| transitions draft→...→published/failed | APP-5 | ported | — |
## ENDPOINTS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| /wp-json/wc/v3/ | SETTINGS-15 | ported | — |
| /api/v1/settings | SETTINGS-20, SETTINGS-30 | ported | — |
| /api/v1/admin/taxonomy | SETTINGS-50 | ported | — |
| POST /api/v1/settings/test-woo | SETTINGS-40, SETTINGS-80 | ported | — |
| GET /api/v1/validation/module | — | dropped | validation module ruled cut |
| POST /api/v1/settings/test-inference | SETTINGS-45 | ported | — |
## ERROR CODES
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| 409 duplicate SKU only | PUBLISH-15 | ported | — |
| 422 stale value | PUBLISH-20 | ported | — |
| 412 validation hash | — | dropped | validation module ruled cut |
| "Never show 412" | PUBLISH-35 | dropped | moot after cut |
## USER-FACING ERROR / EMPTY STATES
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Call 1 runtime failure → retry or message | METADATA-115 | ported | recoverable retries, unrecoverable explains |
| Below 0.7 fields stay empty | METADATA-45 | ported | — |
| Duplicate SKU field error | PUBLISH-15 | ported | — |
| Stale value field error | PUBLISH-20 | ported | — |
| Review gate empty subset | REVIEW-5, REVIEW-20 | ported | — |
| Inline nudges, not submit-only | REVIEW-20 | ported | — |
| UI "Updating rules" | — | dropped | validation module cut |
| failed error detail stored, retry | PUBLISH-30 | ported | — |
## INFERENCE
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Call 1 auto-run only if inference_enabled | METADATA-35, SETTINGS-90 | ported | — |
| Call 1 skipped when disabled | METADATA-70 | ported | — |
| Call 1 input: all originals downscaled to 1024 | METADATA-35 | superseded | PoR sends the clean processed photos |
| Call 1 input: synced taxonomy only | METADATA-35, METADATA-40 | ported | — |
| Call 1 input: SKU/length/thickness | METADATA-35 | ported | — |
| Call 1 timeout 45s | METADATA-115 | ported | runtime failure triage |
| Threshold ≥0.7 pre-populate | METADATA-45 | ported | — |
| Below 0.7 empty | METADATA-45 | ported | — |
| Manual entry authoritative | METADATA-50 | ported | — |
| Call 2 no auto-fire | METADATA-55 | ported | — |
| Call 2 portable context / full resend | — | superseded | thread work out of MVP |
| previous_response_id | — | superseded | thread work out of MVP |
| Call 2 confirmed vs inferred | METADATA-60 | ported | — |
| per-slab thread, delete on submit/abandon | — | superseded | thread work out of MVP |
| test-inference mode stateful/stateless/fail | SETTINGS-45 | ported | — |
| fail blocks Call 2 only | SETTINGS-45 | ported | — |
| Call 1/2 assist-only, do not gate publish | METADATA-75 | ported | — |
| low-confidence does not auto-fill | METADATA-45 | ported | — |
## PUBLISH PAYLOAD
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Draft upload contents | CAPTURE-135 | ported | — |
| Originals needed for retry | PUBLISH-40 | ported | — |
| Post-publish deletion | PUBLISH-25 | ported | — |
| Duplicate SKU handling | PUBLISH-15 | ported | — |
| Stale value handling | PUBLISH-20 | ported | — |
| Product status per setting | SETTINGS-65, PUBLISH-10 | ported | — |
| Title/desc typed, generated, or templated | REVIEW-10, METADATA-70 | ported | templates are fallback |
| Publish poll | PUBLISH-5 | ported | — |
| woo_product_id stored | PUBLISH-25 | ported | — |
| Images purged | PUBLISH-25 | ported | — |
| Publish resync > 1 hour | SETTINGS-60 | ported | — |
| Submit carries validation_hash / 412 retry | — | dropped | validation module cut |
| Woo-shaped 422 store rejection | APP-50, PUBLISH-20 | ported | — |
| Taxonomy: categories/attributes/fig-* synced | SETTINGS-50, SETTINGS-51 | ported | scope narrowed to fig/feat |
## CONSTANTS / NUMBERS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| 1–5 photos | CAPTURE-25 | superseded | no cap |
| downscale 1024 | METADATA-35 | ported | source conflict noted |
| Call 1 timeout 45s | METADATA-115 | ported | runtime failure triage |
| confidence 0.7 | METADATA-45 | ported | — |
| 3:4 | CAPTURE-100 | ported | — |
| 80% fill | CAPTURE-100 | superseded | 90 percent |
| 6in widths | CAPTURE-80 | ported | — |
| SKU charset 3..24 | REVIEW-45 | ported | case widened |
| taxonomy staleness 1 hour | SETTINGS-60 | ported | — |
| ready cardinalities (PNG/species/wood/edge/figure/fig/grade/moisture/feat) | REVIEW-5 | ported | fig/grade superseded |
| five attributes | METADATA-15 | ported | — |
## BROWSER / API SUPPORT
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Browser does not call Woo or vision | APP-25 | ported | — |
| no CORS to store | APP-25 | ported | — |
| localStorage persistence | CAPTURE-145 | ported | — |
| client BG removal APIs | CAPTURE-140, CAPTURE-35 | ported | — |
| camera | CAPTURE-25, CAPTURE-20 | ported | — |
| no U2Net control (POC) | CAPTURE-165 | ported | — |
| U2Net deferred, not deleted | CAPTURE-165 | ported | — |
| title/desc Woo maxLength | REVIEW-50 | ported | Woo v3 documents no max; caps in `docs/contracts/WOO-API.md` §11 |
## Findings
None open. Runtime inference failure is `METADATA-115`; the Call 1 image source is
`METADATA-35`; title/description length caps are inherent Woo limits.
+158
View File
@@ -0,0 +1,158 @@
# Coverage matrix — CREATE.md (current branch)
Source: `docs/CREATE.md` (current working tree).
Method: every surface entry dispositioned to PoR IDs or a recorded drop.
## Findings
None new. Two open decisions in the doc are already settled elsewhere: the `attributes` element
shape is resolved in `docs/contracts/WOO-API.md` §4, and the crop fill/floor (90% / 800) is the
PoR. The client stack note ("Vite + Svelte SPA") is implementation, not a requirement.
## Superseded (queued in migration TODOs)
- ready set "at least one inventory PNG" → REVIEW-5 (two images)
- grade 1+ → METADATA-15 (exactly one)
- `fig-*` 1+ required → METADATA-30 (optional)
- `short_title` → REVIEW-10 (`short_description`)
- "user typed number wins if overridden" for widths/sqft/bdft → REVIEW-30, REVIEW-40 (read-only)
- "title/short/desc not required to reach ready" → REVIEW-10
- "templates always available" and "server assembles from templates" → METADATA-70, METADATA-80
(model writes when Call 2 runs; template is fallback)
- "Cap at 5 images" / "Cap ≤5" → PUBLISH-40 (no cap)
- Call 1 input "inventory photos downscaled to 1024" → METADATA-35 (clean processed photos)
## SETTINGS KEYS
- `WOO_BASE_URL` env, read-only → SETTINGS-5; HTTPS → SETTINGS-10
- `SLAB_AES_KEY` env → SETTINGS-25
- `woo_wp_username` / `woo_app_password` encrypted → SETTINGS-20
- `woo_create_status` default draft → SETTINGS-65
- `inference_base_url`, `inference_api_key`, `inference_model`, `inference_enabled` → SETTINGS-30
- `content_llm_enabled` → SETTINGS-30, SETTINGS-90
- `taxonomy_last_sync_at`, `taxonomy_anchor` → SETTINGS-55
- `brand_voice`, `geo_context` → SETTINGS-30
## CONTROLS
- store URL read-only → SETTINGS-5
- credential entry → SETTINGS-20
- Generate text disabled when endpoint down → METADATA-110, METADATA-75
- Call 2 blocked when test-inference `fail` → SETTINGS-45
- inline nudges → REVIEW-20
- species picker synced only → METADATA-5, METADATA-10
- attribute pickers synced only → METADATA-15
- stale field / vanished id → PUBLISH-20, REVIEW-35
- duplicate SKU actions → PUBLISH-15
- create/publish trigger → PUBLISH-5
- draft upload trigger → CAPTURE-135
## LISTING FIELDS
- `sku` → REVIEW-45; `status` enum → APP-5
- `length_in`, `thickness_in` 1/8 → CAPTURE-70
- `sqft`, `bdft`, widths → CAPTURE-80, CAPTURE-85, CAPTURE-90
- `species_id` 1 leaf → METADATA-10; `wood_category_ids` 1+ → METADATA-10
- `edge_type_term_id` 1 → METADATA-15; `figure_term_ids` 1+ → METADATA-15
- `thickness_term_id` round-up → METADATA-15; `moisture_term_id` default kiln-dried → METADATA-15
- `feat_tag_ids` 0+ → METADATA-30
- `price`, `price_per_bdft`, `price_source` → REVIEW-25
- templates (title, short, description, `{character}`, `{geo_sentence}`) → contract detail in
`docs/contracts/CONTENT-WOO.md`; fallback only
- species/character/length/free-text thickness not attributes → METADATA-25
## STATUSES
- draft/calibrated/ready/publishing/published/failed → APP-5
- `woo_create_status` draft/publish → SETTINGS-65
- test-inference mode stateful/stateless/fail → SETTINGS-45
- device draft is not a Woo draft → APP-10
## ENDPOINTS
- `/api/health` → APP-30, APP-45
- slabs CRUD, photos, infer-taxon, infer-content, publish, taxonomy, pricing, settings →
`docs/contracts/API.md`
- Woo endpoints (`/wc/v3/products`, categories, tags, attributes, media) →
`docs/contracts/WOO-API.md`
## ERROR CODES
- 502 `woo_error` → SETTINGS-50, PUBLISH-30
- 422 `unpublishable` → REVIEW-5
- 409 `duplicate_sku` → PUBLISH-15
- 202 publish → contract
## USER-FACING ERROR / EMPTY STATES
- sync failure keeps previous cache → SETTINGS-50
- create blocked until ready → REVIEW-5, REVIEW-20
- duplicate SKU block → PUBLISH-15
- stale field, current options → PUBLISH-20
- vanished id not silently swapped → REVIEW-35
- failure: log, mark failed, keep photos, field-level error, no raw code → PUBLISH-30, PUBLISH-35
- low-confidence not shown as defaults → METADATA-45
- Generate text down → METADATA-110
- no pricing rule → price empty, owner types → REVIEW-25
## INFERENCE
- Call 1 auto only when enabled → METADATA-35
- Call 1 input (photos, metadata, taxonomy) → METADATA-35
- Call 1 output + confidence → METADATA-40
- threshold 0.7 pre-fill / below empty → METADATA-45
- moisture never inferred → METADATA-15
- typed wins → METADATA-50
- never blocks create / auto-publish → METADATA-75
- Call 2 user-triggered; requires test-inference ok → METADATA-55, SETTINGS-45
- model prose only, no dimensions → METADATA-65
- templates fallback → METADATA-70
- test-inference shape, fail blocks Call 2 only → SETTINGS-45
- templates math from deterministic pipeline → METADATA-90
- inference-off create → QUALITY-20, METADATA-70
- FastAPI proxies inference → APP-25
## PUBLISH PAYLOAD / FLOW
- payload fields (`name`, `type`, `status`, `sku`, `regular_price`, `description`,
`short_description`, `categories`, `tags`, `images`, `attributes`, `virtual`, `downloadable`,
`catalog_visibility`) → `docs/contracts/WOO-API.md`, PUBLISH-55
- non-null only → PUBLISH-55
- `SLAB-UAT-*` force draft → PUBLISH-10
- images upload keep alpha, lineup order → PUBLISH-40, PUBLISH-45
- published meaning (not live) → PUBLISH-50
- success behavior (product id, purge, delete row, clear device draft) → PUBLISH-25, APP-15
- failure behavior → PUBLISH-30
- create sequence steps 1–4 → PUBLISH-5
- `images alt` text → contract detail
- attributes element shape → resolved, `docs/contracts/WOO-API.md` §4
## CONSTANTS / NUMBERS
- `per_page=100` → SETTINGS-50, WOO-API §7
- connect 10s / read 60s → contract detail
- taxonomy staleness 1 hour → SETTINGS-60
- SKU `[A-Z0-9-]{3,24}` → REVIEW-45
- downscale 1024 → METADATA-35
- confidence 0.7 → METADATA-45
- bdft and price formulas → CAPTURE-90, REVIEW-25
- 1/8 step → CAPTURE-70
- five attributes → METADATA-15
- UAT port `:10881`, do not touch `:10880` → OPS-40
- fill 90% / 800px floor → CAPTURE-100, CAPTURE-105
## BROWSER / API SUPPORT
- FastAPI only Woo caller; browser no creds → APP-25
- app-password Basic auth, not consumer keys → SETTINGS-15
- HTTPS only → SETTINGS-10
- proxy inference, no key in browser → APP-25, SETTINGS-30
- device draft IndexedDB → APP-10, CAPTURE-140
- Woo source of truth, cache ids → METADATA-5
- v1 no term creation → METADATA-20
- taxonomy sync order, transactional, anchor, re-pull, triggers → SETTINGS-50, SETTINGS-55,
SETTINGS-60
- pricing rules flat per species, seed, override sticks, manual allowed → SETTINGS-35, REVIEW-25
- practice rules (`SLAB-UAT-*`, hidden, inference off) → PUBLISH-10, QUALITY-20
- dishonest proxies → QUALITY-105
- tag/leaf filters and feat mapping → SETTINGS-51, METADATA-10, METADATA-30, METADATA-100
+83
View File
@@ -0,0 +1,83 @@
# Coverage matrix — CONTENT-WOO, CAPTURE, PHOTOS (current branch)
Sources: `docs/CONTENT-WOO.md`, `docs/CAPTURE.md`, `docs/PHOTOS.md` (current working tree).
## Findings
None new. Two notes: the copy-template storage location ("templates live in Settings") is
contract detail for `docs/contracts/CONTENT-WOO.md`, and the case-insensitive name-matching rule
is legacy — the review flow selects from pickers, so it is superseded by `METADATA-5`.
## CONTENT-WOO.md
Superseded: `short_title` → REVIEW-10; `fig-*` 1+ required → METADATA-30; "≤5 inventory photos" →
PUBLISH-40; "Only kind=inventory photos / calibration photos do not exist" → calibration exists
(CAPTURE-25, CAPTURE-30); "check against the shared rules (current copy)" → validation module cut
(REVIEW-5); case-insensitive name matching → METADATA-5.
Ported:
- `content_llm_enabled`, `content_source` → SETTINGS-30, METADATA-66
- `geo_sentence` from Settings, default none → SETTINGS-30
- `woo_create_status` default draft → SETTINGS-65
- `WOO_BASE_URL` env HTTPS; `SLAB_AES_KEY` → SETTINGS-5, SETTINGS-10, SETTINGS-25
- templates title/short/description and `{character}` → contract detail
`docs/contracts/CONTENT-WOO.md`
- categories species 1 + wood 1+, tags fig/feat, five attributes → METADATA-10, METADATA-15,
METADATA-30
- ready set → REVIEW-5 (fig/grade cardinality superseded)
- payload fields → `docs/contracts/WOO-API.md`, PUBLISH-55
- `type simple`, `virtual false`, `downloadable false`, `catalog_visibility visible` → PUBLISH-55
- image bytes keep alpha, `POST /media` → PUBLISH-40, WOO-API §5
- `SLAB-UAT-*` force draft → PUBLISH-10
- status `draft`/`publish`, published meaning → SETTINGS-65, PUBLISH-50
- create sequence steps 1–7 → PUBLISH-5
- dedupe every time → PUBLISH-15
- post-create delete originals + processed → PUBLISH-25
- failure: field message, mark failed, keep photos → PUBLISH-30, PUBLISH-35
- partial-failure orphaned media manual cleanup → PUBLISH-31
- taxonomy sync order, `per_page=100`, 1-hour reconcile, anchor → SETTINGS-50, SETTINGS-55,
SETTINGS-60
- vision 0.7 fills; vision off typed; typed wins → METADATA-45, METADATA-50, METADATA-70
- model writes prose only, synced choices only, no invented dimensions → METADATA-40, METADATA-65
- httpx timeouts 10s/60s → contract detail
- wire `{field, code, message, actions[]}`, codes never shown → PUBLISH-35, API contract
## CAPTURE.md
Ported:
- Sheet control, Sensitivity 0–100 → CAPTURE-40, CAPTURE-41
- immediate value update, 2.0 s recompute, last good overlay → CAPTURE-45
- approve blocked with no slab pixels → CAPTURE-50
- length axis rotate/approve → CAPTURE-60
- length/thickness 1/8, Calculate → CAPTURE-70
- scale `longest_axis_px / L` → CAPTURE-75
- widths every 6 in, drop first/last 6, `L ≤ 12` all zero → CAPTURE-80
- `sqft = mask_pixels / scale² / 144`, 2 dp → CAPTURE-85
- `bdft = sqft × thickness_in`, 2 dp → CAPTURE-90
- 3:4, 90% fill, shorter side ≥ 800, no upscale → CAPTURE-100, CAPTURE-105
- PNG 8-bit RGBA, alpha kept → CAPTURE-95
- browsers and hard stop → CAPTURE-10
- client APIs and no OpenCV/ONNX/U2Net → CAPTURE-140
- preview display-only, source pixels → CAPTURE-141
- device draft, Resume/Continue/Start fresh → APP-10
- 1/8 steps → CAPTURE-70; sensitivity maps green/black → CAPTURE-41
Dropped: busy-mark "fraction of a second" (nit, migration TODO); "other backgrounds out of M1"
(scope); M1 single reference photo superseded by batch (CAPTURE-25).
## PHOTOS.md
Ported:
- batch one or more, continue at least one → CAPTURE-25
- pick calibration photo → CAPTURE-25
- M1 states on the calibration photo only → CAPTURE-30
- Photos ready lineup order → CAPTURE-130
- per-photo empty mask / size floor excluded, rest proceed → CAPTURE-110
- single-photo batch works → CAPTURE-25
- crop rules reuse (3:4, 90%, PNG, floor) → CAPTURE-100, CAPTURE-105
- overlay black; stations every 12 in from 6 in, while ≤ L−6; EXIF bottom → CAPTURE-120,
CAPTURE-125
- 1–N photos → CAPTURE-25
- no inference / Woo create on this path → APP-25
No findings.
+39
View File
@@ -0,0 +1,39 @@
# Coverage matrix — Gitea design issues #1–#20
Source: `gitea.vps1.afterthedemo.com/Ty_Tech/SlabUploader` issues #1–#20 (design issues).
Method: every issue dispositioned to PoR IDs or a recorded drop.
## Findings
None open. Issue #6's structured logging, request id, and `LOG_LEVEL` are now `APP-55`.
## Issue map
| Issue | Atom | Disposition | PoR |
|---|---|---|---|
| #1 | portable multi-turn context (closed, superseded by #2) | superseded | thread work out; Call 2 fresh full context METADATA-60 |
| #2 | portable multi-turn context | ported | METADATA-60, SETTINGS-45 |
| #2 | per-slab thread, delete on submit/abandon | superseded | thread work out |
| #2 | confirmed vs inferred labels | ported | METADATA-60 |
| #3 | duplicate SKU means "any status" | ported | PUBLISH-15 |
| #4 | browser compatibility floor + hard stop + load-bearing APIs | ported | CAPTURE-10, CAPTURE-140 |
| #5 | Woo auth via application passwords, server-side, AES-GCM | ported | SETTINGS-15, SETTINGS-20, APP-25 |
| #6 | health checks DB + image-volume writability | ported | APP-45 |
| #6 | sync_log + inference_log written and queryable | ported | PUBLISH-30, METADATA-66 |
| #6 | structured logging, request id phone→FastAPI→Woo, LOG_LEVEL | ported | APP-55 |
| #7 | Prometheus metrics, alerting, log retention (V1) | dropped | out of M3 scope |
| #8 | Call 1 pre-populates review fields when enabled | ported | METADATA-45 |
| #9 | 0.7 threshold prefill; suite passes with inference off | ported | METADATA-45, QUALITY-20 |
| #10 | per-field inline nudges; UX presentation pass | ported | REVIEW-20; docs/contracts/UX.md |
| #11 | WOO_BASE_URL compose-only, read-only, HTTPS, not user-editable | ported | SETTINGS-5, SETTINGS-10, SETTINGS-85 |
| #12 | only synced species selectable | ported | METADATA-5 |
| #13 | store-admin creates a species leaf (V1) | dropped | out of M3 scope |
| #14 | taxonomy anchor, client re-pull, triggers | ported | SETTINGS-50, SETTINGS-55, SETTINGS-60 |
| #15 | BG knobs inline, live re-run, mask on source photo | ported | CAPTURE-45, CAPTURE-150 |
| #15 | four knobs | superseded | CAPTURE-40 |
| #15 | client-only POC; U2Net deferred | ported | CAPTURE-165 |
| #16 | V1 instrumentation | dropped | out of M3 scope |
| #17 | shared validation module, versioned, submit-checked | dropped | validation module cut |
| #18 | 409/422 mapped to field-level recovery, no top banners | ported | PUBLISH-15, PUBLISH-20, PUBLISH-35 |
| #19 | POC acceptance test cases | duplicate | TEST-SPEC owns the test plan |
| #20 | TEST-SPEC review feedback | dropped | process; TEST-SPEC reconciled last |
+152
View File
@@ -0,0 +1,152 @@
# Coverage matrix — OPENAPI.md
Source: `docs/OPENAPI.md` at tag `pre-simplification`.
Method: subagent extracted every surface entry; PoR home assigned here.
Dispositions: `ported`, `superseded`, `dropped` (contract detail), `ui`, `missing`.
## Findings
None. Three items are contract detail (photo 40 MB request cap, `GET /meta`, `inference_error`
field), and the schema conflicts are already resolved in the PoR.
## SETTINGS KEYS
- `woo_base_url` read-only → SETTINGS-5
- `woo_base_url` not writable, reject write → SETTINGS-85
- `woo_wp_username` / `woo_app_password` write-only, AES-GCM → SETTINGS-20
- reject `woo_consumer_key` / `woo_consumer_secret` → SETTINGS-15
- `woo_credentials_configured` boolean → SETTINGS-75
- secrets masked, never echoed → SETTINGS-75
- `inference_base_url`, `inference_model`, `inference_enabled`, `content_llm_enabled`,
`brand_voice`, `geo_context`, `woo_create_status` → SETTINGS-30, SETTINGS-65
- `aspect_ratio` 3:4 → CAPTURE-100
- `output_px` / `output_px_min` 1600, `fill_target` 0.80 → superseded CAPTURE-105
- client prefs not in SettingsView → CAPTURE-145
- PUT partial body, re-encrypt, no echo → SETTINGS-20, SETTINGS-30
- `inference_enabled` default `true` in the example → superseded SETTINGS-90 (default off)
## CONTROLS
- pickers limited to synced taxonomy → METADATA-5
- duplicate SKU actions `edit_sku` / `open_existing` → PUBLISH-15
- stale field actions/options → PUBLISH-20
## LISTING FIELDS (SlabCreate, read model, results)
- `id`, `client_rev` → APP-20
- `sku` 3..24 uppercase → REVIEW-45 (case widened; Woo hard cap in WOO-API §9)
- `length_in`, `thickness_in` 1/8 → CAPTURE-70
- `sqft`, `bdft`, widths → CAPTURE-80, CAPTURE-85, CAPTURE-90
- `species_id`, `wood_category_ids` → METADATA-10
- `edge_type_term_id`, `figure_term_ids`, `thickness_term_id`, `moisture_term_id` → METADATA-15
- `grade_term_ids` (plural, 1+) → superseded METADATA-15 (exactly one, singular)
- `fig_tag_ids` (1+) → superseded METADATA-30 (optional)
- `feat_tag_ids` (0+) → METADATA-30
- `price`, `price_source` → REVIEW-25
- `price_per_bdft` on slab → contract detail (pricing rules SETTINGS-35)
- `title`, `description` → REVIEW-10
- `short_title` → superseded REVIEW-10 (`short_description` canonical)
- `content_source` → METADATA-66
- read model `status`, `inference_status`, `woo_product_id`, `published_at`, revisions → APP-5,
METADATA-35, PUBLISH-25, APP-20
- `inference_error` → contract detail
- PhotoRead `kind` label → dropped (label discarded); urls → contract; 410 → PUBLISH-25
- Call1 result ids/confidences → METADATA-40; free-text → METADATA-100
- Call2 result → METADATA-55/60
- PriceRule shape → SETTINGS-35
## STATUSES
- `calibrated` on create → APP-5, CAPTURE-135
- `ready` preconditions → REVIEW-5 (fig/grade cardinality superseded)
- `publishing` / `failed` / `published` → APP-5, PUBLISH-25, PUBLISH-30
- `inference_status` enum → METADATA-35
- duplicate check across any Woo status → PUBLISH-15
## ENDPOINTS
- `GET /api/health` body → APP-45
- `GET /api/v1/meta` → contract detail
- `POST/GET/PUT/DELETE /api/v1/slabs` → docs/contracts/API.md
- `POST .../u2net/{pid}` reserved → CAPTURE-165
- `GET .../photos/...` → PUBLISH-25
- `POST .../infer-taxon` → METADATA-35
- `POST .../infer-content` → METADATA-55
- `POST .../publish` → PUBLISH-5
- taxonomy GET/sync → SETTINGS-50, SETTINGS-55, SETTINGS-60
- pricing CRUD → SETTINGS-35
- settings GET/PUT, test-woo, test-inference → SETTINGS-20, SETTINGS-30, SETTINGS-40, SETTINGS-45,
SETTINGS-75, SETTINGS-85
- `GET /api/v1/validation/module` → dropped (module cut)
## ERROR CODES
- 400, 404, 500 → APP-35
- 409 `revision_conflict` → APP-20
- 409 `duplicate_sku` → PUBLISH-15
- 422 `unpublishable` → REVIEW-5, REVIEW-20
- 422 `stale_field` → PUBLISH-20
- 422 test-inference gate → SETTINGS-45
- 422 `woo_base_url` write → SETTINGS-85
- 502 `woo_error` → PUBLISH-30, SETTINGS-50
- 504 timeout → METADATA-115
- 410 photos → PUBLISH-25
- 412 validation module → dropped (module cut)
## USER-FACING ERROR / EMPTY STATES
- never show the code, no raw code → PUBLISH-35
- unpublishable UI mapping → REVIEW-20
- test-woo fails closed → SETTINGS-80
- test-inference `fail` blocks Call 2 only → SETTINGS-45, METADATA-75
- low-confidence no prefill → METADATA-45
- Woo failure surfaces as failed + log → PUBLISH-30
- taxonomy sync failure keeps previous cache → SETTINGS-50
## INFERENCE
- Call 1 auto only if enabled → METADATA-35
- Call 1 inputs "original photos downscaled to 1024" → superseded METADATA-35 (clean processed
photos)
- Call 1 timeout 45s → METADATA-115
- confidence persist ≥0.7 → METADATA-45
- free-text → feat-* mapping → METADATA-100
- Call 2 default resend full context → METADATA-60 (no thread)
- `previous_response_id`, per-slab thread → superseded (thread work out)
- Call 2 requires test-inference ok → SETTINGS-45
- validation module shared with Call 2 → dropped (module cut)
## PUBLISH PAYLOAD / FLOW
- preconditions → REVIEW-5
- dedupe → PUBLISH-15
- stale → PUBLISH-20
- success (product id, purge, delete row) → PUBLISH-25
- failure (failed, sync_log, poll 502) → PUBLISH-30
- create-time Woo status → SETTINGS-65, PUBLISH-10
## CONSTANTS / NUMBERS
- base path `/api/v1`, version bump → APP-30
- timestamps UTC ISO-8601 → APP-20
- photo request cap 40 MB → contract detail
- SKU pattern `[A-Z0-9-]{3,24}` → REVIEW-45
- 1/8 step → CAPTURE-70
- price 2 decimals → REVIEW-25
- poll backoff 1/2/4/10s → contract detail
- 1024 downscale → METADATA-35
- 0.7 threshold → METADATA-45
- 45s timeout → METADATA-115
- 3:4 → CAPTURE-100
- 1600 / 0.80 → superseded CAPTURE-105
- publish cardinalities → REVIEW-5
## BROWSER / API SUPPORT
- client pins version → APP-30
- no client auth → OPS-55
- Woo HTTPS Basic Auth, application password, not consumer keys → SETTINGS-10, SETTINGS-15
- u2net post-POC not exposed → CAPTURE-165
- out of contract (bulk, staff, webhook, analytics) → dropped
- test-woo always resyncs → SETTINGS-40
- anchor re-pull / bump rules → SETTINGS-55, SETTINGS-60
+115
View File
@@ -0,0 +1,115 @@
# Coverage matrix — PRD-2026-08.txt
Source: `docs/archive/PRD-2026-08.txt` (frozen history). Method: every labeled atom dispositioned.
## Findings
None new. The two potential holes from this doc are already covered: inference timeout/error →
`METADATA-115`, and no app-level auth → `OPS-55`. The archive's own banner already flags FR17,
FR19, FR40, FR42, and the NFR server timing as non-authoritative.
## Archive banner
- Flags FR17, FR19, FR40, FR42, NFR server timing, and "Known stale" → each of those lines is
superseded by a current row (below).
## Decisions log (2026-08-31)
- Doc contradiction freeze → dropped (process).
- bdft identity, secrets AES-GCM, online-only, `woo_create_status` default draft, `SLAB-UAT-*`
force draft, hybrid happy path, inference off first → ported CAPTURE-90, SETTINGS-20/25,
CAPTURE-15, SETTINGS-65, PUBLISH-10, CAPTURE-5, QUALITY-20.
- Review package not in repo → dropped.
## Decisions log (2026-08-27)
| # | Atom | Disposition | PoR |
|---|---|---|---|
| 1 | no calibration photos | superseded | CAPTURE-25, CAPTURE-30 |
| 1 | manual SKU/length/thickness | ported | CAPTURE-70 |
| 2 | first photo is the measurement photo, top-down | ported | CAPTURE-30, CAPTURE-20 |
| 3 | all photos 80% crop | superseded | CAPTURE-100 |
| 4 | transparent PNG min 1600, 3:4 | superseded | CAPTURE-95, CAPTURE-105 |
| 5 | green/black auto-detect from borders | ported | CAPTURE-35 |
| 6 | species 1 leaf, wood 1+ leaf | ported | METADATA-10 |
| 7 | edge 1, figure 1+, thickness round-up | ported | METADATA-15 |
| 7 | grade 1+ | superseded | METADATA-15 |
| 8 | tags fig/feat 1+ | superseded | METADATA-30 |
| 9 | two-call inference | ported | METADATA-35, METADATA-55 |
| 10 | Call 1 auto only if enabled; review before Call 2 | ported | METADATA-35, METADATA-55 |
| 11 | timeout/non-200 error + retry | ported | METADATA-115 |
| 12 | create status default draft; SLAB-UAT force draft | ported | SETTINGS-65, PUBLISH-10 |
| 13 | prompts as server text files | superseded | METADATA-105 |
| 14 | brand voice + GEO into Call 2 | ported | METADATA-60, SETTINGS-30 |
| 15 | Woo creds server-side AES-GCM | ported | SETTINGS-15, SETTINGS-20 |
| 16 | inference endpoint configurable | ported | SETTINGS-30 |
| 17 | test connection text + vision | ported | SETTINGS-45, SETTINGS-80 |
| 18 | offline not required | ported | CAPTURE-15 |
Open items: none → dropped.
## Functional requirements
- FR1 (1–5 photos) superseded → CAPTURE-25; first top-down ported → CAPTURE-20
- FR2 manual SKU/length/thickness → CAPTURE-70
- FR3 border BG detect → CAPTURE-35
- FR4 scale/sqft/bdft, old divide-by-12 wrong → CAPTURE-75, CAPTURE-85, CAPTURE-90
- FR5 80% crop / 1600 / 3:4 → superseded CAPTURE-100, CAPTURE-105
- FR6 retake/abort → CAPTURE-155
- FR7 deterministic compute → CAPTURE-85, CAPTURE-90
- FR8 thickness manual authoritative → CAPTURE-70, METADATA-50
- FR9 deterministic unit-tested → QUALITY-5, QUALITY-15
- FR10 sync categories/attributes/tags → SETTINGS-50
- FR11 species 1 leaf → METADATA-10
- FR12 wood 1+ leaf → METADATA-10
- FR13 edge 1 → METADATA-15
- FR14 figure 1+ → METADATA-15
- FR15 grade 1+ → superseded METADATA-15
- FR16 thickness round-up → METADATA-15
- FR17 fig-* 1+ → superseded METADATA-30
- FR18 auto-assign + manual override → METADATA-40, METADATA-45, METADATA-50
- FR19 category-weighted pricing → superseded SETTINGS-35
- FR20 bdft pricing → REVIEW-25
- FR21 price editable, stored authoritative → REVIEW-25
- FR22 Call 1 vision with confidences → METADATA-35, METADATA-40
- FR22a threshold 0.7 → METADATA-45
- FR22b species bias full list → METADATA-40
- FR22c free-text → feat-* → METADATA-100
- FR23 Call 2 user-triggered; prose only; server assembles templates → METADATA-55, METADATA-65;
server-assembles superseded → METADATA-70, METADATA-80
- FR24 prompts text files + reset script → superseded METADATA-105
- FR25 progress indicator → dropped (presentation)
- FR26 timeout/non-200 error + retry → METADATA-115
- FR27 results editable, no auto publish → METADATA-50, METADATA-75
- FR28 endpoint configurable + test text/vision → SETTINGS-30, SETTINGS-45, SETTINGS-80
- FR29 chroma-key, U2Net fallback → CAPTURE-35, CAPTURE-165
- FR30 80% / 3:4 / 1600 → superseded CAPTURE-100, CAPTURE-105
- FR31 transparent PNG → CAPTURE-95
- FR32 original + processed, purge after publish → PUBLISH-25, PUBLISH-40
- FR33 consumer keys + app password → superseded SETTINGS-15
- FR34 publish blocked on existing SKU → PUBLISH-15
- FR35 create product fields → PUBLISH-55
- FR36 default draft; SLAB-UAT draft → SETTINGS-65, PUBLISH-10
- FR37 log sync, surface errors, store product id → PUBLISH-25, PUBLISH-30
- FR38 draft slab state → APP-10
- FR39 single review screen, all editable → REVIEW-40
- FR40 server-side processing → superseded CAPTURE-135, APP-40
- FR41 settings UI → SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35
- FR42 compose on `.201` Caddy → superseded OPS-5, OPS-15, OPS-40
- FR43 secrets encrypted, HTTPS → SETTINGS-20, SETTINGS-25, OPS-5
## Non-functional requirements
- performance budgets (1–2s, 3–5s, 45s) → dropped (server timing non-authoritative)
- reliability: unit-tested → QUALITY-5, QUALITY-15
- security: encrypted/HTTPS → SETTINGS-20, SETTINGS-25, OPS-5
- maintainability separation → dropped
- usability one-hand → dropped
## Acceptance criteria
- E2E capture→publish on iPhone/Android → QUALITY-115
- area accuracy +/- 0.25 in² → dropped (sqin banned)
- normalization 80% / PNG / 1600 → superseded CAPTURE-100, CAPTURE-105
- Woo product images/taxonomy/content → PUBLISH-40, PUBLISH-45, PUBLISH-55
- deterministic unit tests + inference logged → QUALITY-5, METADATA-66
@@ -0,0 +1,84 @@
# Coverage matrix — DATA-MODEL, PROMPTS, TECH-SPEC-PIPELINE, DEPLOYMENT, IMPL-PLAN
Sources: the five tag docs at `pre-simplification`.
## Findings
None new. The remaining entries are already ported, superseded by prior rulings, or process
detail. No new requirement is missing.
## Superseded (common to several)
- four knobs including edge offset and feather → CAPTURE-40
- "1–5 photos" / "1–N photos" cap → CAPTURE-25
- 80% fill / 1600 px floor → CAPTURE-100, CAPTURE-105
- grade "1+" / `grade_term_ids` plural → METADATA-15 (exactly one, singular)
- `fig-*` 1+ → METADATA-30 (optional)
- `inference_thread_id`, portable context, `previous_response_id`, per-slab thread → thread work
out
- prompt files on disk, reset script, "prompts are server files" → METADATA-105 (DB with revisions)
- `output_px` / `output_px_min` 1600, `fill_target` 0.80 → CAPTURE-100, CAPTURE-105
- validation module rules in Call 2 → module cut
- em dash title example → hyphen separator
## DATA-MODEL.md
- settings keys (`woo_wp_username`, `woo_app_password`, inference keys/flags, brand/GEO,
`woo_create_status` draft, taxonomy stamps) → SETTINGS-20, SETTINGS-30, SETTINGS-55, SETTINGS-65
- `WOO_BASE_URL` not a settings row → SETTINGS-5; `SLAB_AES_KEY` env, `value_enc` nonce||ciphertext
→ SETTINGS-25
- taxonomy columns and cardinalities → METADATA-10, METADATA-15, METADATA-30
- `sku`, `price`, `price_source`, `content_source` → REVIEW-45, REVIEW-25, METADATA-66
- status machine, transitions, `sync_log.status` → APP-5, PUBLISH-30
- published deletes row + photos, keeps sync_log → PUBLISH-25
- IDs/timestamps/rounding conventions → APP-20, CAPTURE-160
- `sync_log.payload_hash`, `woo_product_id`, `error`, `http_status` → contract detail
- `inference_log` append-only, `call` 1|2 → METADATA-66
- `client_rev`/`server_rev` default 1 → APP-20
## PROMPTS.md
- `inference_enabled`, `content_llm_enabled` gates → SETTINGS-90, METADATA-35, METADATA-70
- Call 1 purpose, inputs, synced-only constraint, schema, threshold, prefill, manual-wins,
ready-not-defined, inference-off → METADATA-5, METADATA-35, METADATA-40, METADATA-45,
METADATA-50, METADATA-75
- free-text → feat-* mapping → METADATA-100
- Call 2 purpose, prose-only, no dimensions, `content_llm_enabled` false → METADATA-55,
METADATA-65, METADATA-70
- brand/GEO + templates → SETTINGS-30, contract detail
- fail closed → SETTINGS-45, METADATA-115
- re-run Call 1 endpoint → API contract
## TECH-SPEC-PIPELINE.md
- sheet/sensitivity knobs, persistence, immediate re-run, confirm, rotate, nearly square →
CAPTURE-40, CAPTURE-41, CAPTURE-45, CAPTURE-50, CAPTURE-60, CAPTURE-65, CAPTURE-145, CAPTURE-150
- mask single contour, retake → CAPTURE-55
- scale/sqft/bdft/widths/price formulas → CAPTURE-75, CAPTURE-80, CAPTURE-85, CAPTURE-90,
REVIEW-25
- no-rule empty price, publish allowed → REVIEW-25
- unsupported client hard stop, client APIs → CAPTURE-10, CAPTURE-140
- factory constants (hue/sat/val, black threshold, border strip, inch step, decimals) → contract
detail (client constants), CAPTURE-35, CAPTURE-41
- no inference in scope → CAPTURE-5
## DEPLOYMENT.md
- `SLAB_AES_KEY`, `WOO_BASE_URL` env, creds encrypted → SETTINGS-25, SETTINGS-5, SETTINGS-20
- `woo_create_status` draft, UAT draft → SETTINGS-65, PUBLISH-10
- health, test-woo on rotate, inference remote → APP-45, SETTINGS-40, OPS-45
- host inventory, ports, LAN/Tailscale, Caddy HTTPS, env mode → OPS-15, OPS-5, OPS-20
- backup 7 daily / 4 weekly → OPS-30
- probes/ports proposal, rekey command, backup schedule → dropped (operational detail)
- `output_px_min` floor line → superseded CAPTURE-105
## IMPL-PLAN.md
- ground rules, inference-toggle suite, status machine → QUALITY-5, QUALITY-10, QUALITY-20, APP-5
- phase deliverables restate CAPTURE/REVIEW/METADATA/PUBLISH/SETTINGS rows
- `woo_create_status`, dedupe, stale recovery, sync_log/purge, partial failure → PUBLISH-10,
PUBLISH-15, PUBLISH-20, PUBLISH-25, PUBLISH-30, PUBLISH-31
- Woo client basic auth, no consumer keys → SETTINGS-15
- E2E browsers, no OCR/ruler/offline → QUALITY-115, CAPTURE-15
- coverage ≥95%, specific UAT slab set, LoRA, "no processing status" → dropped (process/quality
targets, not product requirements)
+109
View File
@@ -0,0 +1,109 @@
# Coverage matrix — TEST-SPEC.md
Source: `docs/TEST-SPEC.md` at tag `pre-simplification` (107 cases). Reconciled last, against the
finished PoR.
## Findings
Two behaviors were tested but not required; both are now PoR rows:
- FUND-3, FUND-5, FUND-6, FUND-7 (keyboard tab order, visible focus ring, 320 px reflow) → `APP-60`
- FUND-24 (no secret material in logs) → `APP-65`
## Superseded cases to purge on migration
- UI-1, UIE-9, UIE-10 — four knobs (edge offset, feather) → two controls
- V-3, API-8 — shared validation module, version hash, 412
- C2-2 — `previous_response_id` / per-slab thread
- C1-1 — "inventory photos at 1024" → clean processed photos
- C2-4 — prompt file edits without restart → prompts live in the DB
- TV-6, TV-7, E2E-5 — 80 percent fill / 1600 px → 90 percent / 800 px
- UIE-1, E2E-4 — manual override of computed fields → read-only
## Case map
FUND
- FUND-1..4, 8..11 — test conventions → dropped (test practice, not requirements)
- FUND-3, 5, 6, 7 — accessibility → APP-60
- FUND-12, 13, 16 — SQLite constraints/migrations → dropped (engineering practice)
- FUND-14 — WAL stale reads → dropped (engineering practice)
- FUND-15 — illegal status transitions rejected → APP-5
- FUND-17 — fresh nonce, tamper fails → SETTINGS-25
- FUND-18 — ciphertext absent from GET → SETTINGS-75
- FUND-19 — missing key refuses startup → SETTINGS-25
- FUND-20 — Basic auth app passwords, HTTPS → SETTINGS-15
- FUND-21 — 401/400/404 mapped → APP-50
- FUND-22 — pre-create SKU lookup, race → PUBLISH-15
- FUND-23 — timeouts/network errors graceful, no stack → PUBLISH-30, PUBLISH-35
- FUND-24 — secrets redacted in logs → APP-65
- FUND-25 — HTTPS, health via proxy, port collision → OPS-5, OPS-15, OPS-20
TV
- TV-1..TV-10 → QUALITY-55..QUALITY-100 (TV-6/TV-7 numeric values superseded)
Validation
- V-1 — SKU charset → REVIEW-45
- V-2 — title/description limits → REVIEW-50
- V-3 — module hash / 412 → dropped
AES / health / draft
- AES-1 → QUALITY-125, SETTINGS-75
- AES-2 → SETTINGS-25
- H-1 → APP-45
- D-1 → API contract, APP-5
Gate C / Woo
- GC-1 → PUBLISH-10; GC-2 → PUBLISH-15; GC-3 → SETTINGS-40; GC-4 → SETTINGS-85; GC-5 → SETTINGS-10
- W-1 → PUBLISH-25; W-2 → PUBLISH-15; W-3 → SETTINGS-55; W-4 → SETTINGS-40; W-5 → PUBLISH-30
Inference
- INF-1 → METADATA-75, QUALITY-20
- INF-2, INF-3 → SETTINGS-45 (mode is kept)
- INF-4 → SETTINGS-45
UI (capture)
- UI-1 → superseded CAPTURE-40
- UI-2 → CAPTURE-50, CAPTURE-55, CAPTURE-165
- UI-3 → CAPTURE-60, CAPTURE-65
- UI-4 → CAPTURE-70, CAPTURE-80, CAPTURE-85, CAPTURE-90
- UI-5 → REVIEW-5, REVIEW-20
Ops
- OPS-1 → APP-45; OPS-2 → OPS-15; OPS-3 → SETTINGS-40, SETTINGS-65, APP-45; OPS-4 → OPS-30;
OPS-5 → OPS-35
API
- API-1 → APP-20; API-2 → APP-40; API-3 → SETTINGS-75; API-4 → METADATA-35, METADATA-115;
API-5 → METADATA-45; API-6 → REVIEW-5; API-7 → SETTINGS-50, SETTINGS-55; API-8 → dropped;
API-9 → API contract; API-10 → SETTINGS-80
- TAX-1 → SETTINGS-60; TAX-2 → METADATA-5; TAX-3 → SETTINGS-60
UI end-to-end
- UIE-1 → superseded REVIEW-30, REVIEW-40
- UIE-2 → METADATA-45, REVIEW-20
- UIE-3 → PUBLISH-15; UIE-4 → PUBLISH-20; UIE-5 → PUBLISH-25; UIE-6 → PUBLISH-30
- UIE-7 → METADATA-70, METADATA-110
- UIE-8 → SETTINGS-5, SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35, SETTINGS-65
- UIE-9, UIE-10 → superseded CAPTURE-40, CAPTURE-45, CAPTURE-145
Calls
- C1-1 → superseded METADATA-35 (clean processed photos)
- C1-2, C1-3 → METADATA-45, REVIEW-5
- C2-1 → METADATA-55, METADATA-60
- C2-2 → superseded (thread work out)
- C2-3 → METADATA-65
- C2-4 → METADATA-66, METADATA-105
- OFF-1 → QUALITY-20; OFF-2 → SETTINGS-45
Instrumentation
- INS-1 → APP-45; INS-2 → APP-55; INS-3 → METADATA-66; INS-4 → PUBLISH-30
E2E
- E2E-1..3 → QUALITY-115
- E2E-4 → superseded REVIEW-30, REVIEW-40
- E2E-5 → superseded CAPTURE-100, CAPTURE-105
## Test harness (contract detail)
Harness layout, allowed result values, evidence rules, and the Gitea-issue bug log are engineering
practice. They belong in `docs/contracts/TEST-SPEC.md`, not the PoR.
+217
View File
@@ -0,0 +1,217 @@
# Coverage matrix — UX-DESIGN.md (pilot)
Purpose: prove every entry on a reference surface in the source doc has a home in the PoR.
Source: `docs/UX-DESIGN.md` at tag `pre-simplification` (non-normative wireframes).
Method: subagent extracted every entry mechanically; this file assigns the PoR home and disposition.
Dispositions: `ported`, `superseded`, `dropped`, `ui` (presentation-only, not a requirement),
`missing` (a finding).
Pilot proof: the three entries fixed in SETTINGS-45 / SETTINGS-90 / METADATA-110 are marked
`ported` below. Before that fix they had no home, which is exactly what this matrix surfaces.
## SETTINGS KEYS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Store URL field | SETTINGS-5 | ported | env, read-only |
| WP Username field | SETTINGS-20 | ported | — |
| Application Password field | SETTINGS-20 | ported | — |
| Inference Endpoint field | SETTINGS-30 | ported | — |
| Inference API Key field | SETTINGS-30 | ported | — |
| Enable Vision toggle, default off | SETTINGS-90 | ported | fixed |
| Enable Content toggle, default off | SETTINGS-90 | ported | fixed |
| Pricing Rules | SETTINGS-35 | ported | — |
| Publish Status dropdown, default Draft | SETTINGS-65 | ported | — |
| Brand Voice field | SETTINGS-30 | ported | — |
| GEO Context field | SETTINGS-30 | ported | — |
| Sheet dropdown | CAPTURE-40 | ported | — |
| Edge Offset control | CAPTURE-40 | superseded | removed |
| Feather control | CAPTURE-40 | superseded | removed |
| Knob persistence localStorage | CAPTURE-145 | ported | — |
## CONTROLS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Test Connection (WP) | SETTINGS-40, SETTINGS-80 | ported | resync and failure |
| Test Connection (Inference) two-turn probe, stateful/stateless/fail | SETTINGS-45 | ported | fixed |
| Enable Vision / Enable Content buttons | SETTINGS-90 | ported | — |
| Add Rule / Edit (pricing) | SETTINGS-35 | ported | — |
| Reset Capture Knobs | CAPTURE-145 | ported | — |
| Refresh Store Lists | SETTINGS-60 | ported | — |
| Got it (first-run card) | — | ui | presentation |
| R retake shortcut | CAPTURE-50 | ported | — |
| Sheet dropdown | CAPTURE-40 | ported | — |
| Sensitivity slider | CAPTURE-41, CAPTURE-45 | ported | — |
| Edge Offset slider | CAPTURE-40 | superseded | removed |
| Feather slider | CAPTURE-40 | superseded | removed |
| Retake (capture) | CAPTURE-50, CAPTURE-155 | ported | — |
| Confirm (capture) | CAPTURE-50 | ported | — |
| Rotate (axis) | CAPTURE-60, CAPTURE-65 | ported | — |
| Confirm (axis) | CAPTURE-60 | ported | — |
| SKU input | REVIEW-45 | ported | — |
| Length input | CAPTURE-70 | ported | — |
| Thickness input | CAPTURE-70 | ported | — |
| Done (type values) | APP-5 | ported | status calibrated |
| X exit review | APP-10 | ported | — |
| Species dropdown | METADATA-10 | ported | — |
| Wood Cat dropdown | METADATA-10 | ported | — |
| Edge Type dropdown | METADATA-15 | ported | — |
| Figure dropdown | METADATA-15 | ported | — |
| Grade dropdown | METADATA-15 | ported | cardinality superseded |
| Fig Tags dropdown | METADATA-30 | ported | cardinality superseded |
| Feat Tags dropdown | METADATA-30 | ported | — |
| Thickness Band dropdown | METADATA-15 | ported | — |
| Moisture dropdown | METADATA-15 | ported | — |
| Price input | REVIEW-25 | ported | — |
| Review Title / Desc button | REVIEW-10 | ported | — |
| Publish button disabled until ready | REVIEW-20 | ported | — |
| Title input | REVIEW-10 | ported | — |
| Short Title input | REVIEW-10 | ported | naming migrated |
| Description input | REVIEW-10 | ported | — |
| Generate Text button, availability | METADATA-110 | ported | fixed |
| Done (title/desc) | REVIEW-40 | ported | — |
| Open in Store | — | ui | candidate: store link is presentation |
| Done (publish success) | PUBLISH-25 | ported | — |
| Retry (publish failed) | PUBLISH-30, PUBLISH-37 | ported | — |
| Back to Review | PUBLISH-30 | ported | retry from same screen |
| Retake (mask failure) | CAPTURE-50, CAPTURE-55 | ported | — |
| Rotate (axis check) | CAPTURE-60 | ported | — |
| Retake (source too small) | CAPTURE-105 | ported | — |
| Edit SKU | PUBLISH-15 | ported | — |
| Open Existing | PUBLISH-15 | ported | — |
| Refresh Store Lists (stale) | PUBLISH-20 | ported | — |
| Retry / Open Settings (unreachable) | PUBLISH-30, PUBLISH-36, PUBLISH-38 | ported | — |
| Update Browser | CAPTURE-10 | ported | — |
## LISTING FIELDS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| SKU | REVIEW-45, PUBLISH-15 | ported | — |
| Length | CAPTURE-70 | ported | — |
| Thickness | CAPTURE-70 | ported | — |
| sqft (computed) | CAPTURE-85 | ported | — |
| bdft (computed) | CAPTURE-90 | ported | — |
| widths (computed) | CAPTURE-80 | ported | — |
| Photos, "at least one inventory PNG" | REVIEW-5 | superseded | ready set is two images |
| Species exactly one | METADATA-10 | ported | — |
| Wood category 1+ | METADATA-10 | ported | — |
| Edge type one | METADATA-15 | ported | — |
| Figure 1+ | METADATA-15 | ported | — |
| Fig tags 1+ | METADATA-30 | superseded | tags optional |
| Feat tags 0+ | METADATA-30 | ported | — |
| Grade 1+ | METADATA-15 | superseded | grade exactly one |
| Thickness Band | METADATA-15 | ported | — |
| Moisture | METADATA-15 | ported | — |
| Price | REVIEW-25 | ported | — |
| Title | REVIEW-10 | ported | — |
| Short Title | REVIEW-10 | ported | naming migrated |
| Description | REVIEW-10 | ported | — |
| Store product ID | PUBLISH-25 | ported | display is presentation |
## STATUSES
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Publish Status Draft | SETTINGS-65 | ported | — |
| calibrated | APP-5 | ported | — |
| publishing | APP-5 | ported | — |
| published | APP-5, PUBLISH-50 | ported | — |
| failed | APP-5 | ported | — |
| Woo product draft | PUBLISH-10 | ported | — |
| SKU "any status" | PUBLISH-15 | ported | — |
| probe stateful/stateless/fail | SETTINGS-45 | ported | fixed |
## ENDPOINTS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| WP REST v3 auth | SETTINGS-15, SETTINGS-80 | ported | — |
| Inference endpoint | SETTINGS-30 | ported | — |
| Inference endpoint reachability | METADATA-110, METADATA-75 | ported | fixed |
## ERROR CODES
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| green check / red error | SETTINGS-80 | ported | — |
| stateful/stateless/fail | SETTINGS-45 | ported | fixed |
## USER-FACING ERROR / EMPTY STATES
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Mask failure "Cannot isolate the slab edge..." | CAPTURE-55 | ported | — |
| Axis misalignment "Rotate the axis..." | CAPTURE-60 | ported | — |
| Source too small "Photo will be too small..." | CAPTURE-105 | ported | — |
| SKU duplicate "This SKU already exists..." | PUBLISH-15 | ported | — |
| Stale taxonomy "This value is no longer valid..." | PUBLISH-20, REVIEW-35 | ported | — |
| Store unreachable "Cannot reach the store..." | PUBLISH-30, PUBLISH-36 | ported | — |
| Publish failed "The store rejected the listing..." | PUBLISH-30, PUBLISH-35 | ported | — |
| Publishing in progress | PUBLISH-5 | ported | — |
| Publish success | PUBLISH-25 | ported | — |
| Browser gate "update Safari or Chrome" | CAPTURE-10 | superseded | matrix includes PC |
| Species/Figure/Wood/Edge nudges | REVIEW-20, METADATA-10, METADATA-15 | ported | — |
| Generic inline nudge | REVIEW-20 | ported | — |
| First-run guidance text | — | ui | presentation |
| Vision-off empty taxonomy | METADATA-45, METADATA-70 | ported | — |
## INFERENCE
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Call 1 flag default off | SETTINGS-90, METADATA-35 | ported | fixed |
| Call 2 flag default off | SETTINGS-90, METADATA-55 | ported | fixed |
| Generate Text triggers Call 2 | METADATA-55 | ported | — |
| Pre-populate threshold 0.7 | METADATA-45 | ported | — |
| Below-threshold leaves empty | METADATA-45 | ported | — |
| Below-threshold manual fill to ready | REVIEW-5, REVIEW-20 | ported | — |
| Two-turn probe stateful/stateless/fail | SETTINGS-45 | ported | fixed |
| AI badge on Call 1 fields | — | ui | presentation |
| Generate Text availability | METADATA-110 | ported | fixed |
| Call 2 prose only, templates numbers | METADATA-65, METADATA-70 | ported | — |
| Vision off state | METADATA-70 | ported | — |
## PUBLISH PAYLOAD / FLOW
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Publish action, poll | PUBLISH-5 | ported | — |
| Draft creation | PUBLISH-10 | ported | — |
| SLAB-UAT-* always draft | PUBLISH-10 | ported | — |
| Publish Status default draft | SETTINGS-65 | ported | — |
| Duplicate SKU behavior | PUBLISH-15 | ported | — |
| Stale taxonomy behavior | PUBLISH-20 | ported | — |
| Success result, open in store | PUBLISH-25 | ported | link is presentation |
| Failure behavior, keep draft, retry | PUBLISH-30 | ported | — |
| Product ID stored, images purged | PUBLISH-25 | ported | — |
| Publish button gating | REVIEW-20 | ported | — |
| Submit-time validation after all fields | REVIEW-20 | superseded | per-field nudges, no submit list |
| Taxonomy freshness on test | SETTINGS-40 | ported | — |
## CONSTANTS / NUMBERS
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| SKU pattern `[A-Z0-9-]{3,24}` | REVIEW-45 | ported | case widened |
| Length / thickness 1/8 step | CAPTURE-70 | ported | — |
| Confidence threshold 0.7 | METADATA-45 | ported | — |
| Width sample every 6 inches | CAPTURE-80 | ported | — |
| Wireframe width 375px | — | ui | sketch detail |
| Sample values (sqft 0.64, bdft 0.96, widths, price, id) | — | ui | examples |
| Mandatory counts list | REVIEW-5 | ported | grade/fig superseded |
| Optional feat-* zero fine | METADATA-30 | ported | — |
| Photo thumbnail count 5 | CAPTURE-25 | superseded | no cap |
| SLAB-UAT-* pattern | PUBLISH-10 | ported | — |
## BROWSER / API SUPPORT
| Entry | PoR | Disposition | Note |
|---|---|---|---|
| Gate on missing APIs | CAPTURE-10 | ported | — |
| Supported browsers | CAPTURE-10 | ported | matrix worded phone-only, superseded |
| Hard-stop screen | CAPTURE-10 | ported | — |
| Client-side mask re-run | CAPTURE-140, CAPTURE-150 | ported | — |
| Camera capture | CAPTURE-20, CAPTURE-25 | ported | — |
| localStorage | CAPTURE-145 | ported | — |
+12
View File
@@ -0,0 +1,12 @@
# Coverage ledger — prd
Source `prd` (`docs/archive/PRD-2026-08.txt`, archived). Seeded by the settings/auth/health
pilot 2026-09-18. The archived PRD is walked in full later in the order.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| prd | decision-15 | Woo credentials are server-side only, never in the browser | ported | SETTINGS-15, SETTINGS-20 | — |
| prd | decision-16 | inference endpoint is configurable: base URL, key, model | ported | SETTINGS-30 | — |
| prd | decision-17 | test connection verifies text and vision support | ported | SETTINGS-80, SETTINGS-45 | — |
| prd | no-app-auth | no app-level auth; HTTPS plus trusted network | ported | OPS-55 | — |
| prd | FR41 | Settings UI for inference, Woo creds, pricing, brand/GEO, prompts | ported | SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35 | prompts are post-M3, audit section 11 |
+32
View File
@@ -0,0 +1,32 @@
# Coverage ledger — PRODUCT.md
Source `cur:PRODUCT` (`docs/PRODUCT.md`, role: intent). Walked 2026-09-18 section by section
against the PoR. Term ruling: the umbrella "Woo attributes" package is renamed **Woo Slab
Taxonomy**; canonical Woo attributes (the five) keep their name.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| cur:PRODUCT | one-slab-one-listing | one slab is one unit and one listing | ported | PUBLISH-60 | — |
| cur:PRODUCT | photos-metadata-inventory | photos and metadata are the inventory record | dropped | — | intent framing; realized by CAPTURE/PHOTOS/CREATE, not a discrete rule |
| cur:PRODUCT | green-black-sheet | photographs taken on a green or black sheet | ported | CAPTURE-20 | — |
| cur:PRODUCT | inventory-png-3-4-transparent | inventory photo(s), uniform 3:4 transparent PNG | ported | CAPTURE-95, CAPTURE-100 | — |
| cur:PRODUCT | listing-fields-user-owned | SKU, length, thickness, price | ported | CAPTURE-70, REVIEW-25 | SKU has no standalone row; folded into PUBLISH-5/PUBLISH-15 |
| cur:PRODUCT | taxon-wood-attributes | species, wood category, edge, figure, grade | ported | METADATA-10, METADATA-15 | — |
| cur:PRODUCT | thickness-band-moisture | thickness band, moisture | ported | METADATA-15 | — |
| cur:PRODUCT | fig-tags-cardinality | one or more `fig-*` tags | superseded | METADATA-30 | source says one or more; ruled optional, Figure attribute is at least one |
| cur:PRODUCT | title-shorttitle-description | title, short title, description | ported | REVIEW-10 | "short title" is stale wording for short_description |
| cur:PRODUCT | feat-tags-optional | zero or more `feat-*` tags | ported | METADATA-30 | — |
| cur:PRODUCT | woo-slab-taxonomy-term | "Woo attributes" locked package name | ported | METADATA-5 | renamed Woo Slab Taxonomy; umbrella rule lives in METADATA-5 |
| cur:PRODUCT | measured-values-templates | measured values feed title and description templates | superseded | METADATA-60, METADATA-70, METADATA-80 | template is the fallback; the model writes when Call 2 runs |
| cur:PRODUCT | decision-rights-table | decision rights for mask/crop, measures, taxonomy, price, prose | ported | CAPTURE-50, CAPTURE-80, CAPTURE-85, CAPTURE-90, CAPTURE-100, METADATA-40, METADATA-45, REVIEW-25, REVIEW-40 | row-for-row mapping; L37 carries the template conflict |
| cur:PRODUCT | override-precedence | user entries override computed or inferred values | ported | METADATA-50 | — |
| cur:PRODUCT | milestones-1-2-browser-only | M1/M2 browser-only, no backend or inference URL | ported | APP-25, OPS-45 | — |
| cur:PRODUCT | m1-handoff-device-draft | M1 handoff is the device draft contents | ported | APP-10 | — |
| cur:PRODUCT | m2-extends-draft | M2 batch, calibration, per-photo PNGs, overlay copy | ported | CAPTURE-25, CAPTURE-110, CAPTURE-115, CAPTURE-130 | — |
| cur:PRODUCT | m3-fastapi-client | M3 FastAPI Woo client and inference proxy, secrets server-side | ported | APP-25, SETTINGS-15, SETTINGS-20, SETTINGS-30 | — |
| cur:PRODUCT | slab-uat-forces-draft | `SLAB-UAT-*` creates a Woo draft | ported | PUBLISH-10 | — |
| cur:PRODUCT | duplicate-sku-blocks | duplicate SKU blocks create | ported | PUBLISH-15 | — |
| cur:PRODUCT | create-inference-off | a listing can be created with inference off | ported | METADATA-70, METADATA-75, QUALITY-20 | — |
| cur:PRODUCT | device-draft-not-woo-draft | device draft is separate from a WooCommerce draft | ported | APP-10 | — |
| cur:PRODUCT | milestone-status-table | milestone status table, UAT on `:10881` | ported | OPS-40 | only host/port is testable; rest navigation; branch-neutral edit queued |
| cur:PRODUCT | out-of-m3-scope | anything beyond CREATE is out of M3 | dropped | — | scope prose, not a requirement; MILESTONES.md owns scope |
-47
View File
@@ -1,47 +0,0 @@
# Coverage ledger — settings / auth / health (pilot)
Seed slice proving the method. Sources: the `pre-simplification` tag, the archived PRD,
the current branch docs, and the Gitea issues.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:TEST-SPEC | GC-1 | SLAB-UAT-* creates a Woo draft regardless of woo_create_status | ported | PUBLISH-10 | — |
| tag:TEST-SPEC | GC-2 | duplicate SKU returns 409 with edit_sku and open_existing | ported | PUBLISH-15 | — |
| tag:TEST-SPEC | GC-3 | test-woo returns ok with taxonomy and always resyncs on success | ported | SETTINGS-40 | — |
| tag:TEST-SPEC | GC-4 | WOO_BASE_URL compose-only, GET read-only, PUT rejects a write with 422 | gap | — | compose-only and read-only live in SETTINGS-5; the API-level 422 rejection has no row |
| tag:TEST-SPEC | GC-5 | FastAPI refuses to start on missing or http WOO_BASE_URL | ported | SETTINGS-10 | — |
| tag:TEST-SPEC | W-3 | taxonomy anchor unchanged on no-op, bumps only on stored-subset hash change | ported | SETTINGS-55 | sync and rebuild live in SETTINGS-50 |
| tag:TEST-SPEC | W-4 | test-woo always runs a taxonomy resync after a successful test | duplicate | SETTINGS-40 | same rule as GC-3 |
| tag:TEST-SPEC | AES-1 | credential encrypt/decrypt round-trips; ciphertext never appears in GET | gap | — | redaction lives in SETTINGS-75; the round-trip assertion has no row |
| tag:TEST-SPEC | AES-2 | missing SLAB_AES_KEY refuses startup, no plaintext fallback | ported | SETTINGS-25 | — |
| tag:TEST-SPEC | API-10 | test-woo fails closed on missing credentials or non-HTTPS URL | gap | — | no row defines test-woo's failure behavior |
| tag:TEST-SPEC | FUND-21 | 401/400/404 mapped to an actionable error, not raw passthrough | gap | — | publish fields are mapped by PUBLISH-20 and PUBLISH-35; the settings handshake mapping is absent |
| tag:TEST-SPEC | H-1 | health 200 with woo_reachable false when credentials are not configured | gap | — | APP-30 names /api/health only |
| tag:TEST-SPEC | INS-1 | health non-200 on DB or volume failure; woo_reachable false when the store is unreachable | gap | — | not represented |
| tag:TEST-SPEC | UIE-8 | Settings screen: WP creds and test-woo, inference and test, pricing, brand/GEO, create status, read-only URL | ported | SETTINGS-5, SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35, SETTINGS-65 | screen composition itself belongs to the contract/UX docs |
| tag:TEST-SPEC | OPS-3 | compose health, test-woo ok, create status draft at deploy | ported | QUALITY-110 | — |
| tag:OPENAPI | health | GET /api/health returns status, version, woo_reachable | gap | — | APP-30 names the path; the body is absent |
| tag:OPENAPI | settings-PUT-reject | PUT /settings cannot write woo_base_url, 422 | duplicate | — | same rule as GC-4 |
| tag:OPENAPI | settings-secrets | secrets are write-only and never echoed | ported | SETTINGS-75 | — |
| tag:OPENAPI | test-woo-shape | test-woo returns ok, detail, taxonomy_anchor, taxonomy_last_sync_at | gap | — | return shape absent |
| tag:OPENAPI | taxonomy-GET | taxonomy GET grouped, with anchor and last_sync_at | ported | SETTINGS-50, SETTINGS-55, SETTINGS-60 | — |
| tag:ARCHITECTURE | s5-server-secrets | Woo creds, inference key, AES key, WOO_BASE_URL are server-side only | ported | SETTINGS-5, SETTINGS-15, SETTINGS-20, SETTINGS-25, SETTINGS-30 | — |
| tag:ARCHITECTURE | s5-client-prefs | sheet and sensitivity preferences persist in localStorage | ported | CAPTURE-145 | — |
| tag:ARCHITECTURE | s7-taxonomy | last_sync_at, anchor, and sync triggers | ported | SETTINGS-50, SETTINGS-55, SETTINGS-60 | — |
| tag:ARCHITECTURE | s3-woo-only-fastapi | Woo is called only by FastAPI | ported | APP-25 | — |
| tag:DATA-MODEL | settings-table | settings.value_enc is AES-GCM; WOO_BASE_URL is not a settings row | ported | SETTINGS-5, SETTINGS-20, SETTINGS-30 | — |
| tag:DEPLOYMENT | env-table | env carries WOO_BASE_URL, Woo credentials, inference key | ported | OPS-10, SETTINGS-5, SETTINGS-30 | — |
| tag:DEPLOYMENT | rotate-creds | rotate Woo credentials then test-woo | duplicate | SETTINGS-40 | rotation is procedure; the verification is test-woo |
| tag:DEPLOYMENT | aes-rekey | SLAB_AES_KEY change requires re-encrypting settings | deferred | — | deferred ruling, audit section 18 item 7 |
| prd | decision-15 | Woo credentials are server-side only, never in the browser | ported | SETTINGS-15, SETTINGS-20 | — |
| prd | decision-16 | inference endpoint is configurable: base URL, key, model | ported | SETTINGS-30 | — |
| prd | decision-17 | test connection verifies text and vision support | gap | — | SETTINGS-45 covers the inference probe; the Woo side of test connection is only SETTINGS-40 |
| prd | no-app-auth | no app-level auth; HTTPS plus trusted network | gap | — | no row states the absence of app-level auth |
| prd | FR41 | Settings UI for inference, Woo creds, pricing, brand/GEO, prompts | ported | SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35 | prompts are post-M3, audit section 11 |
| cur:CREATE | settings-url | WOO_BASE_URL from env, read-only; change means edit .env and recreate | ported | SETTINGS-5 | — |
| cur:CREATE | test-inference-shape | test-inference returns ok, mode, vision_capable, detail | ported | SETTINGS-45 | — |
| cur:CONTENT-WOO | httpx-timeouts | httpx connect 10s, read 60s | gap | — | not represented |
| issue:#5 | app-password | app password, dedicated user, AES-GCM, browser never holds it, sole caller | ported | SETTINGS-15, SETTINGS-20, APP-25 | — |
| issue:#11 | url-compose | WOO_BASE_URL declared in compose, not user-editable | ported | SETTINGS-5 | — |
| issue:#14 | taxonomy-refresh | taxonomy refresh triggers and anchor | ported | SETTINGS-50, SETTINGS-55, SETTINGS-60 | — |
| issue:#6 | instrument-health | health checks and instrumentation | gap | — | same hole as H-1 and INS-1 |
+62
View File
@@ -0,0 +1,62 @@
# Coverage ledger — tag:ARCHITECTURE
Source `tag:ARCHITECTURE` (`docs/ARCHITECTURE.md` at tag `pre-simplification`). Seeded by the
settings/auth/health pilot 2026-09-18.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:ARCHITECTURE | s5-server-secrets | Woo creds, inference key, AES key, WOO_BASE_URL are server-side only | ported | SETTINGS-5, SETTINGS-15, SETTINGS-20, SETTINGS-25, SETTINGS-30 | — |
| tag:ARCHITECTURE | s5-client-prefs | sheet and sensitivity preferences persist in localStorage | ported | CAPTURE-145 | — |
| tag:ARCHITECTURE | s7-taxonomy | last_sync_at, anchor, and sync triggers | ported | SETTINGS-50, SETTINGS-55, SETTINGS-60 | — |
| tag:ARCHITECTURE | s3-woo-only-fastapi | Woo is called only by FastAPI | ported | APP-25 | — |
| tag:ARCHITECTURE | topology-hybrid | phone happy-path; server stores/proxies; reverse proxy HTTPS | ported | CAPTURE-5, APP-25, OPS-5 | — |
| tag:ARCHITECTURE | u2net-deferred | server U2Net deferred from POC, not deleted | ported | CAPTURE-165 | — |
| tag:ARCHITECTURE | keys-server-side | Woo and LLM keys stay on the server; browser never calls Woo or vision | ported | APP-25, SETTINGS-15, SETTINGS-20, SETTINGS-30 | — |
| tag:ARCHITECTURE | new-wood-1-5-photos | new wood: 1-5 photos | superseded | CAPTURE-25 | PoR is one or more; no cap in code |
| tag:ARCHITECTURE | bg-four-knobs | sheet / sensitivity / edge / feather | superseded | CAPTURE-40 | controls are exactly Sheet and Sensitivity |
| tag:ARCHITECTURE | length-axis-confirm | length axis overlay, rotate/confirm | ported | CAPTURE-60, CAPTURE-65 | — |
| tag:ARCHITECTURE | user-length-thickness-sku | user length, thickness, SKU | ported | CAPTURE-70 | — |
| tag:ARCHITECTURE | client-measure-png | sqft, bdft, 6in widths, 3:4 PNGs | ported | CAPTURE-80, CAPTURE-85, CAPTURE-90, CAPTURE-95, CAPTURE-100 | — |
| tag:ARCHITECTURE | call1-prefill | review: Call 1 pre-fill or manual taxonomy | ported | METADATA-35, METADATA-40, METADATA-45 | — |
| tag:ARCHITECTURE | generate-text-tap | tap Generate text | ported | METADATA-55 | — |
| tag:ARCHITECTURE | call2-proxy-text | Call 2 proxy title, description, short description | ported | METADATA-55 | — |
| tag:ARCHITECTURE | happy-path-phone | happy path stays on phone through PNG and numbers; FastAPI idle until confirmed mask | ported | CAPTURE-5, CAPTURE-135 | — |
| tag:ARCHITECTURE | mask-knobs-client | mask knobs on capture; each change re-runs client BG removal; U2Net deferred | ported | CAPTURE-45, CAPTURE-150, CAPTURE-165 | — |
| tag:ARCHITECTURE | draft-upload-delete | draft upload sends originals, PNGs, numbers; delete after publish | ported | CAPTURE-135, PUBLISH-25, PUBLISH-40 | — |
| tag:ARCHITECTURE | call1-auto-body | Call 1 server-side, auto when enabled, 1024 + synced taxonomy, 45s, 0.7 | ported | METADATA-35, METADATA-40, METADATA-45 | — |
| tag:ARCHITECTURE | call2-no-auto | Call 2 does not auto-fire; user taps Generate text | ported | METADATA-55 | — |
| tag:ARCHITECTURE | call2-thread-context | portable context, previous_response_id, per-slab thread | superseded | — | thread ids pushed out of MVP; Call 2 is a fresh call |
| tag:ARCHITECTURE | woo-only-409-422 | Woo only via FastAPI; duplicate SKU 409 on field; stale value 422 on field; draft stays | ported | APP-25, PUBLISH-15, PUBLISH-20, PUBLISH-30 | — |
| tag:ARCHITECTURE | settings-server | settings on the server; store URL env, read-only | ported | SETTINGS-5, SETTINGS-30, SETTINGS-65 | — |
| tag:ARCHITECTURE | what-runs-where-table | what runs where | duplicate | CAPTURE-5, APP-25 | restates the topology and swimlane rows |
| tag:ARCHITECTURE | s5s1-basic-auth | WordPress Basic auth, app password, AES-GCM, not consumer keys | ported | SETTINGS-15, SETTINGS-20 | — |
| tag:ARCHITECTURE | s5s2-inference-key | inference base URL and key encrypted; server proxies | ported | SETTINGS-30, APP-25 | — |
| tag:ARCHITECTURE | s5s3-aes-key | AES master key env, never in the DB | ported | SETTINGS-25 | — |
| tag:ARCHITECTURE | s5s4-woo-url | WOO_BASE_URL env, HTTPS, not user-editable, read-only | ported | SETTINGS-5, SETTINGS-10 | — |
| tag:ARCHITECTURE | s5b2-species-rate | species list with $/bdft read from server settings sync | ported | SETTINGS-35 | — |
| tag:ARCHITECTURE | s5b3-taxonomy-snapshot | taxonomy snapshot read from server, no auth | ported | SETTINGS-50 | — |
| tag:ARCHITECTURE | s5f1-deploy-setup | deploy sets WOO_BASE_URL; operator creates low-priv WP user | ported | SETTINGS-5, SETTINGS-15 | — |
| tag:ARCHITECTURE | s5f2-enter-creds | user enters credentials in Settings; URL read-only | ported | SETTINGS-20 | — |
| tag:ARCHITECTURE | s5f3-encrypt | browser POSTs credentials; server encrypts AES-GCM, stores ciphertext | ported | SETTINGS-20 | — |
| tag:ARCHITECTURE | s5f4-sync-cache | server syncs taxonomy, caches in SQLite | ported | SETTINGS-50 | — |
| tag:ARCHITECTURE | s5f5-client-read | client reads taxonomy, no auth | ported | SETTINGS-50 | — |
| tag:ARCHITECTURE | s5f6-server-woo | all Woo calls go server-to-Woo | ported | APP-25 | — |
| tag:ARCHITECTURE | status-machine | draft, calibrated, ready, publishing, published, failed | ported | APP-5 | — |
| tag:ARCHITECTURE | ready-set | ready set fields | ported | REVIEW-5 | — |
| tag:ARCHITECTURE | ready-set-fig-grade | ready set requires 1+ fig-* tag and 1+ grade | superseded | METADATA-15, METADATA-30 | grade exactly one; tags optional |
| tag:ARCHITECTURE | anchor-bump | anchor bumps only on stored-subset change including deletions | ported | SETTINGS-55 | — |
| tag:ARCHITECTURE | anchor-repull | client re-pulls full taxonomy iff the anchor advanced | ported | SETTINGS-60 | — |
| tag:ARCHITECTURE | species-exclusivity | species pickers and Call 1 lists are exactly the cached set | ported | METADATA-5 | — |
| tag:ARCHITECTURE | trigger-test-woo | test-woo always resyncs taxonomy | ported | SETTINGS-40 | — |
| tag:ARCHITECTURE | trigger-publish-1h | publish resync if the last sync is older than 1 hour | ported | PUBLISH-5, SETTINGS-60 | — |
| tag:ARCHITECTURE | trigger-optional-launch | optional app-launch or Settings refresh | dropped | — | optional, not required for POC |
| tag:ARCHITECTURE | trigger-no-nav-sync | do not sync on every screen navigation | dropped | — | design guidance, not a requirement |
| tag:ARCHITECTURE | validation-module | shared validation module, version hash, 412 | dropped | — | ruled cut 2026-09-18 |
| tag:ARCHITECTURE | sku-charset | SKU charset [A-Z0-9-]{3,24} | ported | REVIEW-45 | case widened to alphanumeric by ruling |
| tag:ARCHITECTURE | validation-empty-optional | field-exit local check; empty optional is valid | dropped | — | review gate covers required fields; no separate row |
| tag:ARCHITECTURE | call1-call2-context | Call 1 to Call 2 portable context default | superseded | — | thread work pushed out of MVP |
| tag:ARCHITECTURE | test-inference-probe | test-inference two-turn probe records stateful, stateless, fail | ported | SETTINGS-45 | mode removed; probe keeps ok, vision_capable, detail |
| tag:ARCHITECTURE | per-slab-thread | per-slab thread id, delete on publish or abandon | superseded | — | cut 2026-09-18 |
| tag:ARCHITECTURE | inference-runtime-failure | Call 1 timeout 45s returns error plus retry on the phone | ported | METADATA-115 | — |
| tag:ARCHITECTURE | call1-image-source | all originals downscaled to 1024 | superseded | METADATA-35 | PoR sends the clean processed photos |
| tag:ARCHITECTURE | title-desc-maxlength | Woo maxLength caps title and descriptions | dropped | — | inherent: bound by Woo limits |
+50
View File
@@ -0,0 +1,50 @@
# Coverage ledger — tag:DATA-MODEL
Source `tag:DATA-MODEL` (`docs/DATA-MODEL.md` at tag `pre-simplification`, role: schema spec).
Walked 2026-09-18. Column mechanics belong in `docs/contracts/DATA-MODEL.md`; the testable
rules carry PoR IDs.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:DATA-MODEL | settings-table | settings.value_enc is AES-GCM; WOO_BASE_URL is not a settings row | ported | SETTINGS-5, SETTINGS-20, SETTINGS-30 | — |
| tag:DATA-MODEL | ids-client-uuid | slab ids are client-generated UUIDv4 | ported | APP-20 | — |
| tag:DATA-MODEL | timestamps-utc | timestamps are UTC ISO-8601 | ported | APP-20 | — |
| tag:DATA-MODEL | status-enum | status draft/calibrated/ready/publishing/published/failed | ported | APP-5 | — |
| tag:DATA-MODEL | rounded-values-stored | rounded values are what gets stored | ported | CAPTURE-160 | — |
| tag:DATA-MODEL | inches-eighth | inches stored as 1/8 increments | ported | CAPTURE-70 | — |
| tag:DATA-MODEL | sqft-bdft-2dp | sqft and bdft to 2 decimals | ported | CAPTURE-85, CAPTURE-90 | — |
| tag:DATA-MODEL | sku-charset | sku `[A-Z0-9-]{3,24}` | ported | REVIEW-45 | — |
| tag:DATA-MODEL | species-leaf-1 | one species leaf | ported | METADATA-10 | — |
| tag:DATA-MODEL | wood-category-1plus | one or more wood-category leaves | ported | METADATA-10 | — |
| tag:DATA-MODEL | edge-1 | one edge type | ported | METADATA-15 | — |
| tag:DATA-MODEL | figure-1plus | one or more figure terms | ported | METADATA-15 | — |
| tag:DATA-MODEL | grade-1plus | one or more grade terms | superseded | METADATA-15 | grade is exactly one |
| tag:DATA-MODEL | thickness-roundup | thickness term by round-up | ported | METADATA-15 | — |
| tag:DATA-MODEL | moisture-default | moisture defaults kiln-dried, not inferred | ported | METADATA-15 | — |
| tag:DATA-MODEL | fig-tags-1plus | fig-* tags 1+ | superseded | METADATA-30 | tags optional |
| tag:DATA-MODEL | feat-tags-0plus | feat-* tags 0+ | ported | METADATA-30 | — |
| tag:DATA-MODEL | price-2dp-source | price 2 dp, price_source recommendation or override | ported | REVIEW-25 | — |
| tag:DATA-MODEL | inference-thread-id | optional stateful inference thread id | superseded | — | thread work out of MVP |
| tag:DATA-MODEL | state-machine | status transitions draft through failed | ported | APP-5 | — |
| tag:DATA-MODEL | ready-set | ready set fields | ported | REVIEW-5 | — |
| tag:DATA-MODEL | published-delete-row | published deletes the row and photos, keeps sync_log | ported | PUBLISH-25 | — |
| tag:DATA-MODEL | failed-error-retry | failed stores error detail, retry available | ported | PUBLISH-30 | — |
| tag:DATA-MODEL | slab-photos-only-inventory | only inventory photos; calibration photos do not exist | superseded | CAPTURE-115 | calibration photo exists; other batch photos are visual inventory |
| tag:DATA-MODEL | no-hard-deletes | no hard deletes for slabs (audit) | superseded | PUBLISH-25 | the local slab row is deleted on success |
| tag:DATA-MODEL | pricing-rules-flat | one flat price_per_bdft per species, no tiers | ported | SETTINGS-35 | — |
| tag:DATA-MODEL | woo-categories-filter | only species and wood-category leaves are offered | ported | METADATA-5, METADATA-10 | — |
| tag:DATA-MODEL | woo-attributes-five | only the five first-class attributes | ported | METADATA-15 | — |
| tag:DATA-MODEL | woo-tags-scope | only fig-* and feat-*; Woo is authoritative | ported | METADATA-30 | — |
| tag:DATA-MODEL | settings-credentials | woo_wp_username and woo_app_password settings | ported | SETTINGS-20 | — |
| tag:DATA-MODEL | settings-store-url-env | store URL is not a settings row | ported | SETTINGS-5 | — |
| tag:DATA-MODEL | settings-inference | inference base URL, key, model, enabled flags | ported | SETTINGS-30 | — |
| tag:DATA-MODEL | settings-brand-geo | brand_voice and geo_context settings | ported | SETTINGS-30 | — |
| tag:DATA-MODEL | settings-create-status | woo_create_status defaults draft | ported | SETTINGS-65 | — |
| tag:DATA-MODEL | settings-taxonomy-stamps | taxonomy_last_sync_at and taxonomy_anchor | ported | SETTINGS-55, SETTINGS-60 | — |
| tag:DATA-MODEL | settings-crop-1600-080 | output_px_min 1600, fill_target 0.80 | superseded | CAPTURE-100, CAPTURE-105 | PoR is 90 percent fill and an 800 px floor |
| tag:DATA-MODEL | settings-client-prefs | sheet and slider prefs in client localStorage | ported | CAPTURE-145 | — |
| tag:DATA-MODEL | settings-aes | AES master key env, value_enc = nonce plus ciphertext | ported | SETTINGS-25 | — |
| tag:DATA-MODEL | sync-log | append-only sync_log, not deleted on publish | ported | PUBLISH-30 | — |
| tag:DATA-MODEL | inference-log | append-only inference_log audit | ported | METADATA-66 | — |
| tag:DATA-MODEL | contract-details | money float internals, JSON arrays, payload_hash, soft-delete mechanics | dropped | — | schema contract detail |
| tag:DATA-MODEL | prompt-files | prompts bind-mounted as text files, read fresh, reset script | superseded | METADATA-105 | ruling: prompts live in the DB with all revisions |
+48
View File
@@ -0,0 +1,48 @@
# Coverage ledger — tag:DEPLOYMENT
Source `tag:DEPLOYMENT` (`docs/DEPLOYMENT.md` at tag `pre-simplification`, role: deploy
playbook). Vetted 2026-09-18. Testable rules are OPS/SETTINGS; operational facts live in
`deploy/`. Doc retired (see migration TODOs).
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:DEPLOYMENT | env-table | env carries WOO_BASE_URL, Woo credentials, inference key | ported | OPS-10, SETTINGS-5, SETTINGS-30 | — |
| tag:DEPLOYMENT | rotate-creds | rotate Woo credentials then test-woo | duplicate | SETTINGS-40 | rotation is procedure; the verification is test-woo |
| tag:DEPLOYMENT | aes-rekey | SLAB_AES_KEY change requires re-encrypting settings | deferred | — | deferred ruling, audit section 18 item 7 |
| tag:DEPLOYMENT | preamble-hybrid-sot | client owns measure/crop; server-side measure/crop scaffolding not done | ported | CAPTURE-5, CAPTURE-135 | — |
| tag:DEPLOYMENT | preamble-uat-draft | Woo UAT is a draft with `SLAB-UAT-*` on the production store | ported | PUBLISH-10 | — |
| tag:DEPLOYMENT | preamble-inference-remote | inference is a remote configurable endpoint, not on the app host | ported | OPS-45 | — |
| tag:DEPLOYMENT | lab-host-example | historical lab host `192.168.1.201` | dropped | — | non-normative historical example |
| tag:DEPLOYMENT | host-inventory | docker ps, Caddy config, free port, volume convention | ported | OPS-15 | — |
| tag:DEPLOYMENT | reachability | confirm the hostname is reachable from the phone network | ported | OPS-5 | — |
| tag:DEPLOYMENT | inventory-before-bind | write values into deploy/INVENTORY.md and host .env before compose up | ported | OPS-15 | — |
| tag:DEPLOYMENT | repo-layout | repository layout at scaffold | dropped | — | scaffold detail |
| tag:DEPLOYMENT | store-url-env | WOO_BASE_URL in deploy/.env, injected into FastAPI | ported | SETTINGS-5, OPS-10 | — |
| tag:DEPLOYMENT | store-url-https | HTTPS only; FastAPI refuses missing or http at startup | ported | SETTINGS-10 | — |
| tag:DEPLOYMENT | store-url-not-settings-row | not a Settings input and not a SQLite settings row | ported | SETTINGS-5 | — |
| tag:DEPLOYMENT | store-url-readonly | Settings UI shows the URL read-only | ported | SETTINGS-5 | — |
| tag:DEPLOYMENT | app-password-out-of-compose | Woo application password stays out of compose; entered in Settings | ported | SETTINGS-20 | — |
| tag:DEPLOYMENT | house-rules-localhost-caddy | services bind 127.0.0.1; Caddy is the only public surface | ported | OPS-20 | — |
| tag:DEPLOYMENT | house-rules-pinned-images | no latest tags; restart unless-stopped; mem_limit | ported | OPS-25 | — |
| tag:DEPLOYMENT | caddy-fragment | Caddy fragment contents | dropped | — | deploy detail |
| tag:DEPLOYMENT | secret-aes-key | SLAB_AES_KEY env, mode 600, 32-byte base64, never in the repo | ported | SETTINGS-25, OPS-10 | — |
| tag:DEPLOYMENT | secret-woo-creds | Woo credentials AES-GCM in SQLite, dedicated low-priv user, not consumer keys | ported | SETTINGS-15, SETTINGS-20 | — |
| tag:DEPLOYMENT | secret-inference-key | inference API key AES-GCM in SQLite | ported | SETTINGS-30 | — |
| tag:DEPLOYMENT | woocred-https-store | store must already be on HTTPS for Application Passwords | ported | SETTINGS-15 | — |
| tag:DEPLOYMENT | woocred-dedicated-user | dedicated low-privilege WordPress user | ported | SETTINGS-15 | — |
| tag:DEPLOYMENT | woocred-generate-password | generate the application password in the WP profile | dropped | — | procedure |
| tag:DEPLOYMENT | woocred-enter-creds | enter credentials in Settings; AES-GCM; browser never keeps them | ported | SETTINGS-20 | — |
| tag:DEPLOYMENT | backup-sqlite-images | WAL-safe SQLite backup plus images tar; 7 daily and 4 weekly | ported | OPS-30 | — |
| tag:DEPLOYMENT | backup-prompt-files | prompt files live in git and need no separate backup | superseded | — | prompts move to the DB with all revisions (GAP-8) |
| tag:DEPLOYMENT | backup-offbox | mirror the backup to an off-box share | ported | OPS-30 | — |
| tag:DEPLOYMENT | restore-tested | stop, restore DB and images, start; tested once | ported | OPS-35 | — |
| tag:DEPLOYMENT | runbook | operations runbook | dropped | — | procedure |
| tag:DEPLOYMENT | smoke-health | health ok from the phone over HTTPS | ported | APP-45 | — |
| tag:DEPLOYMENT | smoke-test-woo | test-woo ok, create status draft, inference off | ported | SETTINGS-40, SETTINGS-65 | — |
| tag:DEPLOYMENT | smoke-capture-to-ready | create a slab, upload fixtures, poll to ready | ported | APP-5 | — |
| tag:DEPLOYMENT | smoke-bdft-price | verify bdft and price against the fixture | ported | CAPTURE-90, REVIEW-25 | — |
| tag:DEPLOYMENT | smoke-uat-draft | publish a `SLAB-UAT-*` slab; Woo product must be draft | ported | PUBLISH-10 | — |
| tag:DEPLOYMENT | smoke-cleanup | leave or delete the UAT draft | dropped | — | procedure |
| tag:DEPLOYMENT | scaling-postgres-redis | Postgres/Redis/GPU scaling paths | dropped | — | post-POC |
| tag:DEPLOYMENT | scaling-never-lower-1600 | never lower output_px_min below 1600 | superseded | CAPTURE-105 | PoR floor is 800 px |
| tag:DEPLOYMENT | scaling-rembg | RemBG is not part of the hybrid happy path | dropped | — | design note |
+82
View File
@@ -0,0 +1,82 @@
# Coverage ledger — tag:IMPL-PLAN
Source `tag:IMPL-PLAN` (`docs/IMPL-PLAN.md` at tag `pre-simplification`). Vetted 2026-09-18.
Process history and duplicates; doc retired (see migration TODOs).
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:IMPL-PLAN | ground-rules | deterministic core tested first, no feature without a passing test, inference toggleable | ported | QUALITY-5, QUALITY-10, QUALITY-20 | — |
| tag:IMPL-PLAN | gates-abc | Gate A docs freeze, Gate B host, Gate C first draft listing | dropped | — | superseded by MILESTONES and the PoR |
| tag:IMPL-PLAN | phase0-client-modules | client pure modules for the deterministic core | ported | CAPTURE-5, CAPTURE-80, CAPTURE-85, CAPTURE-90 | — |
| tag:IMPL-PLAN | phase0-fastapi-skeleton | app factory, health, SQLite, settings AES, draft store stub | ported | APP-30, APP-45, SETTINGS-20, SETTINGS-25, APP-40 | — |
| tag:IMPL-PLAN | phase0-tests-tv | unit tests for TV-1 through TV-10 | ported | QUALITY-15 | — |
| tag:IMPL-PLAN | phase0-fixture-set | fixture photo set for Gate B review | dropped | — | process |
| tag:IMPL-PLAN | phase0-no-server-recompute | server stores client numbers, no server recompute | ported | CAPTURE-135, APP-40 | — |
| tag:IMPL-PLAN | phase0-u2net-stub | real U2Net stubbed, deferred | ported | CAPTURE-165 | — |
| tag:IMPL-PLAN | phase0-species-synced-only | species offered are exactly the synced leaves | ported | METADATA-5 | — |
| tag:IMPL-PLAN | phase0-offline-deferred | offline PWA deferred | ported | CAPTURE-15 | — |
| tag:IMPL-PLAN | phase0-no-fake-upscale | undersized source warns and requires retake | ported | CAPTURE-105 | — |
| tag:IMPL-PLAN | phase0-acceptance-math | bdft identity, no divide-by-12, rounding | ported | CAPTURE-90, QUALITY-100 | — |
| tag:IMPL-PLAN | phase0-health-compose | health up in compose after INVENTORY is filled | ported | OPS-15, APP-45 | — |
| tag:IMPL-PLAN | phase0-settings-aes | AES round-trip, secrets never in GET | ported | SETTINGS-75, QUALITY-125 | — |
| tag:IMPL-PLAN | phase0-draft-store | draft stores uploads without server recompute | ported | APP-40 | — |
| tag:IMPL-PLAN | phase0-coverage-property | coverage target and property checks | ported | QUALITY-40, QUALITY-45 | — |
| tag:IMPL-PLAN | phase0-exit-gate | Ty confirms the shown output | ported | QUALITY-30 | — |
| tag:IMPL-PLAN | phase1-capture-1-5 | online capture of 1-5 photos | superseded | CAPTURE-25 | no cap |
| tag:IMPL-PLAN | phase1-four-knobs | four knobs inline with live re-run | superseded | CAPTURE-40 | two knobs |
| tag:IMPL-PLAN | phase1-client-measure-png | client sqft/bdft/widths and 3:4 PNG prep | ported | CAPTURE-80, CAPTURE-85, CAPTURE-90, CAPTURE-95 | — |
| tag:IMPL-PLAN | phase1-manual-fields | manual SKU, length, thickness, taxonomy | ported | CAPTURE-70 | — |
| tag:IMPL-PLAN | phase1-calibrated-upload | calibrated draft upload, server stores only | ported | CAPTURE-135 | — |
| tag:IMPL-PLAN | phase1-uat-draft | Woo draft create with `SLAB-UAT-*` on the production store | ported | PUBLISH-10 | — |
| tag:IMPL-PLAN | phase1-inference-off | inference remains off for the slice | ported | QUALITY-20 | — |
| tag:IMPL-PLAN | phase1-routers-openapi | routers per OPENAPI, generated openapi.yaml | dropped | — | contract detail |
| tag:IMPL-PLAN | phase1-optimistic-concurrency | client_rev/server_rev, 409 paths | ported | APP-20 | — |
| tag:IMPL-PLAN | phase1-status-machine-queue | status machine, queue only for publish and inference | ported | APP-5 | — |
| tag:IMPL-PLAN | phase1-integration-tests | create to ready, revision conflict, duplicate SKU, encryption, anchor | ported | QUALITY-35 | — |
| tag:IMPL-PLAN | phase1-put-stores-derived | PUT stores derived fields, does not recompute | ported | APP-40 | — |
| tag:IMPL-PLAN | phase1-taxonomy-anchor | anchor advances only on real change; client re-pulls | ported | SETTINGS-55, SETTINGS-60 | — |
| tag:IMPL-PLAN | phase2-offline | offline capture deferred | ported | CAPTURE-15 | — |
| tag:IMPL-PLAN | phase3-review-override-paths | widths/sqft/bdft shown with manual override paths | superseded | REVIEW-30, REVIEW-40 | calculated fields are read-only |
| tag:IMPL-PLAN | phase3-show-pngs | show processed PNGs, originals while retained | ported | PUBLISH-40 | — |
| tag:IMPL-PLAN | phase3-inference-ui | 0.7 pre-fill, below empty, full ready set | ported | METADATA-45, REVIEW-5 | — |
| tag:IMPL-PLAN | phase3-capture-four-knobs | four knobs on the mask screen | superseded | CAPTURE-40 | two knobs |
| tag:IMPL-PLAN | phase3-publish-poll | publish button, poll, surface error detail | ported | PUBLISH-5, PUBLISH-30 | — |
| tag:IMPL-PLAN | phase3-settings-ui | settings screen for creds, inference, pricing, brand/GEO, create status | ported | SETTINGS-5, SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35, SETTINGS-65 | — |
| tag:IMPL-PLAN | phase3-secrets-masked | secrets never appear in GET | ported | SETTINGS-75 | — |
| tag:IMPL-PLAN | phase4-woo-client | Woo client with Basic auth, taxonomy sync | ported | SETTINGS-15, SETTINGS-50 | — |
| tag:IMPL-PLAN | phase4-auto-assign | auto-assign categories, five attributes, fig/feat tags | ported | METADATA-10, METADATA-15, METADATA-30 | — |
| tag:IMPL-PLAN | phase4-media-create | media upload of processed PNGs, product create per status | ported | PUBLISH-40, PUBLISH-10 | — |
| tag:IMPL-PLAN | phase4-dedupe | dedupe by SKU before create, 409 recovery | ported | PUBLISH-15 | — |
| tag:IMPL-PLAN | phase4-stale-recovery | 422 stale-field recovery with current options | ported | PUBLISH-20 | — |
| tag:IMPL-PLAN | phase4-sync-log-purge | sync_log, set published, purge images | ported | PUBLISH-25, PUBLISH-30 | — |
| tag:IMPL-PLAN | phase4-taxonomy-sync | taxonomy sync endpoint against the real store | ported | SETTINGS-50, SETTINGS-55 | — |
| tag:IMPL-PLAN | phase4-integration-respx | integration tests against a Woo mock | ported | QUALITY-35 | — |
| tag:IMPL-PLAN | phase4-partial-failure | orphaned media logged, manual cleanup note | ported | PUBLISH-31 | — |
| tag:IMPL-PLAN | phase5-call1-proxy | Call 1 proxy, all photos at 1024, taxonomy, 0.7 | ported | METADATA-35, METADATA-40, METADATA-45 | — |
| tag:IMPL-PLAN | phase5-prefill-rules | at or above threshold pre-fill, below empty | ported | METADATA-45 | — |
| tag:IMPL-PLAN | phase5-call2-proxy | Call 2 proxy, never auto, prose only, templates inject numbers | ported | METADATA-70, METADATA-65 | — |
| tag:IMPL-PLAN | phase5-portable-context | portable Call 1 context, previous_response_id | superseded | — | thread work out of MVP |
| tag:IMPL-PLAN | phase5-test-inference | test-inference probe | ported | SETTINGS-45 | mode removed |
| tag:IMPL-PLAN | phase5-prompt-files | prompt files read fresh each call | superseded | METADATA-105 | prompts live in the DB with all revisions |
| tag:IMPL-PLAN | phase5-no-invention | no numeric invention, LoRA deferred | ported | METADATA-65 | — |
| tag:IMPL-PLAN | phase6-host-inventory | host inventory pass | ported | OPS-15 | — |
| tag:IMPL-PLAN | phase6-deploy-backup | deploy, backup, restore tested | ported | OPS-5, OPS-30, OPS-35 | — |
| tag:IMPL-PLAN | phase6-uat-suite | UAT suite on real slabs | ported | QUALITY-110 | — |
| tag:IMPL-PLAN | phase6-e2e-browsers | end-to-end capture to publish on phone and PC browsers | ported | QUALITY-115 | — |
| tag:IMPL-PLAN | phase6-manual-length-override | manual length override recalculates widths/sqft/bdft | superseded | REVIEW-30, REVIEW-40 | calculated fields are read-only |
| tag:IMPL-PLAN | phase6-crop-80-1600 | crop 80 percent, shorter side 1600 | superseded | CAPTURE-100, CAPTURE-105 | PoR is 90 percent and 800 px |
| tag:IMPL-PLAN | phase6-woo-product | Woo product with processed PNGs and taxonomy | ported | PUBLISH-40, PUBLISH-45 | — |
| tag:IMPL-PLAN | phase6-unit-tests-logs | deterministic functions tested, inference calls logged | ported | QUALITY-5, METADATA-66 | — |
| tag:IMPL-PLAN | risks-green-sheet | chroma key plus inline knobs, retake, never lower pixel floor | ported | CAPTURE-35, CAPTURE-41, CAPTURE-155 | — |
| tag:IMPL-PLAN | risks-never-lower-1600 | never lower output_px_min below 1600 | superseded | CAPTURE-105 | PoR floor is 800 px |
| tag:IMPL-PLAN | risks-no-vision | inference toggleable, manual fully functional | ported | METADATA-75 | — |
| tag:IMPL-PLAN | risks-partial-publish | orphaned media, retained images, manual cleanup | ported | PUBLISH-31 | — |
| tag:IMPL-PLAN | risks-sqlite | SQLite contention under concurrent polls | dropped | — | single owner, low volume |
| tag:IMPL-PLAN | risks-host-port | host port or Caddy collision | ported | OPS-15 | — |
| tag:IMPL-PLAN | risks-ruler-deferred | ruler detection deferred; manual length is authoritative | ported | CAPTURE-15 | — |
| tag:IMPL-PLAN | dod-phases | all phases exit-gated by Ty | dropped | — | process |
| tag:IMPL-PLAN | dod-acceptance | hybrid online acceptance met in Phase 6 UAT | ported | QUALITY-110 | — |
| tag:IMPL-PLAN | dod-tests-green-off | pytest, integration, UAT green with inference off | ported | QUALITY-20 | — |
| tag:IMPL-PLAN | dod-deploy-backup | deployed, HTTPS, backed up, restore tested | ported | OPS-5, OPS-30, OPS-35 | — |
| tag:IMPL-PLAN | dod-gitea-source | repo on gitea is source of truth | ported | OPS-50 | — |
| tag:IMPL-PLAN | dod-archive-frozen | archive is frozen history; live docs are the SoT | dropped | — | process |
+79
View File
@@ -0,0 +1,79 @@
# Coverage ledger — tag:OPENAPI
Source `tag:OPENAPI` (`docs/OPENAPI.md` at tag `pre-simplification`, role: contract). Walked
2026-09-18. Wire detail (endpoints, schemas, examples) is contract material for
`docs/contracts/API.md`; only the testable rules carry PoR IDs.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:OPENAPI | auth-no-client-auth | no client auth; trusted LAN/Tailscale plus HTTPS | ported | OPS-55 | — |
| tag:OPENAPI | error-envelope | uniform error envelope { code, message, detail } | ported | APP-35 | — |
| tag:OPENAPI | error-400-404 | 400 validation; 404 not_found | ported | APP-35 | — |
| tag:OPENAPI | error-409-duplicate-sku | 409 duplicate_sku, SKU exists in Woo any status | ported | PUBLISH-15 | — |
| tag:OPENAPI | error-409-revision-conflict | 409 revision_conflict with current_server_rev | ported | APP-20 | — |
| tag:OPENAPI | error-422-unpublishable | 422 unpublishable with field keys, no raw code | ported | REVIEW-5, REVIEW-20 | — |
| tag:OPENAPI | error-412-validation-stale | 412 validation_module_stale | dropped | — | validation module ruled cut 2026-09-18 |
| tag:OPENAPI | error-502-woo | 502 woo_error carries the Woo error body | ported | PUBLISH-30 | — |
| tag:OPENAPI | error-500-internal | 500 internal | ported | APP-35 | — |
| tag:OPENAPI | revisions | client_rev/server_rev, mismatch 409 revision_conflict | ported | APP-20 | — |
| tag:OPENAPI | photos-multipart-40mb | multipart, max 40 MB per request | dropped | — | contract detail |
| tag:OPENAPI | photos-meta-role-kind | meta { kind: inventory, role, seq } | dropped | — | role/kind label discarded per CAPTURE migration |
| tag:OPENAPI | pagination-full-arrays | lists return full arrays | ported | APP-35 | — |
| tag:OPENAPI | api-version | /api/v1, breaking changes bump v2 | ported | APP-30 | — |
| tag:OPENAPI | schema-sku | SKU string 3..24 | ported | REVIEW-45 | — |
| tag:OPENAPI | schema-length-thickness | length_in and thickness_in 1/8 step | ported | CAPTURE-70 | — |
| tag:OPENAPI | schema-derived | sqft, bdft, widths computed by client | ported | CAPTURE-80, CAPTURE-85, CAPTURE-90 | — |
| tag:OPENAPI | schema-species-woodcategory | species leaf 1, wood categories 1+ | ported | METADATA-10 | — |
| tag:OPENAPI | schema-edge-figure | edge 1, figure 1+ | ported | METADATA-15 | — |
| tag:OPENAPI | schema-grade-cardinality | grade 1+ | superseded | METADATA-15 | grade is exactly one |
| tag:OPENAPI | schema-thickness-roundup | thickness term by round-up | ported | METADATA-15 | — |
| tag:OPENAPI | schema-moisture-default | moisture defaults kiln-dried | ported | METADATA-15 | — |
| tag:OPENAPI | schema-fig-tags-cardinality | fig-* 1+ | superseded | METADATA-30 | tags optional |
| tag:OPENAPI | schema-feat-tags | feat-* 0+ | ported | METADATA-30 | — |
| tag:OPENAPI | schema-price | price 2 dp, price_source recommendation or override | ported | REVIEW-25 | — |
| tag:OPENAPI | schema-short-title | short_title field | superseded | REVIEW-10 | Woo canonical name is short_description |
| tag:OPENAPI | slab-read-model | status, inference_status, woo_product_id, published_at, revisions | ported | APP-5 | — |
| tag:OPENAPI | photo-read-410 | original/processed urls, 410 after publish | ported | PUBLISH-25 | — |
| tag:OPENAPI | call1-result-shape | Call 1 taxonomy ids plus confidences | ported | METADATA-40 | — |
| tag:OPENAPI | call1-free-text-to-feat | free-text observations mapped to synced feat-* tags | ported | METADATA-100 | — |
| tag:OPENAPI | call2-result-shape | title, short_title, description | ported | METADATA-55 | short_title naming migrated to short_description |
| tag:OPENAPI | price-rule-shape | flat price_per_bdft per species | ported | SETTINGS-35 | — |
| tag:OPENAPI | settings-view-shape | settings read model; secrets masked | ported | SETTINGS-5, SETTINGS-30, SETTINGS-35, SETTINGS-65, SETTINGS-75 | — |
| tag:OPENAPI | settings-view-crop | fill_target 0.80, output_px_min 1600 | superseded | CAPTURE-100, CAPTURE-105 | PoR is 90 percent fill and an 800 px floor |
| tag:OPENAPI | meta-endpoint | GET /meta version, templates_configured | dropped | — | contract detail |
| tag:OPENAPI | create-slab-calibrated | POST /slabs returns 201 calibrated, stores client numbers | ported | CAPTURE-135, APP-5 | — |
| tag:OPENAPI | create-slab-auto-call1 | auto-run Call 1 only if inference_enabled | ported | METADATA-35 | — |
| tag:OPENAPI | create-slab-confidence-persist | persist inferred values only at or above 0.7 | ported | METADATA-45 | — |
| tag:OPENAPI | create-slab-dup-sku | 409 duplicate_sku on create | ported | PUBLISH-15 | — |
| tag:OPENAPI | get-slabs-list | GET /slabs most recent first | dropped | — | contract detail |
| tag:OPENAPI | get-slab-poll | GET /slabs/{id} poll with backoff | dropped | — | contract detail |
| tag:OPENAPI | put-slab-stores-derived | PUT stores client derived fields, never recomputes | ported | APP-40 | — |
| tag:OPENAPI | put-slab-dup-sku-actions | duplicate SKU actions edit_sku/open_existing, never raw code | ported | PUBLISH-15, PUBLISH-35 | — |
| tag:OPENAPI | put-slab-stale-field | 422 stale_field with current options | ported | PUBLISH-20 | — |
| tag:OPENAPI | put-slab-412 | 412 validation module stale | dropped | — | validation module ruled cut |
| tag:OPENAPI | delete-slab-soft | DELETE soft, unpublished drafts only | dropped | — | contract detail |
| tag:OPENAPI | u2net-endpoint | POST u2net post-POC, not exposed | ported | CAPTURE-165 | — |
| tag:OPENAPI | photo-serve-410 | photo original/processed, 410 after publish | ported | PUBLISH-25 | — |
| tag:OPENAPI | infer-taxon-endpoint | POST infer-taxon, prompt fresh, 1024 plus taxonomy, 202 | ported | METADATA-35 | — |
| tag:OPENAPI | infer-taxon-image-source | original photos downscaled to 1024 | superseded | METADATA-35 | PoR sends the clean processed photos |
| tag:OPENAPI | infer-taxon-timeout | timeout over 45s returns 504 | ported | METADATA-75 | — |
| tag:OPENAPI | infer-content-endpoint | POST infer-content, 202, requires test-inference ok | ported | METADATA-55 | — |
| tag:OPENAPI | infer-content-context-thread | full resend default, previous_response_id, per-slab thread | superseded | — | thread work out of MVP |
| tag:OPENAPI | publish-preconditions | publish requires the full ready set, else 422 | ported | REVIEW-5 | — |
| tag:OPENAPI | publish-dup-sku | 409 duplicate_sku before create | ported | PUBLISH-15 | — |
| tag:OPENAPI | publish-stale | 422 stale_field, draft stays | ported | PUBLISH-20, PUBLISH-30 | — |
| tag:OPENAPI | publish-success | success sets woo_product_id, purges images, deletes draft | ported | PUBLISH-25 | — |
| tag:OPENAPI | publish-woo-fail | Woo failure returns failed, sync_log, 502 | ported | PUBLISH-30 | — |
| tag:OPENAPI | taxonomy-sync | sync rebuilds cache, anchor only on change, previous retained on failure | ported | SETTINGS-50, SETTINGS-55 | — |
| tag:OPENAPI | pricing-crud | pricing rule CRUD | ported | SETTINGS-35 | — |
| tag:OPENAPI | settings-get | GET settings returns SettingsView | ported | SETTINGS-75 | — |
| tag:OPENAPI | settings-put | PUT settings partial, secrets re-encrypted, password never echoed | ported | SETTINGS-20, SETTINGS-30, SETTINGS-65 | — |
| tag:OPENAPI | settings-put-woo-url-reject | woo_base_url not writable | ported | SETTINGS-85 | — |
| tag:OPENAPI | settings-put-consumer-key-reject | reject consumer key/secret payload | ported | SETTINGS-15 | — |
| tag:OPENAPI | test-woo-fail-closed | test-woo fails closed on missing credentials or non-https | ported | SETTINGS-80 | — |
| tag:OPENAPI | test-inference-shape | test-inference ok, mode, vision_capable, detail | ported | SETTINGS-45 | mode removed by ruling |
| tag:OPENAPI | validation-module-endpoint | GET validation/module, hash, 412 on mismatch | dropped | — | ruled cut 2026-09-18 |
| tag:OPENAPI | examples-worked | worked request/response examples | dropped | — | non-normative examples |
| tag:OPENAPI | example-taxonomy-sync-key | example uses synced_at while spec says taxonomy_last_sync_at | dropped | — | contract detail inconsistency |
| tag:OPENAPI | versioning-client-pin | client pins the version it was built against | ported | APP-30 | — |
| tag:OPENAPI | out-of-contract-v1 | bulk, staff/role, webhook push, analytics out of contract | dropped | — | contract detail |
+36
View File
@@ -0,0 +1,36 @@
# Coverage ledger — tag:PROMPTS
Source `tag:PROMPTS` (`docs/PROMPTS.md` at tag `pre-simplification`, role: prompt spec).
Walked 2026-09-18. Prompt templates are contract material for `docs/contracts/PROMPTS.md`;
the testable rules carry PoR IDs.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:PROMPTS | management-location | prompts are server text files under backend/app/prompts, mounted read-only | superseded | METADATA-105 | ruling: prompts live in the DB with all revisions |
| tag:PROMPTS | management-edit-host | edit the text files on the host, no restart | superseded | — | prompts move to the DB |
| tag:PROMPTS | management-reset-script | python -m app.prompts.reset restores defaults | superseded | — | replaced by DB revision history |
| tag:PROMPTS | management-version-log | inference_log stores prompt content or hash per call | ported | METADATA-66 | — |
| tag:PROMPTS | call1-purpose | classify species, edge, figure, grade from photos using synced lists only | ported | METADATA-40 | — |
| tag:PROMPTS | call1-inputs-photos | 1-5 inventory photos downscaled to 1024 | ported | METADATA-35 | downsample rule |
| tag:PROMPTS | call1-photo-cap | 1-5 inventory photos | superseded | CAPTURE-25 | no photo cap |
| tag:PROMPTS | call1-inputs-taxonomy | species, edge, figure, grade lists with ids | ported | METADATA-35, METADATA-40 | — |
| tag:PROMPTS | call1-inputs-metadata | user metadata SKU, length, thickness | ported | METADATA-35 | — |
| tag:PROMPTS | call1-system-constraint | only use provided taxonomy values, do not invent | ported | METADATA-40 | — |
| tag:PROMPTS | call1-schema | taxonomy ids plus confidences and free-text observations | ported | METADATA-40 | — |
| tag:PROMPTS | call1-free-text-to-feat | free-text observations mapped to synced feat-* tags | ported | METADATA-100 | — |
| tag:PROMPTS | call1-prepopulation | Call 1 is the primary pre-fill source when inference is enabled | ported | METADATA-45 | — |
| tag:PROMPTS | call1-confidence-gate | at or above 0.7 pre-fill, below leaves empty | ported | METADATA-45 | — |
| tag:PROMPTS | call1-ready-not-defined | Call 1 does not define the ready gate | ported | METADATA-75 | — |
| tag:PROMPTS | call1-manual-wins | manual entry wins; Call 1 is assist only | ported | METADATA-50 | — |
| tag:PROMPTS | call2-purpose | the model writes descriptive prose only | ported | METADATA-60 | — |
| tag:PROMPTS | call2-inputs-context | portable Call 1 context, previous_response_id | superseded | — | thread work out of MVP |
| tag:PROMPTS | call2-confirmed-inferred | explicit confirmed versus inferred labels | ported | METADATA-60 | PoR states metadata confirmed or changed in review |
| tag:PROMPTS | call2-deterministic-measurements | deterministic measurements, never invented | ported | METADATA-60, METADATA-65 | — |
| tag:PROMPTS | call2-brand-geo | brand voice, GEO context, templates | ported | METADATA-60 | — |
| tag:PROMPTS | call2-validation-rules | shared-validation rules in Call 2 assembly | dropped | — | validation module ruled cut |
| tag:PROMPTS | call2-system-no-invention | measurements are not invented; only provided data is used | ported | METADATA-65 | — |
| tag:PROMPTS | call2-template-assembly | server assembles title and description from templates | ported | METADATA-70, METADATA-80 | — |
| tag:PROMPTS | call2-llm-not-dimensions | the LLM never touches dimensions | ported | METADATA-65 | — |
| tag:PROMPTS | call2-llm-disabled | content_llm_enabled false skips the LLM, templates are used | ported | METADATA-70 | — |
| tag:PROMPTS | tuning-workflow | iterate prompts against real slabs | dropped | — | procedure |
| tag:PROMPTS | title-example-emdash | example title uses an em dash and a multiplication sign | superseded | — | title separator is the hyphen; migration cleanup |
+51
View File
@@ -0,0 +1,51 @@
# Coverage ledger — tag:TECH-SPEC-PIPELINE
Source `tag:TECH-SPEC-PIPELINE` (`docs/TECH-SPEC-PIPELINE.md` at tag `pre-simplification`).
Vetted 2026-09-18. Rules are CAPTURE, vectors are QUALITY. Doc retired (see migration TODOs).
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:TECH-SPEC-PIPELINE | invariants-determinism | pure function of pixels and user inputs; no network in the math | ported | CAPTURE-5 | — |
| tag:TECH-SPEC-PIPELINE | invariants-manual-authoritative | user-entered length, thickness, SKU, price always win | ported | METADATA-50 | — |
| tag:TECH-SPEC-PIPELINE | invariants-fallback-chain | every computed value has a defined fallback; never silently guesses | ported | CAPTURE-155 | — |
| tag:TECH-SPEC-PIPELINE | invariants-units | inches in 1/8 steps; sqft and bdft 2 decimals | ported | CAPTURE-70, CAPTURE-160 | — |
| tag:TECH-SPEC-PIPELINE | invariants-client-authoritative | all deterministic processing in the browser; server stores | ported | CAPTURE-135, APP-40 | — |
| tag:TECH-SPEC-PIPELINE | browser-compat-floor | iOS Safari, Android Chrome, desktop Chrome/Edge/Firefox; hard stop | ported | CAPTURE-10 | — |
| tag:TECH-SPEC-PIPELINE | load-bearing-apis | canvas or OffscreenCanvas, image decode/crop/encode, fetch | ported | CAPTURE-140 | — |
| tag:TECH-SPEC-PIPELINE | units-table | per-quantity source and rounding | ported | CAPTURE-70, CAPTURE-85, CAPTURE-90, REVIEW-25, CAPTURE-160 | — |
| tag:TECH-SPEC-PIPELINE | bdft-not-rounded-whole | bdft is never rounded up to whole board feet | ported | CAPTURE-90 | — |
| tag:TECH-SPEC-PIPELINE | pixels-hidden | pixel-to-inch scale is an implementation detail | dropped | — | internal detail |
| tag:TECH-SPEC-PIPELINE | bg-removal-load-bearing | the mask defines the measurement footprint; the eye is the validator | ported | CAPTURE-50 | — |
| tag:TECH-SPEC-PIPELINE | sheet-detect | 2-5 percent border strip, HSV green or black, else user picks | ported | CAPTURE-35 | — |
| tag:TECH-SPEC-PIPELINE | overlay-source-photo | overlay the mask on the source photo and confirm the edge | ported | CAPTURE-50 | — |
| tag:TECH-SPEC-PIPELINE | knobs-inline-live | knobs inline on capture, live re-run, persisted, no server round trip | ported | CAPTURE-45, CAPTURE-145, CAPTURE-150 | — |
| tag:TECH-SPEC-PIPELINE | knobs-four | sheet, sensitivity, edge offset, feather | superseded | CAPTURE-40 | controls are exactly Sheet and Sensitivity |
| tag:TECH-SPEC-PIPELINE | algorithms-floodfill | chroma key or threshold with border-connected flood fill | ported | CAPTURE-35, CAPTURE-41 | — |
| tag:TECH-SPEC-PIPELINE | bg-poc-client-u2net-deferred | client-only mask with retake; U2Net deferred, contract preserved | ported | CAPTURE-165 | — |
| tag:TECH-SPEC-PIPELINE | edge-quality-contiguous | the mask must be one contiguous slab contour, else retake | ported | CAPTURE-55 | — |
| tag:TECH-SPEC-PIPELINE | contour-length-axis | min-area bounding rect; long side is the length axis, prevailing length | ported | CAPTURE-60 | — |
| tag:TECH-SPEC-PIPELINE | axis-rotate-confirm | user rotates and confirms; nearly square picks the axis | ported | CAPTURE-60, CAPTURE-65 | — |
| tag:TECH-SPEC-PIPELINE | scale-formula | scale = longest_axis_px / user length | ported | CAPTURE-75 | — |
| tag:TECH-SPEC-PIPELINE | widths | sample every 6 inches perpendicular; min, max, average | ported | CAPTURE-80 | — |
| tag:TECH-SPEC-PIPELINE | sqft-formula | sqft = mask_pixels / scale squared / 144, 2 decimals | ported | CAPTURE-85 | — |
| tag:TECH-SPEC-PIPELINE | bdft-formula | bdft = sqft times thickness_in, 2 decimals | ported | CAPTURE-90 | — |
| tag:TECH-SPEC-PIPELINE | normalization-3-4-png | 3:4 portrait, transparent PNG, slab centered | ported | CAPTURE-95, CAPTURE-100 | — |
| tag:TECH-SPEC-PIPELINE | normalization-80-fill-1600 | 80 percent fill and 1600 px floor | superseded | CAPTURE-100, CAPTURE-105 | PoR is 90 percent fill and an 800 px floor |
| tag:TECH-SPEC-PIPELINE | normalization-every-photo | applies to every inventory photo | ported | CAPTURE-30, CAPTURE-110 | — |
| tag:TECH-SPEC-PIPELINE | dimension-overlay-v1_5 | auto-dimension overlay is v1.5, out of this spec | superseded | CAPTURE-120, CAPTURE-125 | the overlay is shipped |
| tag:TECH-SPEC-PIPELINE | pricing | species $/bdft, recommendation, override, no-rule behavior | ported | REVIEW-25, SETTINGS-35 | — |
| tag:TECH-SPEC-PIPELINE | constants-code | FILL_TARGET, ASPECT, OUTPUT_PX_MIN, WIDTH_SAMPLE, INCH_STEP, decimals | superseded | CAPTURE-100, CAPTURE-105 | fill and pixel floor superseded |
| tag:TECH-SPEC-PIPELINE | factory-bg-defaults | sheet auto, green hue/sat/val, black threshold | ported | CAPTURE-35, CAPTURE-41 | — |
| tag:TECH-SPEC-PIPELINE | tv1-green-sheet | interior green patch not touching the border survives; U2Net not invoked | ported | QUALITY-55 | — |
| tag:TECH-SPEC-PIPELINE | tv2-black-sheet | dark interior wood survives; flood fill isolates border-connected regions | ported | QUALITY-60 | — |
| tag:TECH-SPEC-PIPELINE | tv3-scale-sqft-bdft | 96 in, 1.5 in, 0.64 sqft yields 0.96 bdft | ported | QUALITY-65 | — |
| tag:TECH-SPEC-PIPELINE | tv4-width-samples | 6 inch stations on a 96 inch axis report min, max, average | ported | QUALITY-70 | — |
| tag:TECH-SPEC-PIPELINE | tv5-angled-end | one square end and one 45 degree cut; axis follows prevailing length | ported | QUALITY-75 | — |
| tag:TECH-SPEC-PIPELINE | tv6-crop | 3:4, fill at extremes, transparent PNG, shorter side floor | ported | QUALITY-80 | PoR uses 90 percent fill and the 800 px floor |
| tag:TECH-SPEC-PIPELINE | tv7-too-small | undersized source warns, is not upscaled, not publishable until retake | ported | QUALITY-85 | PoR floor is 800 px |
| tag:TECH-SPEC-PIPELINE | tv8-pricing | 0.96 bdft at 12.50 gives 12.00; override stored | ported | QUALITY-90 | — |
| tag:TECH-SPEC-PIPELINE | tv9-thickness-range | 1 in rounds up into the synced Woo thickness band | ported | QUALITY-95 | — |
| tag:TECH-SPEC-PIPELINE | tv10-rounding | half-up 2 decimal rounding cases | ported | QUALITY-100 | — |
| tag:TECH-SPEC-PIPELINE | assumptions | top-down first photo, user length, declared thickness, projected area | ported | CAPTURE-20, CAPTURE-70, CAPTURE-85, CAPTURE-90, CAPTURE-135 | — |
| tag:TECH-SPEC-PIPELINE | cross-reference-table | cross-references to other docs | dropped | — | stale refs; migration |
| tag:TECH-SPEC-PIPELINE | issue4-version-pins | exact minimum version pins tracked under issue #4 | dropped | — | tracked as an issue, not a requirement |
+29
View File
@@ -0,0 +1,29 @@
# Coverage ledger — tag:TEST-SPEC
Source `tag:TEST-SPEC` (`docs/TEST-SPEC.md` at tag `pre-simplification`). Rows seeded by the
settings/auth/health pilot 2026-09-18. TEST-SPEC is reconciled LAST, against a finished PoR.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:TEST-SPEC | GC-1 | SLAB-UAT-* creates a Woo draft regardless of woo_create_status | ported | PUBLISH-10 | — |
| tag:TEST-SPEC | GC-2 | duplicate SKU returns 409 with edit_sku and open_existing | ported | PUBLISH-15 | — |
| tag:TEST-SPEC | GC-3 | test-woo returns ok with taxonomy and always resyncs on success | ported | SETTINGS-40 | — |
| tag:TEST-SPEC | GC-4 | WOO_BASE_URL compose-only, GET read-only, PUT rejects a write with 422 | ported | SETTINGS-85 | — |
| tag:TEST-SPEC | GC-5 | FastAPI refuses to start on missing or http WOO_BASE_URL | ported | SETTINGS-10 | — |
| tag:TEST-SPEC | W-3 | taxonomy anchor unchanged on no-op, bumps only on stored-subset hash change | ported | SETTINGS-55 | sync and rebuild live in SETTINGS-50 |
| tag:TEST-SPEC | W-4 | test-woo always runs a taxonomy resync after a successful test | duplicate | SETTINGS-40 | same rule as GC-3 |
| tag:TEST-SPEC | AES-1 | credential encrypt/decrypt round-trips; ciphertext never appears in GET | ported | SETTINGS-75, QUALITY-125 | — |
| tag:TEST-SPEC | AES-2 | missing SLAB_AES_KEY refuses startup, no plaintext fallback | ported | SETTINGS-25 | — |
| tag:TEST-SPEC | API-10 | test-woo fails closed on missing credentials or non-HTTPS URL | ported | SETTINGS-80 | — |
| tag:TEST-SPEC | FUND-21 | 401/400/404 mapped to an actionable error, not raw passthrough | ported | APP-50 | — |
| tag:TEST-SPEC | H-1 | health 200 with woo_reachable false when credentials are not configured | ported | APP-45 | — |
| tag:TEST-SPEC | INS-1 | health non-200 on DB or volume failure; woo_reachable false when the store is unreachable | ported | APP-45 | — |
| tag:TEST-SPEC | UIE-8 | Settings screen: WP creds and test-woo, inference and test, pricing, brand/GEO, create status, read-only URL | ported | SETTINGS-5, SETTINGS-15, SETTINGS-20, SETTINGS-30, SETTINGS-35, SETTINGS-65 | screen composition itself belongs to the contract/UX docs |
| tag:TEST-SPEC | OPS-3 | compose health, test-woo ok, create status draft at deploy | ported | QUALITY-110 | — |
| tag:TEST-SPEC | FUND-3, FUND-5, FUND-6, FUND-7 | keyboard tab order, visible focus ring, 320 px reflow | ported | APP-60 | found by TEST-SPEC reconciliation |
| tag:TEST-SPEC | FUND-24 | no secret material in logs | ported | APP-65 | found by TEST-SPEC reconciliation |
| tag:TEST-SPEC | V-3, API-8 | shared validation module hash, 412 | dropped | — | validation module ruled cut |
| tag:TEST-SPEC | C2-2 | previous_response_id, per-slab thread | superseded | — | thread work out of MVP |
| tag:TEST-SPEC | UI-1, UIE-9, UIE-10 | four knobs | superseded | CAPTURE-40 | two controls |
| tag:TEST-SPEC | UIE-1, E2E-4 | manual override of computed fields | superseded | REVIEW-30, REVIEW-40 | computed fields read-only |
| tag:TEST-SPEC | TV-6, TV-7, E2E-5 | 80 percent fill, 1600 px | superseded | CAPTURE-100, CAPTURE-105 | 90 percent, 800 px |
+78
View File
@@ -0,0 +1,78 @@
# Coverage ledger — tag:UX and tag:UX-DESIGN
Sources: `tag:UX` (`docs/UX.md`, SIGNED presentation spec) and `tag:UX-DESIGN`
(`docs/UX-DESIGN.md`, non-normative wireframes). Walked 2026-09-18. UX migrates to
`docs/contracts/UX.md`; UX-DESIGN is retired.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| tag:UX | jobs | five jobs: photo to listing, practice drafts, retake, fill fields, publish | ported | CAPTURE-5, PUBLISH-10, CAPTURE-50, METADATA-50, PUBLISH-5 | — |
| tag:UX | photos-1-to-5 | 1 to 5 inventory photos | superseded | CAPTURE-25 | no cap |
| tag:UX | no-calibration-photos | there are no calibration photos; only inventory photos exist | superseded | CAPTURE-25, CAPTURE-30 | the calibration photo exists |
| tag:UX | first-photo-topdown | first photo top-down, lens parallel to the broad face | ported | CAPTURE-20 | — |
| tag:UX | mask-overlay-only-check | the overlay on the source photo is the only quality check | ported | CAPTURE-50 | — |
| tag:UX | knobs-four | sheet, sensitivity, edge offset, feather | superseded | CAPTURE-40 | controls are exactly Sheet and Sensitivity |
| tag:UX | knobs-live-persist | live re-run, no apply step, no server round trip, persisted | ported | CAPTURE-45, CAPTURE-145, CAPTURE-150 | — |
| tag:UX | u2net-deferred | server matting deferred, no control | ported | CAPTURE-165 | — |
| tag:UX | length-axis-confirm | bounding rect and axis, rotate, nearly square choice | ported | CAPTURE-60, CAPTURE-65 | — |
| tag:UX | numbers-manual | length, thickness, SKU entered by hand | ported | CAPTURE-70 | — |
| tag:UX | widths-min-max-avg | widths every 6 inches; min, max, average | ported | CAPTURE-80 | — |
| tag:UX | sqft-bdft-2dp | square feet and board feet to two decimals | ported | CAPTURE-85, CAPTURE-90 | — |
| tag:UX | bdft-identity | one square foot at one inch is one board foot, no divide-by-12 | ported | CAPTURE-90 | — |
| tag:UX | server-no-recompute | computed in the browser and stored as sent | ported | CAPTURE-135, APP-40 | — |
| tag:UX | photo-prep-80-1600 | 3:4 at 80 percent fill, shorter side 1600 or more | superseded | CAPTURE-100, CAPTURE-105 | PoR is 90 percent fill and an 800 px floor |
| tag:UX | continue-calibrated | Continue uploads originals, PNGs, numbers; status calibrated | ported | CAPTURE-135, APP-5 | — |
| tag:UX | vision-fill-threshold | Call 1 pre-fills at or above 0.7 after the draft uploads | ported | METADATA-35, METADATA-45 | — |
| tag:UX | inference-off-empty | with inference off every field starts empty | ported | METADATA-70 | — |
| tag:UX | inference-never-blocks | inference never blocks publish and never auto-publishes | ported | METADATA-75 | — |
| tag:UX | call2-not-auto | Call 2 fires only when the owner taps it | ported | METADATA-55 | — |
| tag:UX | sku-charset | SKU `[A-Z0-9-]{3,24}` | ported | REVIEW-45 | PoR allows alphanumeric (lowercase too) |
| tag:UX | length-thickness-editable | length and thickness editable in review | ported | REVIEW-40 | — |
| tag:UX | calc-fields-override | square feet, board feet, widths have a manual override path | superseded | REVIEW-30, REVIEW-40 | calculated fields are read-only |
| tag:UX | species-exactly-one | exactly one species leaf from the synced list | ported | METADATA-10 | — |
| tag:UX | wood-categories-1plus | at least one wood category | ported | METADATA-10 | — |
| tag:UX | edge-one | one edge type | ported | METADATA-15 | — |
| tag:UX | figure-1plus | at least one figure term | ported | METADATA-15 | — |
| tag:UX | grade-1plus | at least one grade term | superseded | METADATA-15 | grade is exactly one |
| tag:UX | thickness-band-roundup | thickness band rounds up into the synced Woo range | ported | METADATA-15 | — |
| tag:UX | moisture-default | moisture defaults kiln-dried, never inferred | ported | METADATA-15 | — |
| tag:UX | fig-tags-1plus | at least one fig-* tag | superseded | METADATA-30 | tags are optional |
| tag:UX | feat-tags-0plus | zero or more feat-* tags | ported | METADATA-30 | — |
| tag:UX | price-reco-override | recommendation from species $/bdft, override sticks | ported | REVIEW-25 | — |
| tag:UX | price-no-rule-manual | no rule leaves the price empty; the owner types it | ported | REVIEW-25 | price is required before create |
| tag:UX | title-desc-not-required-to-ready | title, short title, description not required to reach ready | superseded | REVIEW-10 | they are required on the product |
| tag:UX | templates-always-run | templates always run and inject the numbers | superseded | METADATA-70, METADATA-80 | the model writes when Call 2 runs; template is the fallback |
| tag:UX | inline-nudges | per-field inline nudge; no single submit-time list | ported | REVIEW-20 | — |
| tag:UX | generate-text-button | Generate text runs Call 2 and fills title, short title, description | ported | METADATA-55 | — |
| tag:UX | draft-vs-live | `woo_create_status` default draft; SLAB-UAT-* always draft | ported | PUBLISH-10, SETTINGS-65 | — |
| tag:UX | published-not-live | published means the store create succeeded, not that it is live | ported | PUBLISH-50 | — |
| tag:UX | publish-success | success cleans up the local draft and photos | ported | PUBLISH-25 | — |
| tag:UX | publish-dup-sku | duplicate SKU on the field, edit SKU or open existing | ported | PUBLISH-15 | — |
| tag:UX | publish-stale-value | stale value on the field, pick from the current list | ported | PUBLISH-20 | — |
| tag:UX | publish-store-unreachable | plain message, no status number or stack trace, retry | ported | PUBLISH-30, PUBLISH-35, PUBLISH-36, PUBLISH-38 | — |
| tag:UX | publish-log-retry | the server logs every attempt; retry from the same screen | ported | PUBLISH-30 | — |
| tag:UX | browser-matrix | iOS Safari, Android Chrome, desktop Chrome/Edge/Firefox | ported | CAPTURE-10 | — |
| tag:UX | unsupported-hard-stop | hard stop with an update or switch link, no polyfill | ported | CAPTURE-10 | — |
| tag:UX | deferred-features | photo quality, OCR, ruler, server measuring, U2Net, offline deferred | ported | CAPTURE-15, CAPTURE-165 | — |
| tag:UX | where-jobs-live-table | where each job lives | dropped | — | stale refs; migration |
| tag:UX-DESIGN | wireframes-non-normative | wireframes are non-normative and defer to UX.md | dropped | — | non-normative by its own text |
| tag:UX-DESIGN | settings-screen | settings fields, test connections, pricing, brand/GEO | ported | SETTINGS-5, SETTINGS-20, SETTINGS-30, SETTINGS-35, SETTINGS-65 | — |
| tag:UX-DESIGN | settings-vision-content-flags | Enable Vision and Enable Content default off | ported | SETTINGS-90 | — |
| tag:UX-DESIGN | settings-test-inference | test connection shows stateful/stateless/fail | ported | SETTINGS-45 | mode kept as diagnostic; Call 2 does not use thread IDs |
| tag:UX-DESIGN | generate-text-availability | Generate text appears only when content generation is enabled and reachable; disabled when the service is down | ported | METADATA-110 | — |
| tag:UX-DESIGN | settings-reset-knobs | reset capture knobs to default | ported | CAPTURE-145 | — |
| tag:UX-DESIGN | first-run-guidance | first-run card | dropped | — | presentation detail; fold into the UX contract |
| tag:UX-DESIGN | capture-knobs-four | four knobs on capture | superseded | CAPTURE-40 | two knobs |
| tag:UX-DESIGN | type-values-screen | SKU, length, thickness, computed values, done | ported | CAPTURE-70, CAPTURE-85, CAPTURE-90 | — |
| tag:UX-DESIGN | calc-values-override | typed number wins over the computed value | superseded | REVIEW-30, REVIEW-40 | calculated fields are read-only |
| tag:UX-DESIGN | review-screen-fields | all store fields on review | ported | REVIEW-5, METADATA-10, METADATA-15, METADATA-30, REVIEW-25 | minus grade/fig cardinality |
| tag:UX-DESIGN | review-grade-fig-mandatory | grade and fig-* mandatory | superseded | METADATA-15, METADATA-30 | grade exactly one; tags optional |
| tag:UX-DESIGN | ai-badge | AI badge on Call 1-filled fields | dropped | — | presentation detail; fold into the UX contract |
| tag:UX-DESIGN | per-field-nudges | per-field nudges as the user works | ported | REVIEW-20 | — |
| tag:UX-DESIGN | submit-time-validation | submit-time validation fires after all fields are filled | superseded | REVIEW-20 | no single submit-time list |
| tag:UX-DESIGN | title-desc-screen | separate Title/Description screen, exit review returns to calibrated | ported | APP-10, REVIEW-40 | — |
| tag:UX-DESIGN | publish-states | publishing, success, failed with retry | ported | PUBLISH-5, PUBLISH-25, PUBLISH-30 | — |
| tag:UX-DESIGN | error-states | mask, axis, too-small, duplicate SKU, stale value, unreachable | ported | CAPTURE-55, CAPTURE-105, PUBLISH-15, PUBLISH-20, PUBLISH-30 | — |
| tag:UX-DESIGN | vision-off-below-threshold | empty fields with nudges when vision is off or below threshold | ported | METADATA-45, METADATA-70 | — |
| tag:UX-DESIGN | browser-gate-message | hard-stop message says update Safari or Chrome | superseded | CAPTURE-10 | matrix includes PC browsers |
| tag:UX-DESIGN | uat-cases-derived | fourteen UAT cases derived from wireframes | duplicate | REVIEW-20, PUBLISH-10, PUBLISH-15, PUBLISH-20, METADATA-45, CAPTURE-105 | TEST-SPEC owns the test plan |
+59
View File
@@ -0,0 +1,59 @@
# Coverage ledger — UAT-PRACTICE.md
Source `cur:UAT-PRACTICE` (`docs/UAT-PRACTICE.md`, role: practice). Walked 2026-09-18.
Four conflicts were ruled superseded; the rest port to the PoR.
| Source | Atom | Requirement | Disposition | PoR ID | Rationale |
|---|---|---|---|---|---|
| cur:UAT-PRACTICE | inventory-filled | deploy/INVENTORY filled before deploy | ported | OPS-15 | — |
| cur:UAT-PRACTICE | lan-tailscale | reachable over LAN/Tailscale | ported | OPS-5 | — |
| cur:UAT-PRACTICE | https-only | HTTPS only, valid cert | ported | OPS-5 | — |
| cur:UAT-PRACTICE | health-passes | health endpoint returns ok | ported | APP-30 | — |
| cur:UAT-PRACTICE | store-url-set | WOO_BASE_URL in host .env, https | ported | SETTINGS-5 | — |
| cur:UAT-PRACTICE | wp-store-https | WordPress store must already be on HTTPS | ported | SETTINGS-10, SETTINGS-15 | — |
| cur:UAT-PRACTICE | dedicated-low-priv-user | dedicated low-privilege WP user | ported | SETTINGS-15 | — |
| cur:UAT-PRACTICE | generate-password | generate application password in WP profile | dropped | — | procedure, not a requirement |
| cur:UAT-PRACTICE | enter-creds-encrypted | username + application password in Settings, server-encrypted | ported | SETTINGS-20 | — |
| cur:UAT-PRACTICE | test-woo-resync | test-woo reports ok and resyncs taxonomy | ported | SETTINGS-40 | — |
| cur:UAT-PRACTICE | fastapi-sole-caller | FastAPI is the only store caller | ported | APP-25 | — |
| cur:UAT-PRACTICE | rotate-creds | rotate application password then test-woo | duplicate | SETTINGS-40 | rotation is procedure; the verification is test-woo |
| cur:UAT-PRACTICE | sku-prefix | practice SKU starts with `SLAB-UAT-` | ported | PUBLISH-10 | — |
| cur:UAT-PRACTICE | always-draft | `SLAB-UAT-*` always creates a Woo draft | ported | PUBLISH-10 | — |
| cur:UAT-PRACTICE | create-status-default-draft | `woo_create_status` defaults to draft | ported | SETTINGS-65 | — |
| cur:UAT-PRACTICE | customers-never-see | a draft is hidden from the storefront | ported | PUBLISH-10, PUBLISH-50 | — |
| cur:UAT-PRACTICE | supported-browsers | iOS Safari, Android Chrome, desktop Chrome/Edge/Firefox; hard stop | ported | CAPTURE-10 | — |
| cur:UAT-PRACTICE | matrix-issue-refs | signed matrix and issue #4 provenance | dropped | — | stale provenance, not a requirement |
| cur:UAT-PRACTICE | photo-count-1-to-5 | take 1 to 5 photos | superseded | CAPTURE-25 | PoR is one or more; no cap in code |
| cur:UAT-PRACTICE | first-photo-topdown | first photo top-down, lens parallel | ported | CAPTURE-20 | — |
| cur:UAT-PRACTICE | four-knobs | Sheet, Sensitivity, Edge offset, Feather | superseded | CAPTURE-40 | controls are exactly Sheet and Sensitivity |
| cur:UAT-PRACTICE | confirm-mask | confirm the mask | ported | CAPTURE-50 | — |
| cur:UAT-PRACTICE | length-axis | bounding rectangle, rotate, nearly square choice | ported | CAPTURE-60, CAPTURE-65 | — |
| cur:UAT-PRACTICE | enter-length-thickness-sku | length/thickness 1/8 inch, SKU typed | ported | CAPTURE-70 | — |
| cur:UAT-PRACTICE | computed-numbers | sqft, bdft, widths, bdft identity | ported | CAPTURE-80, CAPTURE-85, CAPTURE-90 | — |
| cur:UAT-PRACTICE | continue-upload-status | Continue uploads originals, PNGs, numbers; status calibrated | ported | APP-5, CAPTURE-135 | — |
| cur:UAT-PRACTICE | species-exactly-one | pick exactly one species | ported | METADATA-10 | — |
| cur:UAT-PRACTICE | wood-categories | pick at least one wood category | ported | METADATA-10 | — |
| cur:UAT-PRACTICE | grade-at-least-one | at least one grade | superseded | METADATA-15 | grade is exactly one |
| cur:UAT-PRACTICE | figure-at-least-one | at least one figure | ported | METADATA-15 | — |
| cur:UAT-PRACTICE | thickness-band-roundup | thickness band rounds up | ported | METADATA-15 | — |
| cur:UAT-PRACTICE | moisture-default | moisture default kiln-dried | ported | METADATA-15 | — |
| cur:UAT-PRACTICE | fig-tags-at-least-one | pick at least one `fig-*` tag | superseded | METADATA-30 | tags are optional |
| cur:UAT-PRACTICE | feat-tags-zero-or-more | zero or more `feat-*` tags | ported | METADATA-30 | — |
| cur:UAT-PRACTICE | price-reco-override | recommendation from species `$/bdft`, override sticks | ported | REVIEW-25 | — |
| cur:UAT-PRACTICE | price-missing-rate | no rate starts empty, type it, publish allowed | ported | REVIEW-25 | price required before create; manual entry when no rate |
| cur:UAT-PRACTICE | title-description-templates | type or leave for templates; templates inject numbers | ported | METADATA-70, REVIEW-10 | — |
| cur:UAT-PRACTICE | inline-nudges-ready | inline nudge; cannot reach ready until filled | ported | REVIEW-20 | — |
| cur:UAT-PRACTICE | sku-check-create | server checks SKU, creates if new | ported | PUBLISH-5 | — |
| cur:UAT-PRACTICE | success-cleanup | success message, local draft and photos gone, status published | ported | PUBLISH-25, PUBLISH-50 | — |
| cur:UAT-PRACTICE | published-not-live | published means store create succeeded, not live | ported | PUBLISH-50 | — |
| cur:UAT-PRACTICE | store-draft-fields | confirm draft status and fields in the store | ported | PUBLISH-10, PUBLISH-40, PUBLISH-45, PUBLISH-55, METADATA-15 | — |
| cur:UAT-PRACTICE | storefront-hidden | not visible on the live storefront | ported | PUBLISH-10, PUBLISH-50 | — |
| cur:UAT-PRACTICE | repeat-pc | repeat the walk on a desktop browser | ported | CAPTURE-10 | — |
| cur:UAT-PRACTICE | pass-fail-checklist | pass/fail checks table | duplicate | REVIEW-5, PUBLISH-10, CAPTURE-90 | restates rows above |
| cur:UAT-PRACTICE | duplicate-sku-recovery | duplicate SKU recovery, edit or open existing | ported | PUBLISH-15 | — |
| cur:UAT-PRACTICE | fail-no-success | no success message, plain error, server log, retry | ported | PUBLISH-30, PUBLISH-35, PUBLISH-37 | — |
| cur:UAT-PRACTICE | fail-stale-value | value no longer valid, pick from current list | ported | PUBLISH-20, REVIEW-35 | — |
| cur:UAT-PRACTICE | fail-store-unreachable | store unreachable, plain message, retry | ported | PUBLISH-30, PUBLISH-36, PUBLISH-38 | — |
| cur:UAT-PRACTICE | cleanup-draft | leave or delete the UAT draft; app does not delete store products | dropped | — | procedure |
| cur:UAT-PRACTICE | final-poc-publish | final POC publish is a separate gated step | dropped | — | scope/procedure |
| cur:UAT-PRACTICE | where-rules-live | "where each rule lives" table | dropped | — | stale doc refs; migration |