Files
ui/_docs/03_implementation/batch_05_report.md
Oleksandr Bezdieniezhnykh 6d03643c2c
ci/woodpecker/push/build-arm Pipeline was successful
[AZ-461] [AZ-464] [AZ-470] [AZ-472] Batch 5 - detection/bulk-validate/panel-width/classes tests
- AZ-461 sync image detect URL canary (FT-P-11) PASS;
  async-video QUARANTINE (FT-P-12) + X-Refresh-Token drift
  (FT-P-13) recorded as it.fails() with controls.
- AZ-464 bulk-validate URL + UI sync (≤2 s) PASS;
  body shape drift {annotationIds,status} vs contract
  {ids,targetStatus:30} captured as it.fails().
- AZ-470 panel-width debounce + rehydration: entire task
  is Phase-B target (useResizablePanel has no PUT writer
  / no rehydration); 3 ACs as it.fails() with controls.
- AZ-472 DetectionClasses load + click + fallback PASS;
  hotkey arithmetic P=0 PASS, P=20/P=40 it.fails() for
  classes[idx+P]-against-dense-array drift.

Code review: PASS (0 findings). Fast: 18/18 files,
102 passed / 13 skipped. Static: 21/21 PASS.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 04:38:22 +03:00

9.9 KiB
Raw Permalink Blame History

Batch Report

Batch: 05 Tasks: AZ-461 (Detection endpoints sync/async/long-video), AZ-464 (Bulk-validate URL/body/UI sync), AZ-470 (Panel-width debounced PUT + rehydration), AZ-472 (DetectionClasses load + hotkeys + click + fallback) Date: 2026-05-11 Cycle: Phase A baseline, Step 6 — Implement Tests Total complexity: 9 pts (2 + 2 + 2 + 3)

Task Results

Task Status Files Modified Tests AC Coverage Issues
AZ-461_test_detection_endpoints Done 1 created (tests/detection_endpoints.test.tsx); 1 e2e created (e2e/tests/detection_endpoints.e2e.ts) 4 fast (2 pass + 2 it.fails() per spec QUARANTINE / drift, 2 controls); 2 e2e (1 PASS + 1 test.fail) 3 / 3 ACs covered 2 documented drifts: production POSTs single-endpoint /api/detect/<id> regardless of mediaType (no async-video route — AC-25 lifts QUARANTINE); api.post sets only Authorization header (no X-Refresh-Token — Phase B wires it)
AZ-464_test_bulk_validate Done 1 created (tests/bulk_validate.test.tsx); 1 e2e created (e2e/tests/bulk_validate.e2e.ts) 3 fast (2 pass + 1 it.fails() for body-shape drift + 1 control); 3 e2e (2 PASS + 1 test.fail) 3 / 3 ACs covered 1 documented drift: production sends {annotationIds, status: AnnotationStatus.Validated (=2)} instead of contract {ids, targetStatus: 30} (flips with AC-04 wire enum scheme)
AZ-470_test_panel_width_persistence Done 1 created (tests/panel_width_persistence.test.tsx); 1 e2e created (e2e/tests/panel_width_persistence.e2e.ts) 5 fast (3 it.fails() + 2 controls — every AC is it.fails() per spec note); 1 e2e (test.fail) 3 / 3 ACs covered 1 systemic drift: useResizablePanel hook holds local state only — no PUT to /api/annotations/settings/user on resize-end, no rehydration of seeded panelWidths on reload (entire task is Phase-B-target)
AZ-472_test_detection_classes Done 1 created (tests/detection_classes.test.tsx); 1 e2e created (e2e/tests/detection_classes.e2e.ts) 7 fast (5 pass + 2 it.fails() for hotkey drift); 1 e2e (PASS) 4 / 4 ACs covered 1 documented drift: production hotkey logic uses classes[idx + photoMode] against a dense array — yields wrong class for P=20 and out-of-range for P=40 (flips with filter-then-index OR sparse length-60 array). P=0 PASS (coincidentally)

AC Test Coverage: All covered (13 / 13 ACs across the four tasks)

AZ-461 — Detection endpoints (3 ACs, 6 scenarios)

Scenario Where Profile Status
AC-1 / FT-P-11 (sync image detect URL) tests/detection_endpoints.test.tsx + e2e/tests/detection_endpoints.e2e.ts fast + e2e PASS — production POSTs /api/detect/<numeric-id> matching the contract regex
AC-2 / FT-P-12 (async video detect endpoint + SSE — QUARANTINE) tests/detection_endpoints.test.tsx fast it.fails() — runs end-to-end, emits "FT-P-12 awaits AC-25 / async video detect impl" log per spec
AC-2 / control: production POSTs /api/detect/<id> regardless of mediaType (drift pin) same fast PASS — pins single-endpoint drift
AC-3 / FT-P-13 (long-video detect carries X-Refresh-Token) tests/detection_endpoints.test.tsx + e2e/tests/detection_endpoints.e2e.ts fast + e2e it.fails() (fast) + test.fail (e2e) — production sets only Authorization
AC-3 / control: production sets only Authorization on detect (current behavior) tests/detection_endpoints.test.tsx fast PASS — proves spy machinery + Authorization presence

AC summary:

  • AC-1 sync URL canary → PASS today (numeric media id satisfies ^/api/detect/[0-9]+$).
  • AC-2 async video / SSE → it.fails() + control + log per QUARANTINE rule.
  • AC-3 X-Refresh-Token header → it.fails() + control pinning Authorization-only drift.

AZ-464 — Bulk-validate (3 ACs, 4 scenarios)

Scenario Where Profile Status
AC-1 / FT-P-20 URL canary tests/bulk_validate.test.tsx + e2e/tests/bulk_validate.e2e.ts fast + e2e PASS — production POSTs /api/annotations/dataset/bulk-status
AC-2 / FT-P-20 body shape {ids, targetStatus: 30} same fast + e2e it.fails() (fast) + test.fail (e2e)
AC-2 / control: body is {annotationIds, status: AnnotationStatus.Validated} (current shape) tests/bulk_validate.test.tsx fast PASS — pins field-name + status-value drift
AC-3 / FT-P-21 + NFT-PERF-07 (UI sync ≤ 2 000 ms) tests/bulk_validate.test.tsx + e2e/tests/bulk_validate.e2e.ts fast + e2e PASS — wall-clock from click to all rows showing Validated badge ≤ 2 s

AC summary:

  • AC-1 URL canary → PASS.
  • AC-2 body shape → it.fails() + control proving production's drift shape (both field names AND status value differ from contract).
  • AC-3 UI sync → PASS within 2 s (production calls fetchItems() after the 200 returns).

AZ-470 — Panel-width debounced PUT + rehydration (3 ACs, 5 scenarios)

Scenario Where Profile Status
AC-1 / FT-P-37 + NFT-PERF-08 (debounce window) tests/panel_width_persistence.test.tsx fast it.fails() — production never PUTs
AC-1 / control: production emits ZERO PUTs during a resize today same fast PASS — pins no-writer drift
AC-2 / FT-P-37 (PUT body carries panelWidths) same fast it.fails() — depends on AC-1 writer landing
AC-3 / FT-P-38 (rehydration on reload) same + e2e/tests/panel_width_persistence.e2e.ts fast + e2e it.fails() (fast) + test.fail (e2e) — no rehydration effect
AC-3 / control: production renders panels at constructor defaults (250 / 200) ignoring seeded settings tests/panel_width_persistence.test.tsx fast PASS — pins drift

AC summary:

  • Entire AZ-470 is a Phase-B-target group per task spec (useResizablePanel has no settings writer / reader today).
  • Every AC is it.fails(); controls pin the current no-writer + constructor-default behavior.
  • Tests flip green automatically once useResizablePanel is wired to <UserSettings> save/load.

AZ-472 — DetectionClasses (4 ACs, 8 scenarios)

Scenario Where Profile Status
AC-1 / FT-P-44 (load contract) tests/detection_classes.test.tsx + e2e/tests/detection_classes.e2e.ts fast + e2e PASS — GET /api/annotations/classes observed at mount; 9 entries rendered for P=0
AC-2 / FT-P-45 P=0 (keys 1..9 → ids 0..8) tests/detection_classes.test.tsx fast PASS — coincidentally aligns since offset is 0
AC-2 / FT-P-45 P=20 (keys 1..9 → ids 20..28) same fast it.fails() — production's classes[idx + 20] lands in the 40s window against the dense length-27 array
AC-2 / FT-P-45 P=40 (keys 1..9 → ids 40..48) same fast it.fails()classes[idx + 40] exceeds array length; cls is undefined
AC-3 / FT-P-46 (click path) same fast PASS — userEvent.click fires onSelect(c.id)
AC-4 / FT-P-47 fallback on [] same fast PASS — FALLBACK_CLASS_NAMES rendered when API returns empty
AC-4 / FT-P-47 fallback on 500 same fast PASS — FALLBACK_CLASS_NAMES rendered on server error
AC-4 / fallback id set equals [0..N-1, 20..20+N-1, 40..40+N-1] same fast PASS — pins fallback contract for downstream AZ-473 dependants

AC summary:

  • AC-1 load → PASS at mount.
  • AC-2 hotkey arithmetic → P=0 PASS, P=20 + P=40 it.fails() for documented production drift.
  • AC-3 click → PASS.
  • AC-4 fallback → 3 scenarios PASS (empty, 500, id-set).

Code Review Verdict: PASS

See _docs/03_implementation/reviews/batch_05_review.md for the full 7-phase walkthrough.

  • 0 Critical, 0 High, 0 Medium, 0 Low findings.
  • All it.fails() placements anchored to either explicit task-spec QUARANTINE direction (AZ-461 AC-2) or documented production drift with control test pinning the current shape.
  • Architecture compliance (Phase 7): no layer-direction violations; tests are leaves of the import graph; no new cyclic dependencies; static profile (STC-S6, STC-S13) re-confirms.

Auto-Fix Attempts: 0

PASS verdict — no auto-fix loop entered.

Stuck Agents: None

Each task implemented in a single sequential pass. No file rewritten 3+ times; no approach pivots.

Test Run Summary

  • bun run test:fast — 18 files / 102 passed / 13 skipped / 7.31 s.
  • ./scripts/run-tests.sh --static-only — all 21 static checks PASS / 17.95 s.
  • ReadLints — clean on all 8 changed files.

Documented Drifts (cumulative across batch)

Drift Where Spec/AC affected Resolves when
Single-endpoint detect (no /api/detect/video/...) src/features/annotations/AnnotationsSidebar.tsx (Detect button handler) AZ-461 AC-2 AC-25 (Phase B async-video path)
X-Refresh-Token header absent on detect src/api/client.ts request fn AZ-461 AC-3 Phase B (header wiring per Step 4 / F7)
Bulk-validate body shape {annotationIds, status} vs contract {ids, targetStatus} src/features/dataset/DatasetPage.tsx AZ-464 AC-2 AC-04 wire enum scheme
Status value AnnotationStatus.Validated (=2) vs contract 30 same AZ-464 AC-2 AC-04 wire enum scheme
useResizablePanel has no PUT writer src/hooks/useResizablePanel.ts AZ-470 AC-1 + AC-2 Phase B (debounced settings writer)
useResizablePanel has no rehydration reader same AZ-470 AC-3 Phase B (reads panelWidths from settings on mount)
Hotkey index formula classes[idx + P] against dense array src/components/DetectionClasses.tsx (keydown handler) AZ-472 AC-2 (P=20, P=40) Either filter-then-index switch OR sparse length-60 fixture

Next Batch: AZ-454, AZ-456 epics likely complete after this batch — 14 → 10 tasks remaining in todo/. Cumulative review (batches 0406) triggers after the next batch per Step 14.5 (K=3 cadence).