Files
SlabUploader/docs/M1-POR.md
T
Ty 92d1a7ec5e docs(m1): plan of record — TDD card breakdown, UAT deployment, fixtures, worker dispatch
- docs/M1-POR.md: scope, TDD method, 6-card breakdown, deployment POR,
  test plan, real-slab fixtures, dev/QA worker dispatch (.202:8081 text,
  .202:8082 vision; one task per endpoint)
- docs/CAPTURE.md: input photo (JPEG + HEIC fallback), 200KB soft goal
- deploy/README.md: Milestone 1 UAT deployment POR (one container, LAN URL)
- tests/fixtures/: 3 black-sheet slab photos + calibration records
  (152422 28x2.25 irregular, 155818 21x1.75, 155754 21x1.75)
2026-09-13 22:37:19 -07:00

7.0 KiB
Raw Blame History

Milestone 1 — Plan of Record (POR)

Decisions captured as they are made. This is the working plan for implementing and UAT-ing Milestone 1. It is the source of truth for scope, order, and dispatch; the spec detail lives in docs/CAPTURE.md and docs/PRODUCT.md.

Scope

Implement Milestone 1 — Capture only (see AGENTS.md). Browser-only, inference-free, no backend, no Woo create. Milestones 2–4 are out of scope.

Method — TDD (non-negotiable)

Every card is delivered test-first per the test-driven-development skill:

NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
  • Red-Green-Refactor, tracer-bullet: one behavior slice at a time (RED→GREEN→REFACTOR), not all-tests-then-all-code.
  • Verify RED (watch it fail for the right reason) and Verify GREEN (it passes + full suite stays green) are mandatory before the card is done.
  • Code written before a failing test is deleted and redone — not kept as "reference."
  • The deterministic core (math + PNG contract) is unit-tested in a browser-runnable JS suite; UI behaviors are tested with Playwright against the fixtures.
  • A card is not complete until: every new function has a test, each test was seen failing first, the full suite passes with pristine output.

Card breakdown (implementation order)

Each card follows TDD. "Define" = write the failing tests (RED); "Build" = minimal code to pass (GREEN); "Refactor" = clean up keeping green.

  1. Scaffold + Dockerfile + test harness — SvelteKit project with the browser-only M1 runtime (Web Worker, canvas/OffscreenCanvas, IndexedDB via idb-keyval), frontend/Dockerfile, and the test harness (JS unit runner + Playwright web).
    • TDD note: this card establishes the harness itself (a smoke test that runs and fails, then passes) so every later card has a place to be RED/GREEN.
  2. Deterministic core — the pure math + PNG-encode functions.
    • RED: unit tests for scale, sqft, bdft, width sampling, 1/8″ stepping, rounding, and the PNG contract (3:4, 8-bit RGBA, 80% fill, ≥1600px floor, undersized→retake). Run on the fixtures' calibration records.
    • GREEN/REFACTOR: implement to pass; core is authoritative and server-less.
  3. Capture + Mask — Add photo (JPEG; HEIC→"retake as JPEG" notice), green/black key, four knobs, debounced recompute, mask approve.
    • RED: Playwright — load fixture, key sheet, approve; empty-mask blocks approve; HEIC shows the notice.
    • GREEN/REFACTOR: build the Mask state to pass.
  4. Length axis — min-area bounding rectangle + long-side axis, user rotate, approve.
    • RED: Playwright — rect drawn from the approved mask, axis on long side, rotate, approve.
    • GREEN/REFACTOR: build the axis state.
  5. Measure + PNG — length/thickness (1/8″), compute sqft/bdft/widths, write the 3:4 inventory PNG. M1 stops here.
    • RED: Playwright — enter L/thickness → Calculate; assert PNG is 3:4 with alpha, and numbers equal the fixture's expected values.
    • GREEN/REFACTOR: build Measure + PNG encode.
  6. M1 UAT — serve the container per deploy/README.md §Milestone 1 UAT; run the full Playwright suite in the container; then the manual phone pass. Record host + URL in deploy/INVENTORY.md.

Deployment (UAT)

See deploy/README.md §Milestone 1 UAT — deployment POR: one container, host chosen at runtime, LAN-reachable URL, no backend.

Dev / QA worker dispatch

Two local inference endpoints are available as dispatchable workers for test / dev / QA:

  • .202:8081 — gemma-4-12B-it-q4_k_m (12B, Q4) — completion only, no vision. Use for text/code tasks: drafting, code review, test-writing help.
  • .202:8082 — Qwen3.8-27B-UD-IQ3_XXS (27B, IQ3) — completion + multimodal (vision). This is the vision worker: any task that must look at a slab photo (bg-removal tuning, mask/axis calibration review, fixture sanity checks) goes here.

Coordinator: Hermes (me) — plans, decomposes, dispatches, verifies, and does work directly when a card is small or judgment-heavy.

Rules:

  • Vision tasks → .202:8082 only.
  • Never more than one task on an endpoint at a time. Two concurrent jobs on the same endpoint back up and overheat. Serialize dispatch; one endpoint = one active task.
  • Both run low-quant (Q4 / IQ3). Fine for dispatch-style assist; deep sustained reasoning is better done by the coordinator directly or on a higher-quant model.

Test plan (M1)

Three layers. The deterministic core is unit-tested; the end-to-end path is Playwright; a real phone is the final UAT gate.

1. Unit (deterministic core) — must pass before any UI consumes it

  • bdft = sqft × thickness_in; sqft = (mask_px / scale²) / 144; scale = longest_axis_px / L.
  • 1/8 in stepping; rounding (sqft/bdft 2 decimals).
  • Width sampling every 6 in along the approved axis.
  • PNG encode contract: 3:4 aspect, 8-bit RGBA, 80% fill, shorter side ≥ 1600px when source allows; undersized source → warn + retake (no upscale).
  • Mask empty → approve blocked.

2. Playwright (automated end-to-end, runs in the UAT container's browser)

Walks the 5 states against a sample photo:

  • Add photo → Mask (set sheet + sensitivity) → approve → Length axis → approve → Measure (enter L, thickness) → Calculate.
  • Assert: PNG rendered, dimensions = 3:4, alpha present; sqft/bdft/widths equal the expected values for that fixture (within tolerance); numbers visible on screen.
  • HEIC input → "retake as JPEG" notice shown (not a crash).
  • Device draft: reload → Resume → Continue restores last approved state.

3. Manual phone UAT (final gate)

On a real phone (iOS Safari / Android Chrome) over the LAN UAT URL: repeat the happy path with one real slab; confirm PNG + numbers on screen. Record host + URL in deploy/INVENTORY.md.

Test fixtures (sample pics)

Real slab photos are the fixtures (supplied by Ty from \\truenas.local\Business\Samples, SMB user SMBSVC). Each is a DJI MIMO top-down JPEG, ~4000×2256, slab on a green/black sheet.

tests/fixtures/:

  • sample_01 … sample_0N.JPG — a representative handful of real slab photos (pulled on demand from the TrueNAS Samples share; do not bulk-copy the whole folder).
  • Each fixture gets a calibration record in tests/fixtures/<name>.json: the slab's true length and thickness (in inches), the sheet color, and the approved mask/axis reference — used to compute the expected scale, sqft, bdft, and sampled widths for assertions.

The real photos drive both bg removal (green/black key) and rectangle/axis calibration. Expected values come from the calibration records, so assertions stay deterministic even on real imagery.

M1 fixture set (agreed, complete for M1): three black-sheet slabs — one irregular (stress-tests the min-area rectangle/axis), two clean elongated. Green-sheet keying is deferred (not an M1 fixture). A 1 HEIC sample (optional) for the decode-fallback test.

Open decisions

  • (none outstanding for M1 as of this plan; new decisions append here)