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:
@@ -0,0 +1,152 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user