docs(wiki): decide vision service packaging — apps/vision/ in the monorepo

Settle WHERE the host-side ANPR service lives and how it joins the build: in this
monorepo at apps/vision/ (not a separate repo), still a separate OS process called
over localhost HTTP, wired into the Turbo graph via a thin package.json shim whose
scripts shell to Python tooling (uv/uvicorn/ruff/pytest). Co-located source honors the
vision-service runtime+license isolation decision (AGPL reach is a linking boundary,
not a folder); the fast-alpr MIT baseline removes most of the split-repo pressure
anyway. New page vision-service-packaging; updates vision-service, opencv-anpr-service,
the CLAUDE.md layout, index, log. Not built yet — packaging decision only.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-19 14:25:31 +02:00
parent e4827c9651
commit ee28b7302f
6 changed files with 109 additions and 4 deletions
+4
View File
@@ -908,3 +908,7 @@ Added a THIRD data stream (`app_logs`) alongside the signed ledger and device te
## [2026-06-19] query | ANPR recognizer options — fast-alpr evaluated as the baseline
Q: LPR/ANPR options — YOLO, OpenCV, both, another framework? Reframed: "YOLO vs OpenCV" is a category error — they're different pipeline LAYERS (YOLO = plate detector; OpenCV = Apache-2.0 image-handling glue, used regardless; plus an OCR stage). The real choice is which end-to-end recognizer. Researched [fast-alpr](https://github.com/ankandrew/fast-alpr) (latest **v0.4.0, 15 Mar 2026, MIT**): a thin orchestrator over two swappable ONNX stages — detection via [open-image-models](https://github.com/ankandrew/open-image-models) (`yolo-v9-t-384-license-plate-end2end`, MIT) + OCR via [fast-plate-ocr](https://github.com/ankandrew/fast-plate-ocr) (`cct-xs-v2-global-model`, MIT; also has a EUROPEAN model trained on 40+ countries — relevant for AL plates). MIT top-to-bottom (code AND published weights), one maintainer across all three repos, CPU-only + fully offline, backend extras for CPU/CUDA/OpenVINO/DirectML/QNN. KEY FINDING: its detector is open-image-models' OWN YOLOv9 ONNX export, NOT the Ultralytics AGPL package — so fast-alpr is a PERMISSIVE baseline that may not even need the scoped AGPL exception from [[vision-service]]. CAVEAT (flagged, not closed): a repo's LICENSE covers code, not necessarily redistributed model WEIGHTS (YOLOv9 upstream is GPL-3.0; Ultralytics YOLO AGPL) — verify weight provenance before relying on "MIT weights". fast-alpr is PLATE-ONLY → Job 2 (vehicle-attribute anti-spoofing) is still ours to build, but shares the same ONNX runtime. Recommendation: prototype fast-alpr now; Ultralytics-YOLO+PaddleOCR fine-tune only if accuracy disappoints. Recorded as an evaluated-options note; decision kept status:open pending the provenance check + an AL-plate accuracy benchmark. Updated [[opencv-anpr-service]] (new "Recognizer evaluation" section + licensing nuance), [[vision-service]] (open/next), index.
## [2026-06-19] decision | Vision service packaging — apps/vision/ in this monorepo, Turbo shim
Q: how to IMPLEMENT the vision service — can we use this Turborepo? Settled (status:settled): the Python/FastAPI ANPR service lives in THIS monorepo at `apps/vision/`, NOT a separate repo. Key clarification: Turbo orchestrates JS/TS package.json TASKS (+ caches outputs); it has no native Python build — but "in the repo" ≠ "in the Turbo graph", and "separate process" ≠ "separate repo". Decision: (1) co-locate source at apps/vision/ (pnpm-workspace already globs apps/*, so it auto-joins) for atomic cross-cutting changes (the /analyze contract + the Node adapter together), one wiki/history; (2) still a SEPARATE OS process (uvicorn over localhost HTTP) — co-location is source-level only, runtime isolation intact; (3) wire into Turbo via a THIN package.json shim whose scripts shell to Python (dev→uv run uvicorn, lint→ruff, test→pytest, build→no-op/model-fetch since Python has no dist/**), so `turbo run lint/test` covers vision too — deps stay uv/pyproject, not pnpm; (4) Node talks to it via a VisionClient interface (device-adapter style), swappable. WHY co-location honors the [[vision-service]] isolation decision: that decision is about RUNTIME + LICENSE isolation (separate process; AGPL doesn't reach Node because it's not LINKED, just HTTP) — AGPL's reach is a linking/distribution-boundary question, NOT a which-folder question. And with the MIT-end-to-end [[opencv-anpr-service|fast-alpr]] baseline the AGPL pressure to split the repo largely evaporates anyway. Rejected: separate repo (loses atomic changes; fallback if AGPL acute or another team owns it), embed-in-Node (already rejected by vision-service), packages/ (that's for shared JS libs, vision is a deployable app). NOT built yet — packaging decision only; scaffold when vision work starts. New page [[vision-service-packaging]]; updated [[vision-service]], [[opencv-anpr-service]], CLAUDE.md layout, index.