01aa4c52c3
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/.
153 lines
8.1 KiB
Markdown
153 lines
8.1 KiB
Markdown
# Test spec contract
|
||
|
||
Status: SPEC · 2026-09-18 · reconciled against the finished PoR.
|
||
Defines the affirmative test bar. It cites requirement IDs; `docs/REQUIREMENTS.md` is normative.
|
||
The human walkthrough is `docs/UAT-PRACTICE.md`.
|
||
|
||
## Requirements impact
|
||
|
||
| Requirement | Impact on this design |
|
||
|---|---|
|
||
| QUALITY-5, QUALITY-10, QUALITY-15 | TDD for the deterministic core; vectors TV-1..TV-10 |
|
||
| QUALITY-20, QUALITY-35, QUALITY-50 | inference-off suite, Woo-mock integration, Compose UI E2E |
|
||
| QUALITY-25, QUALITY-30 | evidence rules; Ty owns gate exit |
|
||
| QUALITY-40, QUALITY-45 | property checks and bdft identity |
|
||
| QUALITY-55 .. QUALITY-100 | pipeline vectors |
|
||
| QUALITY-105, QUALITY-110 | dishonest proxies; M3 exit evidence |
|
||
| QUALITY-115, QUALITY-120, QUALITY-125 | browser E2E, no raw codes, AES round-trip |
|
||
| APP-45, APP-55, APP-60, APP-65 | health, logging, accessibility, log redaction |
|
||
| SETTINGS-80, PUBLISH-30/31/35 | failure handling under test |
|
||
|
||
## 1. Layers and harness
|
||
|
||
| Layer | Written | Location | Rule source |
|
||
|---|---|---|---|
|
||
| Unit | TDD before the code exists | `backend/tests/unit/`, `frontend/src/__tests__/` | deterministic core and validation |
|
||
| API contract | with the feature | `backend/tests/contract/` (pytest + httpx TestClient) | `docs/contracts/API.md` |
|
||
| Integration | with the feature | `backend/tests/integration/` (respx Woo mock) | `docs/contracts/WOO-API.md`, `docs/contracts/CONTENT-WOO.md` |
|
||
| UI / E2E | with the feature | `frontend/e2e/` (Playwright, Compose stack, mocked Woo) | `docs/contracts/UX.md` |
|
||
| Ops | with deploy config | `deploy/tests/` (shell) | `deploy/` |
|
||
|
||
Allowed results are `pass`, `fail`, `not run`, and optionally `blocked`. Every `pass` or `fail`
|
||
needs runner evidence; no evidence means `not run`. The only bug log is Gitea issues. Ty reads raw
|
||
results and owns gate exit; an agent never declares a gate green (`QUALITY-25`, `QUALITY-30`).
|
||
|
||
## 2. Fundamentals (FUND)
|
||
|
||
- FUND-1..4 — no browser/DOM/network deps in pure tests; semantic selectors; real Tab navigation;
|
||
reactivity flush. (test practice)
|
||
- FUND-5, FUND-6, FUND-7 — Tab order, 320 px reflow, visible focus ring → `APP-60`
|
||
- FUND-8..11 — app factory per test, lifespan, override cleanup, no real network (test practice)
|
||
- FUND-12, FUND-13, FUND-16 — FK and constraint enforcement, migration integrity (test practice)
|
||
- FUND-14 — WAL with no stale reads (test practice)
|
||
- FUND-15 — illegal status transitions rejected → `APP-5`
|
||
- FUND-17 — fresh nonce per encrypt; tamper fails → `SETTINGS-25`
|
||
- FUND-18 — ciphertext absent from GET; only configured booleans → `SETTINGS-75`
|
||
- FUND-19 — missing key refuses startup → `SETTINGS-25`
|
||
- FUND-20 — Basic Auth with application passwords over HTTPS, not consumer keys → `SETTINGS-15`
|
||
- FUND-21 — 401/400/404 mapped, not passed raw → `APP-50`
|
||
- FUND-22 — pre-create SKU lookup, duplicate race → `PUBLISH-15`
|
||
- FUND-23 — timeouts/network errors graceful, no stack → `PUBLISH-30`, `PUBLISH-35`
|
||
- FUND-24 — no secret material in logs → `APP-65`
|
||
- FUND-25 — HTTPS, health through proxy, port collision → `OPS-5`, `OPS-15`, `OPS-20`
|
||
|
||
## 3. Deterministic vectors (TV)
|
||
|
||
- TV-1 — green patch not touching the border survives; U2Net not invoked → `QUALITY-55`
|
||
- TV-2 — dark interior wood survives; flood fill isolates border-connected regions → `QUALITY-60`
|
||
- TV-3 — 96 in, 1.5 in, 0.64 sqft yields 0.96 bdft; 1 sqft at 1 in equals 1 bdft → `QUALITY-65`
|
||
- TV-4 — 6 in stations on a 96 in axis report min, max, average → `QUALITY-70`
|
||
- TV-5 — one square end, one 45 degree cut; axis follows prevailing length → `QUALITY-75`
|
||
- TV-6 — 3:4 crop, 90 percent fill at extremes, transparent PNG, 800 px floor → `QUALITY-80`
|
||
- TV-7 — undersized source warns, is not upscaled, not publishable until retake → `QUALITY-85`
|
||
- TV-8 — 0.96 bdft at 12.50 gives 12.00; a 150.00 override is stored → `QUALITY-90`
|
||
- TV-9 — 1 in rounds up into the synced Woo thickness band → `QUALITY-95`
|
||
- TV-10 — half-up 2 decimal rounding cases → `QUALITY-100`
|
||
|
||
Validation:
|
||
- SKU charset 3–24 alphanumeric and hyphen → `REVIEW-45`
|
||
- title/short_description/description within limits → `REVIEW-50`
|
||
|
||
AES:
|
||
- round-trip decrypt; ciphertext never in GET → `QUALITY-125`, `SETTINGS-75`
|
||
- missing key refuses startup → `SETTINGS-25`
|
||
|
||
API contract / health / draft:
|
||
- `GET /api/health` shape and non-200 on DB/volume failure → `APP-45`
|
||
- `POST /api/v1/slabs` multipart returns 201 calibrated → `docs/contracts/API.md`, `APP-5`
|
||
|
||
## 4. Gate C and Woo
|
||
|
||
- `SLAB-UAT-*` creates a draft regardless of setting → `PUBLISH-10`
|
||
- duplicate SKU before create returns 409 with `edit_sku` / `open_existing` → `PUBLISH-15`
|
||
- test-woo ok, resyncs taxonomy → `SETTINGS-40`
|
||
- WOO_BASE_URL read-only, PUT rejected → `SETTINGS-5`, `SETTINGS-85`
|
||
- startup refuses missing or http WOO_BASE_URL → `SETTINGS-10`
|
||
- Woo create stores `woo_product_id`, purges images → `PUBLISH-25`
|
||
- Woo 409 mapped to field recovery, draft retained → `PUBLISH-15`
|
||
- taxonomy anchor unchanged on no-op, bumps on change → `SETTINGS-55`
|
||
- failed publish marks failed, keeps photos, writes sync_log, retries to success → `PUBLISH-30`
|
||
|
||
## 5. Inference
|
||
|
||
- with inference off: Call 1 skipped, no inference calls, suite passes → `METADATA-75`, `QUALITY-20`
|
||
- test-inference returns ok, mode stateful/stateless, vision_capable → `SETTINGS-45`
|
||
- test-inference fail blocks Call 2 only → `SETTINGS-45`
|
||
- Call 1 at or above 0.7 pre-fills; below stays empty; override wins → `METADATA-45`, `METADATA-50`
|
||
- Call 1 sends clean processed photos at 1024, synced taxonomy, user metadata → `METADATA-35`
|
||
- Call 2 user-triggered only, fresh full context → `METADATA-55`, `METADATA-60`
|
||
- model does not invent dimensions → `METADATA-65`
|
||
- generation logged → `METADATA-66`
|
||
- prompts stored with revisions → `METADATA-105`
|
||
|
||
## 6. UI end-to-end (UIE / E2E)
|
||
|
||
- capture controls, overlay, axis, numbers, ready gates → `CAPTURE-40`, `CAPTURE-45`, `CAPTURE-50`,
|
||
`CAPTURE-60`, `CAPTURE-70`, `CAPTURE-80`, `CAPTURE-85`, `CAPTURE-90`, `REVIEW-5`, `REVIEW-20`
|
||
- review pre-fill and editability → `METADATA-45`, `REVIEW-40`
|
||
- duplicate SKU, stale value, success, failure messages → `PUBLISH-15`, `PUBLISH-20`, `PUBLISH-25`,
|
||
`PUBLISH-30`, `PUBLISH-35`
|
||
- inference-off content path, Generate text disabled → `METADATA-70`, `METADATA-110`
|
||
- settings screen and read-only URL → `SETTINGS-5`, `SETTINGS-15`, `SETTINGS-20`, `SETTINGS-30`,
|
||
`SETTINGS-35`, `SETTINGS-65`
|
||
- cross-browser capture through publish → `QUALITY-115`
|
||
|
||
## 7. API surface
|
||
|
||
- revisions and conflict → `APP-20`
|
||
- PUT stores derived, no recompute → `APP-40`
|
||
- secrets absent from GET → `SETTINGS-75`
|
||
- infer-taxon/content 202 and poll; timeout → `METADATA-35`, `METADATA-115`
|
||
- publish preconditions → `REVIEW-5`
|
||
- taxonomy sync, anchor, cache retention → `SETTINGS-50`, `SETTINGS-55`
|
||
- delete soft, published undeletable → `docs/contracts/API.md`
|
||
- test-woo fails closed → `SETTINGS-80`
|
||
- taxonomy re-pull and 1 hour publish refresh → `SETTINGS-60`
|
||
- species picker synced only → `METADATA-5`
|
||
|
||
## 8. Ops and instrumentation
|
||
|
||
- compose health, inventory, test-woo, draft status → `OPS-15`, `SETTINGS-40`, `SETTINGS-65`, `APP-45`
|
||
- backup and restore retention and cycle → `OPS-30`, `OPS-35`
|
||
- health non-200 on DB/volume, `woo_reachable` false → `APP-45`
|
||
- request id in logs → `APP-55`
|
||
- inference_log and sync_log written → `METADATA-66`, `PUBLISH-30`
|
||
|
||
## 9. Purged cases
|
||
|
||
Removed because the behavior was superseded: four-knob cases (edge offset, feather), the shared
|
||
validation module and its 412 path, `previous_response_id` and the per-slab thread, "inventory
|
||
photos" as the Call 1 input, prompt files edited without restart, 80 percent / 1600 px crop values,
|
||
and manual override of the computed fields.
|
||
|
||
## 10. New cases
|
||
|
||
- keyboard tab order, focus ring, and 320 px reflow → `APP-60`
|
||
- no secret material in any log output → `APP-65`
|
||
|
||
## 11. Rules that do not change
|
||
|
||
Inference is optional and the full suite passes with it off. `bdft = sqft × thickness_in`, no
|
||
divide-by-12. The client is authoritative for deterministic math; the server stores the numbers.
|
||
No new product locks live in this document.
|