Phase 1: FastAPI backend with async job model

- backend/app: FastAPI API wrapping the CAD skill modules
  - upload -> job -> poll -> model / BOM / artifacts -> geometry query
  - SQLite via SQLModel (Model, Job, BomRow, QueryLog)
  - ThreadPoolExecutor worker, serialized, with live stage updates
- docker-compose.yml: dev server (mounts source, --reload) on :8000
- api-test.sh: end-to-end live validation script
- requirements.txt: add fastapi, uvicorn, python-multipart, sqlmodel
- external_diagram.py: port active-area detection OCC.Core -> OCP
- .gitignore, PHASE1.md

Validated live: MR16 round-trip passes (28 BOM rows, 12 artifacts,
bounding-box query, xlsx download; active-area detection working).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jason Stedwell
2026-06-17 16:38:26 -05:00
parent c1abe36822
commit b3c3e2a3b2
15 changed files with 701 additions and 5 deletions
+8 -5
View File
@@ -873,10 +873,13 @@ def _detect_active_area(model: StepModel, selected_parts: list) -> dict | None:
"""
try:
if model.backend == "build123d":
from OCC.Core.BRepGProp import BRepGProp
from OCC.Core.GProp import GProp_GProps
from OCC.Core.GeomAdaptor import GeomAdaptor_Surface
from OCC.Core.GeomAbs import GeomAbs_Plane
# build123d ships the OpenCASCADE kernel as OCP (cadquery-ocp), not the
# pythonocc `OCC.Core` package. OCP mirrors the same module names and the
# same `_s` static-method suffix, so this is a 1:1 import rename.
from OCP.BRepGProp import BRepGProp
from OCP.GProp import GProp_GProps
from OCP.GeomAdaptor import GeomAdaptor_Surface
from OCP.GeomAbs import GeomAbs_Plane
best_area = 0
best_face_data = None
@@ -885,7 +888,7 @@ def _detect_active_area(model: StepModel, selected_parts: list) -> dict | None:
for face in model.shape.faces():
try:
from OCC.Core.BRep import BRep_Tool
from OCP.BRep import BRep_Tool
surf = BRep_Tool.Surface_s(face.wrapped)
adaptor = GeomAdaptor_Surface(surf)
if adaptor.GetType() != GeomAbs_Plane: