Something went wrong. Try again.
atproto Thingiverse but good
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393# polymodel development commandsset dotenv-load := false# Canonical SQLite database URL for the projection store and the compile-time# `query!` macros. Scoping it here (rather than via .env) keeps `just` recipes# hermetic — see `set dotenv-load := false` above.db-url := 'sqlite:./data/polymodel.db'# Public recipes are dispatch boundaries; implementations are underscore-prefixed# so Just hides them from --list while keeping the dependency graph in-shell.default: @just --list# Format Rust sources. Run clippy/check separately; clippy --fix can corrupt RSX.fix: @tools/in-dev-shell _fix# Run clippy without --fix; automatic clippy rewrites can corrupt Dioxus RSX.lint: @tools/in-dev-shell _lint# Compile checks across the whole workspace plus the app's server/wasm targets.# The server check resolves compile-time `query!` macros against the committed# `.sqlx` offline cache; regenerate it with `just sqlx-prepare` after changing# SQL or migrations.check: @tools/in-dev-shell _check# Create and migrate the SQLite projection database.# Required when regenerating the `.sqlx` cache, and re-run after editing migrations.migrate: @tools/in-dev-shell _migrate# Regenerate the committed `.sqlx` offline query cache after changing SQL.# Self-contained: migrates the local database first, then points `cargo sqlx# prepare` at it via DATABASE_URL so no manual env setup is required.sqlx-prepare: @tools/in-dev-shell _sqlx-prepare# Run unit tests across the workspace with the app's server-only code enabled.test: @tools/in-dev-shell _test# Test the Just/Nix-shell dispatch boundary without evaluating the flake.test-just-nix: bash tools/test-just-nix.sh# Guard the repair shell from depending on repository build outputs. This must# remain runnable even when Nix evaluation or repository builds are broken.check-devshell-tools-only: python3 tools/check-devshell-tools-only.py# Run server-feature tests (app only; polymodel-api has no server feature).test-server: @tools/in-dev-shell _test-server# Run browser-backed wasm tests for the renderer worker.test-renderer: @tools/in-dev-shell _test-renderer# Validate the authored PM-77 corpus, provenance, matrix, gates, and snapshots.ldraw-corpus: @tools/in-dev-shell _ldraw-corpus# Compile the semantic core and reusable corpus/gate code for the E-facing WASM target.ldraw-wasm-check: @tools/in-dev-shell _ldraw-wasm-check# Ensure expected/gate/harness/fuzz paths use authored data and the real core adapter.ldraw-oracle-integrity: @tools/in-dev-shell _ldraw-oracle-integrity# Check committed expected records against a fresh oracle-only generation.ldraw-oracle-check: @tools/in-dev-shell _ldraw-oracle-check# Run bounded, deterministic native adversarial/property smoke.ldraw-fuzz-smoke: @tools/in-dev-shell _ldraw-fuzz-smoke# Generate oracle-only v3 projections into a temporary directory by default.ldraw-oracle-generate: @tools/in-dev-shell _ldraw-oracle-generate# Require the native LDParse oracle toolchain before running oracle-backed gates.require-nix: @tools/in-dev-shell _require-nix# Run the offline native LDParse compatibility boundary.ldraw-differential: @tools/in-dev-shell _ldraw-differential# Run focused LDraw core tests.test-ldraw-core: @tools/in-dev-shell _test-ldraw-core# Run focused native renderer-worker unit tests, including scene picking.test-renderer-worker-native: @tools/in-dev-shell _test-renderer-worker-native# Run the recipe-owned native preview/readback contract.test-renderer-native: @tools/in-dev-shell _test-renderer-native# Render the pinned LDraw corpus with the exact native preview target.preview-ldraw *ARGS: @tools/in-dev-shell _preview-ldraw {{ ARGS }}# Emit machine-readable parser/adapter benchmark evidence for the pinned model.ldraw-bench: @tools/in-dev-shell _ldraw-bench# Capture native preview timing and persistent readback evidence for the pinned model.ldraw-visual: @tools/in-dev-shell _ldraw-visual# Run all local validation expected before review. Keep the PM-77 recipes explicit# so corpus, WASM, fuzz, and Nix-backed differential gates remain visible.test-all: @tools/in-dev-shell _test-all# Run browser end-to-end tests.e2e: @tools/in-dev-shell _e2e# Start the Dioxus dev server. Builds the renderer worker first if missing.serve *ARGS: @tools/in-dev-shell _serve {{ ARGS }}# Build the renderer worker WASM bundle (separate from the app WASM).build-renderer-worker: @tools/in-dev-shell _build-renderer-worker# Build and stage the single-threaded OpenCascade.js STEP conversion artifacts.build-opencascade-step: @tools/in-dev-shell _build-opencascade-step# Build the Dioxus app for web (includes renderer worker build).build-web: @tools/in-dev-shell _build-web# Build the Dioxus app for web (release, optimized). Strips debug symbols and runs wasm-opt.build-web-release: @tools/in-dev-shell _build-web-release# Verify the renderer split: no heavy deps in the app, worker wasm exists, bundle size under ceiling.verify-renderer-split: @tools/in-dev-shell _verify-renderer-split# Regenerate crates/polymodel-api from authored lexicons via the local Jacquard checkout.generate-api: @tools/in-dev-shell _generate-api# Validate portable event-sourced GC coordination state.validate-gc-state *ARGS: @tools/in-dev-shell _validate-gc-state {{ ARGS }}# Validate GC jj workspace/bookmark rails before or after forgetting workspaces.validate-gc-jj-state *ARGS: @tools/in-dev-shell _validate-gc-jj-state {{ ARGS }}# Check that build-time environment handling does not expose server secrets to the frontend.check-public-env *ARGS: @tools/in-dev-shell _check-public-env {{ ARGS }}# Guard compile-time SQL usage in handwritten production Rust.check-production-sql *ARGS: @tools/in-dev-shell _check-production-sql {{ ARGS }}# Validate current documentation references and architecture maps.check-doc-references *ARGS: @tools/in-dev-shell _check-doc-references {{ ARGS }}# Guard the single production appview content-type normalizer and its callers.check-content-type *ARGS: @tools/in-dev-shell _check-content-type {{ ARGS }}# Validate the borrowed proxy response-reference parser and raw forwarding boundary.check-proxy-response *ARGS: @tools/in-dev-shell _check-proxy-response {{ ARGS }}# Create a sibling jj workspace for a Jira ticket or feature slug, then start a fresh change.workspace-create name: @tools/in-dev-shell _workspace-create {{ name }}# List jj workspaces.workspace-list: @tools/in-dev-shell _workspace-list# Forget a jj workspace after the work is safely landed or intentionally abandoned.workspace-forget name: @tools/in-dev-shell _workspace-forget {{ name }}# Show current jj state and diff.status: @tools/in-dev-shell _status# Clean build artifacts.clean: @tools/in-dev-shell _clean_fix: cargo fmt --all_lint: cargo clippy --workspace --all-targets --features server -- -D warnings -A clippy::useless_format cargo clippy -p polymodel --all-targets --features server -- -D warnings -A clippy::useless_format cargo clippy -p polymodel --target wasm32-unknown-unknown --features web -- -D warnings -A clippy::useless_format_check: cargo check --workspace cargo check -p polymodel --features server cargo check -p polymodel --target wasm32-unknown-unknown --features web RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo check -p polymodel-renderer-worker --target wasm32-unknown-unknown_migrate: mkdir -p ./data cargo sqlx migrate run --source migrations --database-url '{{ db-url }}'_sqlx-prepare: _migrate DATABASE_URL='{{ db-url }}' cargo sqlx prepare -- -p polymodel --features server_test: cargo nextest run --workspace --features server_test-server: cargo nextest run -p polymodel --features server_test-renderer: RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo test -p polymodel-renderer-worker --target wasm32-unknown-unknown_test-ldraw-core: cargo test -p polymodel-ldraw-core cargo test -p polymodel-ldraw-testkit_test-renderer-worker-native: cargo test -p polymodel-renderer-worker --lib_test-renderer-native: @set -eu; \ test -n "${LDRAWDIR:-}"; \ test -d "$LDRAWDIR"; \ echo "[native-test] inherited official library: $LDRAWDIR"; \ Xvfb :99 -screen 0 2560x1440x24 -ac +extension GLX +render -noreset >/tmp/polymodel-xvfb.log 2>&1 & xvfb_pid=$!; \ mkdir -p "$PWD/target/ldraw-preview"; \ preview_log="$PWD/target/ldraw-preview/native-preview.log"; \ test_log="$PWD/target/ldraw-preview/native-test.log"; \ readback_prefix="$PWD/target/ldraw-preview/persistent"; \ rm -f "$preview_log" "$test_log" "$readback_prefix"-*.png; \ trap 'status=$?; kill $xvfb_pid 2>/dev/null || true; echo "[native-test] Xvfb stderr:"; tail -80 /tmp/polymodel-xvfb.log; echo "[native-test] preview log:"; tail -160 "$preview_log" 2>/dev/null || true; echo "[native-test] test log:"; tail -160 "$test_log" 2>/dev/null || true; exit $status' EXIT; \ ready=0; \ for attempt in $(seq 1 100); do \ kill -0 "$xvfb_pid" 2>/dev/null || { echo "[native-test] Xvfb exited before display :99 became ready" >&2; exit 1; }; \ if xset -display :99 q >/dev/null 2>&1; then ready=1; break; fi; \ sleep 0.1; \ done; \ test "$ready" -eq 1 || { echo "[native-test] timed out waiting for display :99" >&2; exit 1; }; \ echo "[native-test] display-ready=:99"; \ echo "[native-test] preview-start"; \ set +e; DISPLAY=:99 WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY= XDG_RUNTIME_DIR= LIBGL_ALWAYS_SOFTWARE=1 LDRAWDIR="$LDRAWDIR" timeout --signal=TERM --kill-after=5s 180s cargo run -p polymodel-renderer-worker --bin ldraw_preview -- --width 2560 --height 1440 --camera-case identity_front --scene-variant identity --proof-ms 1500 --readback-prefix "$readback_prefix" >"$preview_log" 2>&1; status=$?; set -e; cat "$preview_log"; test "$status" -eq 0; \ test -n "$(find "$PWD/target/ldraw-preview" -maxdepth 1 -name 'persistent-*.png' -type f -print -quit)"; \ echo "[native-test] integration-start"; \ set +e; DISPLAY=:99 WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY= XDG_RUNTIME_DIR= LIBGL_ALWAYS_SOFTWARE=1 LDRAWDIR="$LDRAWDIR" timeout --signal=TERM --kill-after=5s 180s cargo test -p polymodel-renderer-worker --test ldraw_preview -- --nocapture >"$test_log" 2>&1; status=$?; set -e; cat "$test_log"; test "$status" -eq 0_preview-ldraw *ARGS: set -eu; test -n "${LDRAWDIR:-}" || { echo "[preview] missing LDRAWDIR" >&2; exit 2; }; test -d "$LDRAWDIR" || { echo "[preview] invalid LDRAWDIR=$LDRAWDIR" >&2; exit 2; }; echo "[preview] inherited official library: $LDRAWDIR"; echo "[preview] launching native renderer; child output follows"; cargo run -p polymodel-renderer-worker --bin ldraw_preview -- {{ ARGS }}_ldraw-bench: # Keep acceptance criteria immutable and require every declared metric. @set -eu -o pipefail; output="${LDRAW_BENCH_OUTPUT:-$PWD/target/ldraw-evidence/bench.json}"; mkdir -p "$(dirname "$output")"; printf '%s\n' '{"schema":"polymodel-ldraw-bench-v2","model":"omr-10030-1.mpd","thresholds":{"parse_ms":5000,"adapt_ms":2000,"frame_allocations":0,"uv_cache_hit_rate":0.3},"required_metrics":["adapt-ldraw","scene-stats","uv-cache","frame"]}' >"$output"; POLYMODEL_LDRAW_TIMING=1 cargo test -p polymodel-renderer-worker --test ldraw_preview ldraw_preview_uses_pinned_corpus_and_scene_stats -- --nocapture 2>&1 | tee "${output%.json}.log"; log="${output%.json}.preview.log"; prefix="${output%.json}.preview"; Xvfb :99 -screen 0 2560x1440x24 -ac +extension GLX +render -noreset >/tmp/polymodel-xvfb-bench.log 2>&1 & xvfb_pid=$!; trap 'kill "$xvfb_pid" 2>/dev/null || true' EXIT; attempt=0; while test "$attempt" -lt 100; do xset -display :99 q >/dev/null 2>&1 && break; sleep 0.1; attempt=$((attempt + 1)); done; DISPLAY=:99 WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY= XDG_RUNTIME_DIR= LIBGL_ALWAYS_SOFTWARE=1 LDRAWDIR="$LDRAWDIR" POLYMODEL_LDRAW_TIMING=1 cargo run -p polymodel-renderer-worker --bin ldraw_preview -- --width 2560 --height 1440 --camera-case identity_front --scene-variant identity --proof-ms 500 --readback-prefix "$prefix" 2>&1 | tee "$log"; cat "$log" >> "${output%.json}.log"; python3 -c 'import json,pathlib,re,sys; p=pathlib.Path(sys.argv[1]); report=json.loads(p.read_text()); log=pathlib.Path(sys.argv[2]); lines=[x for x in log.read_text().splitlines() if "[ldraw-metrics]" in x]; t=report["thresholds"]; fail=[]; parse={"scanned-root","split-root","parsed-root-models","parsed-materializations","traversed"}; metrics=[]; [metrics.append((re.search(r"phase=(\S+)",x).group(1),int(re.search(r"elapsed_ms=(\d+)",x).group(1)) if re.search(r"elapsed_ms=(\d+)",x) else None,x)) for x in lines if re.search(r"phase=(\S+)",x)]; [fail.append("parse threshold exceeded: "+x) for phase,elapsed,x in metrics if phase in parse and elapsed is not None and elapsed>t["parse_ms"]]; [fail.append("adapt threshold exceeded: "+x) for phase,elapsed,x in metrics if phase=="adapt-ldraw" and elapsed is not None and elapsed>t["adapt_ms"]]; adapt=[x for phase,elapsed,x in metrics if phase=="adapt-ldraw"]; scene=[x for phase,elapsed,x in metrics if phase=="scene-stats"]; uv=[x for x in lines if "phase=uv-cache" in x]; frames=[x for x in lines if "phase=frame" in x]; [fail.append("missing "+name+" metric") for name,items in (("adapt-ldraw",adapt),("scene-stats",scene),("uv-cache",uv),("frame",frames)) if not items]; hit=re.search(r"(?:uv_cache_hits|hits)=(\d+)",uv[-1]) if uv else None; miss=re.search(r"(?:uv_cache_misses|misses)=(\d+)",uv[-1]) if uv else None; hits=int(hit.group(1)) if hit else None; misses=int(miss.group(1)) if miss else None; rate=hits/(hits+misses) if hits is not None and misses is not None and hits+misses else (float(re.search(r"hit_rate=([0-9.]+)",uv[-1]).group(1)) if uv and re.search(r"hit_rate=([0-9.]+)",uv[-1]) else None); fail.append("UV cache counters missing") if hits is None or misses is None else None; fail.append("UV cache hit rate below threshold") if rate is None or rate<t["uv_cache_hit_rate"] else None; lat=[int(v) for x in frames for v in re.findall(r"latency_us=(\d+)",x)]; alloc=[int(v) for x in frames for v in re.findall(r"allocations=(\d+)",x)]; fail.append("frame latency metrics missing") if not lat else None; fail.append("frame allocation metrics missing") if not alloc else None; fail.append("frame allocation threshold exceeded") if alloc and max(alloc)>t["frame_allocations"] else None; pct=lambda a,q: sorted(a)[min(len(a)-1,int((len(a)-1)*q+0.999999))]; report["observed"]={"timing_lines":lines,"metrics":[{"phase":a,"elapsed_ms":b,"line":c} for a,b,c in metrics],"log":str(log),"frame_latency_us":{"count":len(lat),"p95":pct(lat,.95) if lat else None,"p99":pct(lat,.99) if lat else None},"frame_allocations":{"max":max(alloc) if alloc else None,"samples":alloc},"uv_cache":{"hits":hits,"misses":misses,"hit_rate":rate},"scene_bytes":int(re.search(r"scene_bytes=(\d+)",scene[-1]).group(1)) if scene and re.search(r"scene_bytes=(\d+)",scene[-1]) else None,"upload_bytes":int(re.search(r"upload_bytes=(\d+)",scene[-1]).group(1)) if scene and re.search(r"upload_bytes=(\d+)",scene[-1]) else None}; p.write_text(json.dumps(report,indent=2)+"\n"); [print("benchmark gate: "+x,file=sys.stderr) for x in fail]; sys.exit(bool(fail))' "$output" "${output%.json}.log"_ldraw-visual: # Capture independent operator-review evidence for every frozen camera case. @set -eu -o pipefail; test -n "${LDRAWDIR:-}" || { echo "[visual] unavailable: LDRAWDIR is not configured" >&2; exit 2; }; test -d "$LDRAWDIR" || { echo "[visual] unavailable: invalid LDRAWDIR=$LDRAWDIR" >&2; exit 2; }; output_dir="${LDRAW_VISUAL_OUTPUT:-$PWD/target/ldraw-evidence/visual}"; mkdir -p "$output_dir"; cases="identity_front orbit_left close_range top_down"; printf '%s\n' '{"schema":"polymodel-ldraw-visual-v2","model":"omr-10030-1.mpd","proof_ms":1500,"cases":["identity_front","orbit_left","close_range","top_down"],"frozen_pixel_comparison":false,"thresholds":{"stage_markers":["preparation-stage=closure","native-build-stage=plan","native-build-stage=static","native-build-stage=picker","readback label=frame-1","stage=Rendered"]}}' >"$output_dir/baseline.json"; Xvfb :99 -screen 0 2560x1440x24 -ac +extension GLX +render -noreset >/tmp/polymodel-xvfb-visual.log 2>&1 & xvfb_pid=$!; trap 'kill "$xvfb_pid" 2>/dev/null || true' EXIT; attempt=0; while test "$attempt" -lt 100; do xset -display :99 q >/dev/null 2>&1 && break; sleep 0.1; attempt=$((attempt + 1)); done; for case in $cases; do case_dir="$output_dir/$case"; mkdir -p "$case_dir"; log="$case_dir/native-preview.log"; prefix="$case_dir/readback"; rm -f "$case_dir"/readback-*.png "$case_dir/metadata.json"; DISPLAY=:99 WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY= XDG_RUNTIME_DIR= LIBGL_ALWAYS_SOFTWARE=1 LDRAWDIR="$LDRAWDIR" cargo run -p polymodel-renderer-worker --bin ldraw_preview -- --width 2560 --height 1440 --camera-case "$case" --scene-variant identity --proof-ms 1500 --readback-prefix "$prefix" >"$log" 2>&1; find "$case_dir" -name 'readback-*.png' ! -name '*frame-1*' -delete; done; for case in $cases; do case_dir="$output_dir/$case"; log="$case_dir/native-preview.log"; test "$(find "$case_dir" -name 'readback-*.png' -type f | wc -l)" -eq 1; grep -q 'viewport requested=2560x1440 actual=2560x1440' "$log"; for marker in 'preparation-stage=closure' 'native-build-stage=plan' 'native-build-stage=static' 'native-build-stage=picker' 'readback label=frame-1' 'stage=Rendered'; do grep -q "$marker" "$log"; done; case "$case" in identity_front) camera='"'"'"yaw_degrees":0.0,"pitch_degrees":0.0,"roll_degrees":0.0,"distance":null,"fov_degrees":45.0,"fit_bounds":true'"'"';; orbit_left) camera='"'"'"yaw_degrees":-35.0,"pitch_degrees":0.0,"roll_degrees":0.0,"distance":null,"fov_degrees":45.0,"fit_bounds":true'"'"';; close_range) camera='"'"'"yaw_degrees":0.0,"pitch_degrees":0.0,"roll_degrees":0.0,"distance":0.35,"fov_degrees":45.0,"fit_bounds":false'"'"';; top_down) camera='"'"'"yaw_degrees":0.0,"pitch_degrees":-90.0,"roll_degrees":0.0,"distance":null,"fov_degrees":45.0,"fit_bounds":true'"'"';; esac; printf '%s\n' "{\"schema\":\"polymodel-ldraw-visual-case-v1\",\"camera_case\":\"$case\",\"dimensions\":{\"requested_width\":2560,\"requested_height\":1440,\"actual_width\":2560,\"actual_height\":1440},\"camera_parameters\":{$camera},\"stage_markers\":[\"preparation-stage=closure\",\"native-build-stage=plan\",\"native-build-stage=static\",\"native-build-stage=picker\",\"readback label=frame-1\",\"stage=Rendered\"],\"readbacks\":[\"$case/readback-frame-1-2560x1440.png\"],\"log\":\"$case/native-preview.log\"}" >"$case_dir/metadata.json"; done; exit 0; # 'import json,pathlib,re,sys; p=pathlib.Path(sys.argv[1]); r=json.loads(p.read_text()); root=p.parent; marks=r["thresholds"]["stage_markers"]; out=[]; [ (lambda d,t,paths,camera,viewport: (_ for _ in ()).throw(SystemExit(f"visual gate failed for {case}: missing={[m for m in marks if m not in t]} readbacks={paths}")) if any(m not in t for m in marks) or not paths or camera is None or viewport is None else out.append({"case":case,"log":str((d/"native-preview.log").relative_to(root)),"readbacks":paths[:1],"stage_markers":marks,"viewport":viewport,"camera":camera))(root/case,(root/case/"native-preview.log").read_text(),sorted(str(x.relative_to(root)) for x in (root/case).glob("readback-*.png")),next((x for x in (root/case/"native-preview.log").read_text().splitlines() if "camera-fit actual=" in x),None),next((x for x in (root/case/"native-preview.log").read_text().splitlines() if "viewport requested=" in x),None)) for case in r["cases"]]; r["captures"]=out; p.write_text(json.dumps(r,indent=2)+"\n")' "$output_dir/baseline.json" || true; python3 -c 'import json,pathlib,re,sys; p=pathlib.Path(sys.argv[1]); r=json.loads(p.read_text()); root=p.parent; marks=r["thresholds"]["stage_markers"]; cams={"identity_front":[0.0,0.0,0.0,None,True],"orbit_left":[-35.0,0.0,0.0,None,True],"close_range":[0.0,0.0,0.0,0.35,False],"top_down":[0.0,-90.0,0.0,None,True]}; out=[]; [ (lambda d,t,paths,m: (_ for _ in ()).throw(SystemExit(f"visual gate failed for {case}")) if len(paths)!=1 or m is None or any(x not in t for x in marks) else (lambda dims: (d.joinpath("metadata.json").write_text(json.dumps({"schema":"polymodel-ldraw-visual-case-v1","camera_case":case,"dimensions":dims,"camera_parameters":{"yaw_degrees":cams[case][0],"pitch_degrees":cams[case][1],"roll_degrees":cams[case][2],"distance":cams[case][3],"fov_degrees":45.0,"fit_bounds":cams[case][4]},"stage_markers":marks,"readbacks":[str(paths[0].relative_to(root))]},indent=2)+"\n"),out.append({"case":case,"metadata":str((d/"metadata.json").relative_to(root)),"readbacks":[str(paths[0].relative_to(root))],"dimensions":dims,"camera_parameters":cams[case]}))(dict(zip(("requested_width","requested_height","actual_width","actual_height"),map(int,m.groups())))))(root/case,(root/case/"native-preview.log").read_text(),sorted((root/case).glob("readback-*.png")),re.search(r"viewport requested=(\\d+)x(\\d+) actual=(\\d+)x(\\d+)",(root/case/"native-preview.log").read_text())) for case in r["cases"]]; r["captures"]=out; p.write_text(json.dumps(r,indent=2)+"\n")' "$output_dir/baseline.json"; python3 -c 'import json,pathlib,re,sys; p=pathlib.Path(sys.argv[1]); r=json.loads(p.read_text()); root=p.parent; cameras={"identity_front":(0.0,0.0,0.0,None,True),"orbit_left":(-35.0,0.0,0.0,None,True),"close_range":(0.0,0.0,0.0,0.35,False),"top_down":(0.0,-90.0,0.0,None,True)}; [ (lambda d,t,case,paths,m: d.joinpath("metadata.json").write_text(json.dumps({"schema":"polymodel-ldraw-visual-case-v1","camera_case":case,"dimensions":{"requested_width":int(m.group(1)),"requested_height":int(m.group(2)),"actual_width":int(m.group(3)),"actual_height":int(m.group(4))},"camera_parameters":{"yaw_degrees":cameras[case][0],"pitch_degrees":cameras[case][1],"roll_degrees":cameras[case][2],"distance":cameras[case][3],"fov_degrees":45.0,"fit_bounds":cameras[case][4]},"stage_markers":[x.strip() for x in t.splitlines() if "stage=" in x or "stage-" in x],"readbacks":[str(paths[0].relative_to(root))],"log":str((d/"native-preview.log").relative_to(root))},indent=2)+"\n"))(root/case,(root/case/"native-preview.log").read_text(),case,sorted((root/case).glob("readback-*.png")),re.search(r"viewport requested=(\d+)x(\d+) actual=(\d+)x(\d+)",(root/case/"native-preview.log").read_text())) for case in r["cases"]]; p.write_text(json.dumps(r,indent=2)+"\n")' "$output_dir/baseline.json"_ldraw-corpus: _ldraw-oracle-integrity _ldraw-oracle-check cargo test -p polymodel-ldraw-testkit cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- validate cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- inventory cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- corpus_ldraw-wasm-check: cargo check --tests -p polymodel-ldraw-core --target wasm32-unknown-unknown cargo check --tests -p polymodel-ldraw-testkit --target wasm32-unknown-unknown_ldraw-oracle-integrity: @if grep -RInE '(^|[^[:alnum:]_])canonical[[:space:]]*\(|(^|[^[:alnum:]_])parse_syntax[[:space:]]*\(' crates/polymodel-ldraw-testkit tools/ldraw-compat-harness tools/ldraw-oracle-generator --include='*.rs' --include='*.json' | grep -vE 'serialize_canonical|serialize[[:space:]]*\('; then echo 'FAIL: heuristic oracle helper call found'; exit 1; else echo 'PASS: no canonical/parse_syntax helper calls'; fi @if grep -RInE 'polymodel_ldraw_core|InProcessRustAdapter|polymodel-ldraw-core' crates/polymodel-ldraw-testkit/corpus/expected tools/ldraw-oracle-generator --include='*.json' --include='*.rs'; then echo 'FAIL: oracle generator/records depend on Rust semantic core'; exit 1; else echo 'PASS: oracle generator/records are core-independent'; fi_ldraw-oracle-check: _require-nix cargo run --manifest-path tools/ldraw-oracle-generator/Cargo.toml -- check crates/polymodel-ldraw-testkit/corpus crates/polymodel-ldraw-testkit/corpus/expected_ldraw-fuzz-smoke: cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- fuzz_ldraw-oracle-generate: _require-nix cargo run --manifest-path tools/ldraw-oracle-generator/Cargo.toml -- generate_ldraw-oracle-update: _require-nix cargo run --manifest-path tools/ldraw-oracle-generator/Cargo.toml -- update crates/polymodel-ldraw-testkit/corpus crates/polymodel-ldraw-testkit/corpus/expected_require-nix: @command -v nix >/dev/null 2>&1 || { echo "FAIL: nix is required for PM-77 oracle gates"; exit 1; }_ldraw-differential: _require-nix cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- differential_test-all: _require-nix _fix _check _lint _test _test-server _test-renderer _test-ldraw-core _ldraw-wasm-check _test-renderer-native_e2e: cd e2e && npm test_serve *ARGS: @if [ ! -f public/renderer_worker_bg.wasm ] || [ ! -f public/renderer_worker_loader.js ]; then echo "renderer worker not built — running just _build-renderer-worker"; just _build-renderer-worker; fi dx serve {{ ARGS }}_build-renderer-worker: RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo build -p polymodel-renderer-worker --bin renderer_worker --target wasm32-unknown-unknown --profile worker-release wasm-bindgen target/wasm32-unknown-unknown/worker-release/renderer_worker.wasm --target web --out-dir public --no-typescript @if command -v wasm-opt &>/dev/null; then wasm-opt public/renderer_worker_bg.wasm -O4 --enable-bulk-memory --enable-simd --enable-nontrapping-float-to-int --enable-sign-ext -o public/renderer_worker_bg.wasm; else echo "wasm-opt not found, skipping optimization"; fi_build-opencascade-step: node tools/renderer-step/build-and-stage-opencascade.mjs_build-web: _build-renderer-worker dx build --platform web_build-web-release: _build-renderer-worker _build-opencascade-step #!/usr/bin/env bash set -e dx build --platform web --release --debug-symbols=false if command -v wasm-opt &>/dev/null; then WASM=$(find target/dx/polymodel/release/web/public -name "polymodel_bg*.wasm" -print -quit 2>/dev/null) if [ -n "$WASM" ]; then echo "==> Running wasm-opt on $WASM" BEFORE=$(stat -c%s "$WASM") wasm-opt "$WASM" -Oz --enable-bulk-memory --enable-simd --enable-nontrapping-float-to-int --enable-sign-ext -o "$WASM" || { echo "==> wasm-opt failed, keeping unoptimized wasm"; exit 0; } AFTER=$(stat -c%s "$WASM") echo " $BEFORE -> $AFTER bytes" fi else echo "==> wasm-opt not found, skipping optimization" fi_verify-renderer-split: _build-web @echo "==> AC.1: checking app dependency tree for forbidden crates..." @if cargo tree -p polymodel --target wasm32-unknown-unknown --features web --edges normal 2>/dev/null | grep -qE '(^| )three-d v|three-d-asset v|stl_io v|polymodel-mesh v'; then echo "FAIL: forbidden crate found in app dependency tree"; exit 1; else echo "PASS: no forbidden crates"; fi @echo "==> AC.1b: checking app Cargo.toml for forbidden deps..." @if grep -qE '^\s*(three-d|three-d-asset|stl_io|polymodel-mesh)\b' Cargo.toml; then echo "FAIL: forbidden dep found in Cargo.toml"; exit 1; else echo "PASS: no forbidden deps in Cargo.toml"; fi @echo "==> AC.2: checking app wasm bundle size (debug build, debuginfo-dominated)..." @APP_WASM="target/dx/polymodel/debug/web/public/wasm/polymodel_bg.wasm" && test -f "$APP_WASM" && SIZE=$(stat -c%s "$APP_WASM") && echo "app wasm: $SIZE bytes" && test "$SIZE" -lt 134217728 && echo "PASS: app wasm < 128MB ceiling" || { echo "FAIL: app wasm >= 128MB or not found"; exit 1; } @echo "==> AC.2b: checking worker wasm exists..." @test -f public/renderer_worker_bg.wasm && echo "PASS: worker wasm exists" || { echo "FAIL: worker wasm not found"; exit 1; } @echo "==> All renderer-split checks passed."_generate-api: nix run ../jacquard_validate-gc-state *ARGS: python3 tools/validate-gc-state.py {{ ARGS }}_validate-gc-jj-state *ARGS: python3 tools/validate-gc-jj-state.py {{ ARGS }}_check-public-env *ARGS: python3 tools/check-public-env.py {{ ARGS }}_check-production-sql *ARGS: python3 tools/check-production-sql.py {{ ARGS }}_check-doc-references *ARGS: python3 tools/check-doc-references.py {{ ARGS }}_check-content-type *ARGS: python3 tools/check-content-type.py {{ ARGS }}_check-proxy-response *ARGS: python3 tools/check-proxy-response.py {{ ARGS }}_workspace-create name: root="$(jj workspace root)" && workspace_path="$(dirname "$root")/{{ name }}" && jj workspace add "$workspace_path" -r @ root="$(jj workspace root)" && workspace_path="$(dirname "$root")/{{ name }}" && cd "$workspace_path" && jj desc -m "{{ name }}" root="$(jj workspace root)" && workspace_path="$(dirname "$root")/{{ name }}" && direnv allow "$workspace_path" && direnv exec "$workspace_path" true_workspace-list: jj workspace list_workspace-forget name: jj workspace forget {{ name }}_status: jj status jj diff --summary_clean: cargo clean rm -rf target/dx