Files
SlabUploader/docs/contracts/TEST-SPEC.md
Ty 01aa4c52c3 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/.
2026-09-18 21:02:06 -07:00

8.1 KiB
Raw Permalink Blame History

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.