Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
7ea85d3
Scaffold uv project, ruff, pytest, CI and pipeline layout
huntertcarver Sep 26, 2026
5b1719b
Add scripts/sync_from_store.sh to refresh foundations from the Projec…
huntertcarver Sep 26, 2026
5cf69f1
Import foundations snapshot from the Project store
huntertcarver Sep 26, 2026
31bb1cd
Refresh snapshot from the Project store, adding the scene and verdict…
huntertcarver Sep 26, 2026
0e4d16d
Add scripts/sync_breadth.sh to push store breadth work to breadth/<pa…
huntertcarver Sep 26, 2026
19fe57a
Stop ignoring outputs/ so breadth result JSON is committed
huntertcarver Sep 26, 2026
ea40af3
Keep meter numbers and SSR prompts out of breadth syncs. (#1)
huntertcarver Sep 26, 2026
443ff74
breadth: A1-classical results (#2)
huntertcarver Sep 26, 2026
43b88ac
breadth: A2-feedforward results (#3)
huntertcarver Sep 26, 2026
78e89cf
breadth: B2-equipment-reading results (#7)
huntertcarver Sep 26, 2026
bfc69a2
Sync c1-rules-3d breadth work from the Project store (result file c1-…
huntertcarver Sep 26, 2026
1d4fe6c
breadth: C2-volumetric results (#9)
huntertcarver Sep 26, 2026
a579ea8
breadth: C3-vlm-baseline results (#10)
huntertcarver Sep 26, 2026
a23158a
breadth: A3-depth-fusion results (#4)
huntertcarver Sep 26, 2026
48efd67
breadth: B1-detection results (#6)
huntertcarver Sep 26, 2026
2084fd0
Add A6, A7, and A8 to the breadth sync. (#11)
huntertcarver Sep 26, 2026
7a774b6
Sync a8-scale-without-lidar breadth work from the Project store (resu…
huntertcarver Sep 26, 2026
b40dd3c
Ignore star-import lint in breadth experiment folders. (#15)
huntertcarver Sep 26, 2026
86a915f
breadth: A8-scale-without-lidar results (#16)
huntertcarver Sep 26, 2026
03427bf
breadth: A5-world-models results (#5)
huntertcarver Sep 26, 2026
a588a4f
Add A9-no-tape-scale to the breadth sync. (#17)
huntertcarver Sep 26, 2026
b87ac8d
breadth: A9-no-tape-scale results (#18)
huntertcarver Sep 26, 2026
ccad689
breadth: A1-classical results (#19)
huntertcarver Sep 26, 2026
a8a2f91
breadth: A6-iphone-quality results (#12)
huntertcarver Sep 26, 2026
74cc9c9
Register A10, B3, and E2E on the breadth sync. (#20)
huntertcarver Sep 26, 2026
4dc1ce0
breadth: b3-cheap-gate results (#21)
huntertcarver Sep 26, 2026
fb3f61f
Sync e2e-criteria-on-recon breadth work from the Project store (resul…
huntertcarver Sep 26, 2026
c8cf890
breadth: A7-iphone-degradation results (#13)
huntertcarver Sep 26, 2026
bc51647
breadth: a10-sparse-photo-flow results (#23)
huntertcarver Sep 26, 2026
630fdd8
Add the server build plan and facade reference media (#24)
huntertcarver Sep 26, 2026
0ddef48
Add the final-pass report and updated workstream briefs. (#27)
huntertcarver Sep 27, 2026
0e7b451
WS-00 contracts: models, schemas, and the contracts CI job (#26)
huntertcarver Sep 27, 2026
4689595
WS-00 skeleton: eval harness, stage stubs, and import rules (#38)
huntertcarver Sep 27, 2026
4725cfe
Paraphrase SSR overlaps and add a shingle check (#40)
huntertcarver Sep 27, 2026
9fd4c62
Add meter table, LaMAR fetchers, and capture sheet (#25)
huntertcarver Sep 27, 2026
7c96421
WS-00 fixtures: golden packets, scenes, and make validate (#41)
huntertcarver Sep 27, 2026
f78ac97
Add meter and panel reads (WS-08) (#30)
huntertcarver Sep 27, 2026
b85c7f5
Align the capture-packet schema with spec 0.4.1. (#45)
softwaremanufacturingplant[bot] Sep 27, 2026
13b08a4
WS-10 result composer and AR guidance (#42)
huntertcarver Sep 27, 2026
4bda59c
Fail closed on capture erase, id keys, and environment. (#47)
softwaremanufacturingplant[bot] Sep 27, 2026
54bb393
Clarify that Riva base_od_m stays 0.1765 from inches. (#46)
softwaremanufacturingplant[bot] Sep 27, 2026
94dd22a
Fix near-edge placement, shown-reject reasons, and missing previews. …
softwaremanufacturingplant[bot] Sep 27, 2026
8e8cbb6
Default VISION_EXTERNAL_CALLS to off (#50)
softwaremanufacturingplant[bot] Sep 27, 2026
e8ca9bb
Record ground-rule ids on rebuilt GT scenes and skip coverage tests w…
softwaremanufacturingplant[bot] Sep 27, 2026
c6b8c04
WS-14: iOS contract kit for spec 0.4 (#43)
huntertcarver Sep 27, 2026
506536e
WS-03 orchestrator: stages, retries, sweeper, early workers (#29)
huntertcarver Sep 27, 2026
38e1acd
Add the live reads gate, SD-67 key hygiene, and a work-dir reads.json…
softwaremanufacturingplant[bot] Sep 27, 2026
c20ddb2
WS-01 capture ingest API (volume backend) (#34)
huntertcarver Sep 27, 2026
5a724ff
Document server id patterns for the iOS kit. (#54)
softwaremanufacturingplant[bot] Sep 27, 2026
4b41a9c
Close the remaining iOS prompt gaps and document auth-off. (#55)
softwaremanufacturingplant[bot] Sep 27, 2026
1c5a557
Ignore reads-gate-live and match the on-only vision wording (#56)
softwaremanufacturingplant[bot] Sep 27, 2026
6d0b5e0
Add integration and overnight handoff docs. (#58)
softwaremanufacturingplant[bot] Sep 27, 2026
e737610
Note that the iOS kit API token is optional. (#60)
softwaremanufacturingplant[bot] Sep 27, 2026
8d3aaa9
Refresh integration status after the capture API landed. (#62)
softwaremanufacturingplant[bot] Sep 27, 2026
0df0606
Publish early results and keep the run record current. (#57)
softwaremanufacturingplant[bot] Sep 27, 2026
5ec19dc
Read the demo auth mode from HSS_AUTH_MODE. (#59)
softwaremanufacturingplant[bot] Sep 27, 2026
40ce621
Let the overnight agent act within a few hard rails. (#61)
softwaremanufacturingplant[bot] Sep 27, 2026
c21fdbb
Record the rebuilt live capture image (#64)
softwaremanufacturingplant[bot] Sep 27, 2026
54e750b
Add the scale layer (LiDAR, meter lookup, ARKit gate) (#35)
huntertcarver Sep 27, 2026
ccd6c0d
Match ios_kit prompt rendering, including a missing variable. (#53)
softwaremanufacturingplant[bot] Sep 27, 2026
6fff6b9
Integrate modern ARKit drift on a continuous walk. (#63)
softwaremanufacturingplant[bot] Sep 27, 2026
4e0c32f
Note the scale layer is on main (#66)
softwaremanufacturingplant[bot] Sep 27, 2026
95f34ca
Pin ingest API tests to static bearer auth. (#65)
softwaremanufacturingplant[bot] Sep 27, 2026
de5e697
De-dupe ground hints and key early reads by still id. (#67)
softwaremanufacturingplant[bot] Sep 27, 2026
2ead04d
Accept WS-08's bare early meter identity. (#69)
softwaremanufacturingplant[bot] Sep 27, 2026
00bed49
Load the real ios kit in the prompt parity test. (#68)
softwaremanufacturingplant[bot] Sep 27, 2026
69757eb
WS-07 object understanding (#28)
huntertcarver Sep 27, 2026
88bf819
Add packet validation and the capture checklist (#37)
huntertcarver Sep 27, 2026
2889fd3
Return finalize 202 before promotion and start_run. (#72)
softwaremanufacturingplant[bot] Sep 27, 2026
f55426d
Integration: make e2e-dev result schema gate (#44)
softwaremanufacturingplant[bot] Sep 27, 2026
846799d
WS-09 criteria engine (#39)
huntertcarver Sep 27, 2026
7334f86
Tell clients to retry finalize after a storage 503. (#76)
softwaremanufacturingplant[bot] Sep 27, 2026
654d601
Publish every artifact path a stage returns. (#77)
softwaremanufacturingplant[bot] Sep 27, 2026
be5c077
Ask Grok when OpenAI is out of quota. (#75)
softwaremanufacturingplant[bot] Sep 27, 2026
fbdd51f
Refresh observed live image and background finalize behavior (#80)
huntertcarver Sep 27, 2026
8e647db
Publish files over 5 MB and skip paths outside the work dir. (#79)
softwaremanufacturingplant[bot] Sep 27, 2026
e4da0c8
Finalize amendments after a completed parent packet (#78)
huntertcarver Sep 27, 2026
67c4d7d
Handle streams and bounded batches in e2e capture uploads (#73)
huntertcarver Sep 27, 2026
2a512e7
Report the delivery C2-off start-range gap. (#83)
softwaremanufacturingplant[bot] Sep 27, 2026
41523d9
Add the WS-12 Terraform stack and Modal image (#36)
huntertcarver Sep 27, 2026
8a39564
Refresh overnight build status and remaining integration seams (#86)
huntertcarver Sep 27, 2026
764c046
WS-06 dense geometry, coverage, and scene builder (#31)
huntertcarver Sep 27, 2026
744dfec
Preserve early-read worker artifacts through dispatch and replay (#71)
huntertcarver Sep 27, 2026
7e2a8d8
Flag malformed stream cells and isolate shared packet checks (#85)
softwaremanufacturingplant[bot] Sep 27, 2026
4d911eb
Stub torch device in the mocked dense loader test (#89)
huntertcarver Sep 27, 2026
fbbf4c4
Skip Modal deploy when the GitHub token is unset. (#90)
softwaremanufacturingplant[bot] Sep 27, 2026
e3c7681
Skip the colmap binary when the CPU image does not have it. (#88)
softwaremanufacturingplant[bot] Sep 27, 2026
1b16573
Record the latest live API image and its evidence limits (#92)
huntertcarver Sep 27, 2026
5536d64
Pin inferred geometry and restore the ground strip (#81)
softwaremanufacturingplant[bot] Sep 27, 2026
4621bd2
Document the dense, coverage, and scene stages. (#94)
softwaremanufacturingplant[bot] Sep 27, 2026
80b7931
WS-11: harness fixes, re-baseline, and offline gates (#33)
huntertcarver Sep 27, 2026
5e7e4c3
Cast 2D detections onto chain walls and vote ground regions. (#96)
softwaremanufacturingplant[bot] Sep 27, 2026
08513e7
Serialize background finalize writes with capture deletion (#87)
huntertcarver Sep 27, 2026
46b4583
Unwrap committed image metadata before early dispatch (#74)
huntertcarver Sep 27, 2026
84c8e0c
Speed up empty-track coverage rays and clock each L4 step (#95)
softwaremanufacturingplant[bot] Sep 27, 2026
70d3210
Refresh build status for the draft remote-result deployment (#99)
huntertcarver Sep 27, 2026
e7740b7
Install Open3D with the dev sync so TSDF tests run (#93)
softwaremanufacturingplant[bot] Sep 27, 2026
d17bc12
Make inferred clearance evidence independent of object order (#97)
huntertcarver Sep 27, 2026
daebe73
Send C3 photos to the judge and clip observed wall views (#82)
softwaremanufacturingplant[bot] Sep 27, 2026
cab08e9
Require distinct camera frames before casting 2D detections (#98)
huntertcarver Sep 27, 2026
74d6fb4
Add the COLMAP pose backbone with ARKit priors (#32)
huntertcarver Sep 27, 2026
14cbe3b
Downgrade a pass when a C3 decision fact is unsure or failing. (#102)
softwaremanufacturingplant[bot] Sep 27, 2026
88be747
Clip coverage rays to the grid before sampling. (#103)
softwaremanufacturingplant[bot] Sep 27, 2026
260998c
Record the dev deploy that mounts stage package data. (#113)
softwaremanufacturingplant[bot] Sep 27, 2026
60cc66a
Mount review templates and schemas into stage images. (#111)
softwaremanufacturingplant[bot] Sep 27, 2026
9f32a9c
Record the main 60cc66a dev deploy and replay. (#116)
softwaremanufacturingplant[bot] Sep 27, 2026
7da7e40
Fix WS-06 pose, anchor, and scene artifact seams (#112)
softwaremanufacturingplant[bot] Sep 27, 2026
6fdfd41
Generate WS-09 overlays for the offline gates (#100)
softwaremanufacturingplant[bot] Sep 27, 2026
2e82d04
Pin the numeric host and score rebuilt GT (#106)
softwaremanufacturingplant[bot] Sep 27, 2026
3a3a180
Compare the synthetic wall on one extract thread. (#120)
softwaremanufacturingplant[bot] Sep 27, 2026
d469247
Allow a non-wall region view in base-verdict/v0 (#115)
softwaremanufacturingplant[bot] Sep 27, 2026
37fbda5
Collect Modal stage results and mark them done (#91)
softwaremanufacturingplant[bot] Sep 27, 2026
b01bf15
Record the main 37fbda5 dev deploy and replay. (#123)
softwaremanufacturingplant[bot] Sep 27, 2026
51bc3a5
Do not report HASWELL when the OpenBLAS pin did not apply (#124)
softwaremanufacturingplant[bot] Sep 27, 2026
13e5d93
Scope run ids by capture and stop re-downloading inline stage inputs …
softwaremanufacturingplant[bot] Sep 27, 2026
dc62d22
Fail closed on committed gate inputs and pin their hashes (#125)
softwaremanufacturingplant[bot] Sep 27, 2026
58b6784
Record the main 13e5d93 dev deploy and replay. (#132)
softwaremanufacturingplant[bot] Sep 27, 2026
579fa7d
Re-extract fixture packets when extracted files disagree with the man…
softwaremanufacturingplant[bot] Sep 27, 2026
5c93d8c
Fail a pass candidate with a non-finite chain span (#133)
softwaremanufacturingplant[bot] Sep 27, 2026
71876e9
Run object models on CUDA and spawn objects on the GPU image (#131)
softwaremanufacturingplant[bot] Sep 27, 2026
ff0c3a9
Prepare the remote-stage switch for real runs (#127)
softwaremanufacturingplant[bot] Sep 27, 2026
30d381b
Withhold observed ground grades from a rejected unreanchored plane (#…
softwaremanufacturingplant[bot] Sep 27, 2026
37debec
Retry live commit and finalize, and pass dev-only meter pixels (#141)
softwaremanufacturingplant[bot] Sep 27, 2026
18baee1
Bake the deployed app name into every Modal service. (#144)
softwaremanufacturingplant[bot] Sep 27, 2026
c4896f2
Point-read open captures and cut remote hydration (#143)
softwaremanufacturingplant[bot] Sep 27, 2026
97da537
Record that real runs are live on c4896f2. (#147)
softwaremanufacturingplant[bot] Sep 27, 2026
498d977
Emit one final event and keep result status with the outcome. (#146)
softwaremanufacturingplant[bot] Sep 27, 2026
2d0911f
chore(backend): port house-scanning-server into the monorepo
SamGu-NRX Oct 15, 2026
6fad552
chore(backend): drop the snapshot so backend/ carries its source history
SamGu-NRX Oct 15, 2026
57f57ff
chore(backend): merge house-scanning-server history under backend/
SamGu-NRX Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
4 changes: 4 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*
!pyproject.toml
!uv.lock
!Dockerfile
55 changes: 55 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Base-provided prompt material and anything else that must not reach GitHub.
private/

.venv/
__pycache__/
.env
.env.*
.terraform/
*.tfstate
*.tfstate.*
*.egg-info/
.pytest_cache/
.ruff_cache/
.coverage
.coverage.*
.DS_Store
runs/
.fixtures/

# data/ holds scripts and manifests only; frames, packets and videos live in the store or on disk.
data/houses/
data/packets/
data/frames/
data/**/*.jpg
data/**/*.jpeg
data/**/*.png
data/**/*.heic
data/**/*.mp4
data/**/*.mov
data/**/*.npz
data/**/*.ply
data/**/*.bin

# Fetched tars, PLYs and extracts. Never commit them.
.fixtures/

# scripts/reads_gate.py --live --out. Holds real meter numbers (barcode payloads
# and reader answers). The default is /tmp/reads-gate, outside the repo. Never
# commit or upload this folder, including an in-repo copy such as reads-gate-live.
reads-gate*/

# Golden fixtures that are committed on purpose (coverage grids, mini-arkit stills).
!data/fixtures/**/*.jpg
!data/fixtures/**/*.jpeg
!data/fixtures/**/*.npz
!data/fixtures/**/*.bin

# Reconstruction outputs. Small JSON results under breadth outputs/ folders are committed.
*.ply
*.splat
# The build-plan reference set is the exception: ETH3D facade clouds for reviewers.
!media/colmap-facade/point-clouds/*.ply

# Terraform provider cache. Lock files stay committed.
.terraform/
8 changes: 8 additions & 0 deletions backend/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
repos:
- repo: local
hooks:
- id: hygiene
name: repo hygiene
entry: uv run --frozen python scripts/check_repo_hygiene.py
language: system
pass_filenames: false
1 change: 1 addition & 0 deletions backend/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
31 changes: 31 additions & 0 deletions backend/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Contributing

## Branches and pull requests

- `main` is protected by convention: nobody pushes to it directly after the initial import, and agents never merge.
- **Breadth work lands on branches named `breadth/<path-id>`, opened as draft pull requests.** Path ids match the folders: `a1-classical`, `a2-feedforward`, `a3-depth-fusion`, `a4-gaussian-splatting`, `a5-world-models`, `a6-iphone-quality`, `a7-iphone-degradation`, `a8-scale-without-lidar`, `a9-no-tape-scale`, `a10-sparse-photo-flow`, `b1-detection`, `b2-equipment-reading`, `b3-cheap-gate`, `c1-rules-3d`, `c2-volumetric`, `c3-vlm`, `e2e-criteria-on-recon`.
- Keep one writer per branch. Each breadth pull request ends with the standard one-page result: metrics, runtime, cost, failure modes, licence, and a go / no-go.
- Other work uses a short descriptive branch name and a draft pull request.
- Breadth agents that work in the Project store don't push themselves: `scripts/sync_breadth.sh <path-id>...` (or `--all`) copies `internal/breadth/<folder>/` and the path's result file (as `RESULTS.md`) onto `breadth/<path-id>` and pushes it. It skips photos, model outputs, weights, files over 5 MB, real meter numbers (`raw/meter/`, `labels/meter_numbers_hand.csv`), and Base SSR prompt text or a digest of it.

## Snapshot folders

These are copied from the team's Cursor Project store by `scripts/sync_from_store.sh`, and edits made here are overwritten on the next sync:

- `packet/` (from `internal/packet-generator/`)
- `eval/` (from `internal/eval-harness/`)
- `criteria/spec/` (from `internal/criteria/`)
- `data/scripts/` and `data/manifest.json` (from `internal/data/`)
- `docs/capture-packet-spec.md`, `docs/criteria-spec.md`, `docs/scene-and-verdict-format.md`

Change them in the store, then run `scripts/sync_from_store.sh`. It creates a `sync/store-<timestamp>` branch from `origin/main`, re-copies the folders, and leaves the changes uncommitted for review. Lint is relaxed for these folders until the store copies are cleaned up.

## What never gets committed

- Anything in `private/`, including the prompt material Base gave the team. The sync script puts it there locally.
- Images, videos, packets, point clouds and other large binaries. The sync skips files over 5 MB; `data/` holds scripts and manifests only.
- ML runs on Google Maps / Street View, Mapbox or Esri imagery, whose terms forbid it. Use StratMap or NAIP.

## Checks

CI runs `ruff check`, `ruff format --check` and `pytest` on every push to `main` and every pull request. Run them locally with `uv run ruff check . && uv run ruff format --check . && uv run pytest`.
111 changes: 111 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# GPU pipeline image. Application code is not copied here; Modal adds server/
# with add_local_python_source. COLMAP 4.2.0 matches pycolmap==4.2.0 (SD-34).
# linux/amd64 digest of nvidia/cuda:12.4.1-devel-ubuntu22.04.
FROM nvidia/cuda:12.4.1-devel-ubuntu22.04@sha256:5645fec64549cc35930eee9d85aafd2b0006c0c3f22632be5a1d85e2604e9749

ENV DEBIAN_FRONTEND=noninteractive \
HF_HOME=/vol/hf \
HUGGINGFACE_HUB_CACHE=/vol/hf/hub \
TORCH_HOME=/vol/torch \
PYTHONUNBUFFERED=1 \
PATH=/app/.venv/bin:$PATH

# Jammy's Ceres package is 1.14. COLMAP 4.2 needs Ceres >= 2.2, so that
# package is not installed; Ceres 2.2.0 is built below. OpenImageIO's Ubuntu
# CMake config looks for /usr/include/opencv4 even when OpenCV is unused.
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
cmake \
ninja-build \
build-essential \
libboost-program-options-dev \
libboost-filesystem-dev \
libboost-graph-dev \
libboost-system-dev \
libeigen3-dev \
libopenimageio-dev \
openimageio-tools \
libmetis-dev \
libgoogle-glog-dev \
libgflags-dev \
libsqlite3-dev \
libsuitesparse-dev \
libcurl4-openssl-dev \
libssl-dev \
libglew-dev \
libgl1-mesa-dev \
libglu1-mesa-dev \
libcgal-dev \
libopenblas-dev \
liblapack-dev \
ca-certificates \
&& mkdir -p /usr/include/opencv4 \
&& rm -rf /var/lib/apt/lists/*

RUN git clone --branch 2.2.0 --depth 1 https://github.com/ceres-solver/ceres-solver.git /tmp/ceres \
&& cmake -S /tmp/ceres -B /tmp/ceres/build -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_TESTING=OFF \
-DBUILD_EXAMPLES=OFF \
-DBUILD_BENCHMARKS=OFF \
&& ninja -C /tmp/ceres/build -j3 \
&& ninja -C /tmp/ceres/build install \
&& rm -rf /tmp/ceres

# A 3.11.1 binary under a 4.x pycolmap wheel is forbidden. Tag 4.2.0 is the
# COLMAP release pycolmap 4.2.0 is built against. The PyPI pycolmap wheel is
# CPU-only (has_cuda is false). pycolmap-cuda12 is installed last: the Pi3,
# MoGe, and Depth Anything archives depend on pycolmap and would replace an
# earlier CUDA wheel with the CPU one. The NVIDIA CUDA 12.4 image is not
# Ubuntu's CUDA package, so the jammy GCC 10 workaround does not apply.
# OpenImageIO's CMake config requires the OpenEXR config, which is not pulled
# in by libopenimageio-dev alone.
# Jammy's CMake is 3.22. COLMAP 4.2 fetches faiss, which requires CMake >= 3.24.
RUN apt-get update && apt-get install -y --no-install-recommends curl libopenexr-dev \
&& curl -fsSL -o /tmp/cmake.tgz https://github.com/Kitware/CMake/releases/download/v3.31.8/cmake-3.31.8-linux-x86_64.tar.gz \
&& echo "630615d8e98ac33eba7fbe472626dff5c899c85af3c024585ae109166a6909d0 /tmp/cmake.tgz" | sha256sum -c - \
&& tar -C /usr/local --strip-components=1 -xzf /tmp/cmake.tgz \
&& rm -rf /tmp/cmake.tgz /var/lib/apt/lists/* \
&& git clone --branch 4.2.0 --depth 1 https://github.com/colmap/colmap.git /tmp/colmap \
&& cmake -S /tmp/colmap -B /tmp/colmap/build -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CUDA_ARCHITECTURES="80;86;89;90" \
-DGUI_ENABLED=OFF \
-DTESTS_ENABLED=OFF \
-DCMAKE_INSTALL_PREFIX=/usr/local \
&& ninja -C /tmp/colmap/build -j3 \
&& ninja -C /tmp/colmap/build install \
&& ldconfig \
&& (colmap -h > /tmp/colmap-help.txt || true) \
&& grep -q COLMAP /tmp/colmap-help.txt \
&& rm -rf /tmp/colmap /tmp/colmap-help.txt

# Tag 0.11.23, pinned by digest. Modal's builder rejects a reference that sets both.
COPY --from=ghcr.io/astral-sh/uv@sha256:d0a0a753ab981624b49c97abc98821c1c09f4ca69d1ef5cee69c501be3d88479 /uv /uvx /bin/

RUN uv python install 3.12

WORKDIR /app
COPY pyproject.toml uv.lock ./
# libsm6/libice6/libx11/libxext are NEEDED by the CUDA wheel. --no-deps keeps
# pip's cuda-toolkit meta-package off this image; CUDA 12.4 is already here.
RUN apt-get update && apt-get install -y --no-install-recommends libsm6 libice6 libx11-6 libxext6 \
&& rm -rf /var/lib/apt/lists/* \
&& uv sync --frozen --no-install-project --no-dev --extra gpu \
&& uv pip install --python /app/.venv/bin/python pip \
&& curl -fsSL -o /tmp/pi3.tgz "https://github.com/yyfz/Pi3/archive/9fa3ddb3f8d53041f8b2738df404f62223bbaa7b.tar.gz" \
&& echo "017c226430e69bd3508940f326bce3db6e3eb778d7efe088b7fe6374cd550431 /tmp/pi3.tgz" | sha256sum -c - \
&& curl -fsSL -o /tmp/moge.tgz "https://github.com/microsoft/MoGe/archive/925b8ed835a7a9cdb7578ba15c658a0afc969030.tar.gz" \
&& echo "c6d90b2564d643f0f3ae65b5ffe163abaea3b55d194c6e2ba9976d67f552bd26 /tmp/moge.tgz" | sha256sum -c - \
&& curl -fsSL -o /tmp/da3.tgz "https://github.com/ByteDance-Seed/Depth-Anything-3/archive/3d835ec1a5802d64a8b8b15f817a1ab54809bfe4.tar.gz" \
&& echo "98aa2dd53ab44b96cef5190ae4841c6ae51797d099b784e08e12a1a55bd3a69b /tmp/da3.tgz" | sha256sum -c - \
&& uv pip install --python /app/.venv/bin/python /tmp/pi3.tgz /tmp/moge.tgz /tmp/da3.tgz \
&& rm -f /tmp/pi3.tgz /tmp/moge.tgz /tmp/da3.tgz \
&& uv pip install --python /app/.venv/bin/python \
torch==2.5.1 torchvision==0.20.1 \
--index-url https://download.pytorch.org/whl/cu124 \
&& uv pip uninstall --python /app/.venv/bin/python pycolmap pycolmap-cuda12 \
&& uv pip install --python /app/.venv/bin/python --no-deps "pycolmap-cuda12==4.2.0"

RUN python -c "import pycolmap; assert pycolmap.__version__.startswith('4.2'), pycolmap.__version__; assert pycolmap.has_cuda, pycolmap.has_cuda"
137 changes: 137 additions & 0 deletions backend/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# `ci` includes `validate` (committed fixtures only). Large PLYs and tars stay in `.fixtures/`.
.PHONY: setup lint test schemas hygiene fixtures gt validate validate-full ci gates-offline gates-update e2e e2e-local lamar criteria-golden e2e-dev orchestrator-e2e ios-kit result-golden reads-gate reads-extra weights

ONLY ?= small

setup:
uv sync --frozen

lint:
uv run --frozen ruff check .
uv run --frozen ruff format --check .
uv run --frozen lint-imports

# api extra only. `--all-extras` installs the gpu torch pin, and the OWLv2
# parity test then runs on agent-store B1 images and misses by one box.
test:
uv run --frozen --extra api pytest -q

schemas:
uv run --frozen python -m server.contracts.export_schemas --check

hygiene:
uv run --frozen python scripts/check_repo_hygiene.py

fixtures:
uv run --frozen python scripts/fetch_fixtures.py --only $(ONLY) $(if $(ITEM),--item $(ITEM),)

# Public Hugging Face weights onto house-capture-pipeline:/vol/hf.
# Local-dir <org>--<repo> and hub/models--<org>--<repo> (see server/weights/fetch.py).
weights:
SMP_ENVIRONMENT=dev uv run modal run -e dev -m server.weights.fetch

gt:
bash scripts/rebuild_gt.sh

validate:
uv run --frozen python scripts/validate_fixtures.py

validate-full:
uv run --frozen python scripts/validate_fixtures.py --full

ci: lint test schemas hygiene validate

# Scores the committed fixtures. Producers write under runs/ unless --update.
gates-offline:
nice -n 10 uv run --frozen python -m server.eval.cli gates --config server/eval/gates.yaml --inputs data/fixtures --out runs/gates-offline/gates.json

gates-update:
uv run --frozen python -m server.eval.producers --update --inputs data/fixtures
uv run --frozen python -m server.eval.cli gates --refresh-hashes --config server/eval/gates.yaml --inputs data/fixtures
$(MAKE) gates-offline

e2e:
nice -n 10 uv run python -m server.eval.e2e --config server/eval/gates.yaml --inputs data/fixtures --out runs/e2e/latest

e2e-local:
nice -n 10 uv run python -m server.eval.e2e --local --config server/eval/gates.yaml --inputs data/fixtures --out runs/e2e/local

lamar:
nice -n 10 uv run python -m server.eval.lamar run --data $(HOME)/lamar --out runs/lamar

# Unit suite, then verdicts for the three ETH3D laser sites at /tmp/crit/<site>/.
# Laser PLYs come from `make fixtures ONLY=all`. C3 stays off.
criteria-golden:
uv run --frozen pytest server/criteria/tests -q
HSS_CRITERIA_C3=off VISION_EXTERNAL_CALLS=off uv run --frozen python -m server.criteria.run --scene data/fixtures/scenes/eth3d-facade/gt-laser/scene.json --out /tmp/crit/facade --no-c3
HSS_CRITERIA_C3=off VISION_EXTERNAL_CALLS=off uv run --frozen python -m server.criteria.run --scene data/fixtures/scenes/eth3d-delivery/gt-laser/scene.json --out /tmp/crit/delivery --no-c3
HSS_CRITERIA_C3=off VISION_EXTERNAL_CALLS=off uv run --frozen python -m server.criteria.run --scene data/fixtures/scenes/eth3d-electro/gt-laser/scene.json --out /tmp/crit/electro --no-c3

# SD-77: the live stack only (Modal dev capture-api, house-scanning bucket).
# CAPTURE_API_URL must be https://huntertcarver-dev--capture-api.modal.run
# SD-86: no CAPTURE_API_TOKEN. PACKET=path/to/packet.json (or its directory).
e2e-dev:
PYTHONPATH=. uv run --frozen python scripts/e2e_dev.py --self-check
PYTHONPATH=. uv run --frozen python scripts/e2e_dev.py $(if $(PACKET),--packet $(PACKET),)

orchestrator-e2e:
STATE_BACKEND=memory STORAGE_BACKEND=local HSS_ORCH_STAGE_STUBS=1 VISION_EXTERNAL_CALLS=off SMP_ENVIRONMENT=dev \
uv run --frozen pytest server/orchestrator/tests -q

# Refresh the committed schema copies and pack the zip the iOS team installs.
ios-kit:
cp server/contracts/schemas/capture-packet.v0.4.schema.json ios-kit/schemas/capture-packet.v0.4.schema.json
cp server/contracts/schemas/result.v0.schema.json ios-kit/schemas/result.v0.schema.json
cp server/contracts/schemas/api.v1.schema.json ios-kit/schemas/api.v1.schema.json
cp server/contracts/schemas/capture-packet.v0.4.schema.json ios-kit/schema/capture-packet.schema.json
cp data/fixtures/packets/examples/example-packet.json ios-kit/examples/packets/example-packet.json
cp data/fixtures/packets/examples/example-packet-photo-only.json ios-kit/examples/packets/example-packet-photo-only.json
cp data/fixtures/packets/mini-arkit/packet.json ios-kit/examples/packets/example-packet-meter-stills.json
rm -rf dist/ios-kit-stage dist/ios-kit-0.4.0.zip
mkdir -p dist/ios-kit-stage/spec dist/ios-kit-stage/schema dist/ios-kit-stage/fixtures
cp ios-kit/README.md ios-kit/VERSION ios-kit/CHANGELOG.md ios-kit/requirements.txt dist/ios-kit-stage/
cp docs/capture-packet-spec.md dist/ios-kit-stage/spec/capture-packet-spec.md
cp -R ios-kit/schemas ios-kit/examples ios-kit/prompts ios-kit/packetgen dist/ios-kit-stage/
cp ios-kit/schema/capture-packet.schema.json dist/ios-kit-stage/schema/
cp ios-kit/fixtures/LICENCE-NOTES.md dist/ios-kit-stage/fixtures/
cp -R ios-kit/fixtures/mini-arkit ios-kit/fixtures/mini-arkit-lidar ios-kit/fixtures/mini-photo-only dist/ios-kit-stage/fixtures/
cd dist/ios-kit-stage && zip -qr ../ios-kit-0.4.0.zip . -x '*__pycache__*'
rm -rf dist/ios-kit-stage
cmp server/contracts/schemas/capture-packet.v0.4.schema.json ios-kit/schemas/capture-packet.v0.4.schema.json

# Compose the committed synthetic fixture. ETH3D rows wait on make fixtures and make criteria-golden.
result-golden:
uv run --frozen --extra result python -m server.result.compose \
--capture server/result/tests/data/capture.sample.json \
--run server/result/tests/data/run.ok.json \
--scene server/result/tests/data/synthetic \
--verdicts server/result/tests/data/synthetic/verdicts \
--out /tmp/res/synthetic \
--reads server/result/tests/data/reads.auto_fill.json \
--catalogue server/result/tests/data/prompts.en-US.json
uv run --frozen --extra result python -m server.result.compose \
--capture server/result/tests/data/capture.sample.json \
--run server/result/tests/data/run.ok.json \
--scene server/result/tests/data/photo \
--verdicts server/result/tests/data/photo/verdicts \
--out /tmp/res/photo \
--catalogue server/result/tests/data/prompts.en-US.json
uv run --frozen --extra result python -m server.result.compose \
--capture server/result/tests/data/capture.sample.json \
--run server/result/tests/data/run.ok.json \
--scene server/result/tests/data/synthetic \
--verdicts server/result/tests/data/reject/verdicts \
--out /tmp/res/reject \
--catalogue server/result/tests/data/prompts.en-US.json \
--show-reject
uv run --frozen --extra result python -c "from server.contracts.result import ResultResponse; import json; \
[ResultResponse.model_validate(json.load(open(f'/tmp/res/{name}/result.json'))) for name in ('synthetic','photo','reject')]; print('ok synthetic photo reject')"

reads-gate:
uv run --frozen python scripts/reads_gate.py --set meter --set panel --set extra --out /tmp/reads-gate

reads-extra:
uv sync --frozen --extra reads
uv run --frozen --extra reads python -c "import openai, zxingcpp"

include infra/deploy.mk
Loading