3870cc3b0f
VisionReferenceImage (migration 013, chained after 012_vision_results): task_id, path, station_id, device_code, calibration_snapshot, engine_version, note, expected_json, acquired_at. station_id/device_code/ calibration_snapshot/engine_version/expected_json stay nullable - nessun endpoint di questo task li popola ancora, arrivano coi Piani 1b/2/4. save_reference_image salva sotto settings.upload_path (non upload_dir, come production_export_service). preview esegue il grafo e non salva niente - comporre non e' misurare, lo asserisce il test. POST /api/vision/reference-images e /api/vision/preview su require_maker (non require_measurement_tec di execute): comporre e provare sono lavoro del Maker, non misure. Suite intera su Python 3.11.15 locale (uv run pytest -q, SQLite in-memory per il backend): 1 failed, 373 passed, 4 skipped in 82.35s. Il fallimento e' quello preesistente e non correlato di test_no_first_party_script_calls_out (fabric-debug.js locale, git-ignored) - 371 passed prima di questo task, +2 qui. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU
70 lines
3.1 KiB
Python
70 lines
3.1 KiB
Python
"""One row per vision execution - not per quote."""
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from sqlalchemy import DateTime, Enum, ForeignKey, Integer, JSON, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from src.backend.database import Base
|
|
|
|
|
|
class VisionResult(Base):
|
|
__tablename__ = "vision_results"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
task_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("recipe_tasks.id"), nullable=False, index=True
|
|
)
|
|
image_path: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
|
overlay_path: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
|
engine_version: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
executed_on: Mapped[str] = mapped_column(
|
|
Enum("server", "station", name="vision_executed_on_enum"), nullable=False
|
|
)
|
|
station_id: Mapped[Optional[int]] = mapped_column(
|
|
Integer, ForeignKey("stations.id"), nullable=True
|
|
)
|
|
device_code: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
|
# Copied, not referenced: a calibration redone six months from now must not
|
|
# rewrite what a measurement already taken means. Same for the graph.
|
|
calibration_snapshot: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
|
graph_snapshot: Mapped[dict] = mapped_column(JSON, nullable=False)
|
|
duration_ms: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
executed_at: Mapped[datetime] = mapped_column(
|
|
DateTime, nullable=False, server_default=func.now()
|
|
)
|
|
|
|
__table_args__ = ({"mysql_engine": "InnoDB", "mysql_charset": "utf8mb4"},)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<VisionResult task={self.task_id} engine={self.engine_version}>"
|
|
|
|
|
|
class VisionReferenceImage(Base):
|
|
"""An image kept so a graph can be composed, tried and re-tried without a
|
|
camera - which is exactly what VisionSuite's source abstraction is for."""
|
|
|
|
__tablename__ = "vision_reference_images"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
task_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("recipe_tasks.id"), nullable=False, index=True
|
|
)
|
|
path: Mapped[str] = mapped_column(String(500), nullable=False)
|
|
station_id: Mapped[Optional[int]] = mapped_column(
|
|
Integer, ForeignKey("stations.id"), nullable=True
|
|
)
|
|
device_code: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
|
calibration_snapshot: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
|
engine_version: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
|
|
note: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
|
expected_json: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
|
acquired_at: Mapped[datetime] = mapped_column(
|
|
DateTime, nullable=False, server_default=func.now()
|
|
)
|
|
|
|
__table_args__ = ({"mysql_engine": "InnoDB", "mysql_charset": "utf8mb4"},)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<VisionReferenceImage task={self.task_id} path={self.path}>"
|