Commit graph

2 commits

Author SHA1 Message Date
Arena Agent
8361a65590 fix(cad): SVG export ignored rotation entirely
Some checks failed
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
Every SVG floor plan containing a rotated element was wrong. arch_svg read
only transform.translation and transform.scale, at all six projection
sites, so a wall yawed 90 degrees exported axis-aligned. A 2 x 6 footprint
came out 2 x 6 instead of 6 x 2.

This is the worst failure mode of the rotation bugs found in this project:
the export succeeds, the file opens cleanly in any viewer, and it shows a
different building. Nothing announces it.

I deferred this during Phase 1 as "a missing feature, not a wrong
calculation". That was the wrong call and PHASE1_STATUS.md now says so.
Silently emitting a different building is not a missing feature.

Fixed by routing all six sites -- box, cylinder/sphere/circle, polygon,
extruded polygon, CSG mesh and arc -- through one project_local() helper
that uses part_model_matrix, the renderer's own transform. Deliberately
not re-derived here: every hand-rolled rotation in an exporter has been
wrong in its own way (arch_stl destructured sin_cos backwards, arch_gltf
produced norm-0.125 quaternions, arch_pdf fed degrees to cos). This
exporter does not get another private copy.

The convention is subtler than it looks and I got it wrong twice while
writing the test. Both plan exporters map to world XZ then negate Z, so
local +X projects to (cos yaw, -sin yaw) and local +Z to
(sin yaw, -cos yaw). That is a reflection, not a rotation: the two model
axes are NOT perpendicular in plan space -- at yaw 30 they are 30 degrees
apart. My first two attempts asserted a rotation and then
perpendicularity, and both failed against real output. Verified against
rot_y_mat arithmetic before believing it. Written down in ARCHITECTURE.md
invariant 6, which previously recorded the bug.

Five tests, chosen so no single symmetry can hide a wrong fix:
- 0 degrees: baseline dimensions.
- 90 degrees: footprint must swap, 2x6 -> 6x2.
- 180 degrees: extents unchanged. Passes even when broken, and is here
  precisely to stop a fix that rotates by the wrong factor from looking
  correct on the 90 degree case alone.
- 45 degrees: no symmetry to hide behind; asserts the diagonal extent
  8/sqrt(2). Tolerance is 0.011 because coordinates are emitted with two
  decimals.
- The projection convention itself, cross-checked against arch_pdf.

Negative-tested: restoring the translation-and-scale projection fails
three of the five.

Also replaced an unchecked mesh.vertices[idx] index in the CSG arm with a
get() -- a malformed mesh would have panicked the exporter.

622 lib + 154 integration, 0 failed.
2026-07-28 19:36:43 +00:00
Arena Agent
b5471e32e3 fix(cad): make the crate buildable, testable and safe to ship
Some checks failed
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
Phases 0-2 of CAD_ASSESSMENT_AND_PLAN.md. The crate did not compile and no
test had ever run; it now builds clean with a green suite.

Build and CI (Phase 0)
- Pin all 33 git dependency manifests to an explicit rev. A branch
  dependency re-resolves on every build and is a code-execution path into
  CI if force-pushed.
- Commit Cargo.lock (540 packages). Producing it required fixing three
  resolution failures the workspace had always had: a non-existent
  makepad-widgets feature, two rusqlite versions both linking sqlite3, and
  four missed CellId call sites in spreadsheet-ui.
- Add .forgejo/workflows/nigig-build.yml.
- Replace five stale CAD docs that contradicted the code with one
  ARCHITECTURE.md; add PHASE0/1/2_STATUS.md and TEST_BASELINE.md.

Correctness (Phase 1)
- Rotation units: transform_point bound sin_cos() backwards, transposed X
  and Z, and applied axes in reverse order, so every exported STL was wrong
  even at zero rotation. It now shares the renderer's matrix helpers.
- GLB quaternions had norm 0.125 (half-angle applied to cos/sin, degrees
  read as radians) - invalid per the glTF spec.
- PDF wall/door/window yaw fed degrees to cos/sin.
- Fix a TOCTOU unwrap in touch picking; viewport.rs now has no unwrap().
- CommandContext gains update_node/insert_node_at/node_index: resize and
  modify were delete+create, silently moving nodes to the end of the scene.
- Wire MAX_UNDO_LEVELS (defined, exported, never read) and switch the undo
  stack to VecDeque; this also made the existing drag-merge logic reachable.
- CadNode::size() returned a fake 1x1x1 for CSG and extruded solids, making
  them unpickable outside a 1x1x1 box at their origin.
- Reject non-finite script input; makepad_csg clamps NaN rather than
  propagating it, so bad input produced silently wrong geometry.

Test baseline: 0 -> 722 passing, 0 failing
- 17 pre-existing failures fixed: 10 real defects (dependency-cycle
  detection, over-allocation of unassigned tasks, quote/backslash
  corruption on save, default rooms lost for all but the first region,
  RGA text ordering) and 7 tests that were themselves wrong, each checked
  against its production caller first.

Security (Phase 2)
- env!("CARGO_MANIFEST_DIR") was used as a runtime path in three places,
  including as the AI agent's working directory. All runtime data now goes
  under app_data_dir().
- Remove the hardcoded LAN LLM endpoint. It is now opt-in via
  NIGIG_CAD_LOCAL_OPENAI_URL/_MODEL and refuses plaintext HTTP to anything
  but loopback.
- Bound and content-sniff AI image attachments (8 MB cap, magic bytes);
  the MIME type came from the filename extension.
- Escape SVG/HTML output, and add SRI to the exported viewer's script tag.
  The pinned model-viewer@3.5.1 does not exist, so every exported viewer
  was silently broken; now 4.0.0 with a verified hash.
- Stop embedding $USER in exported PDFs and logging document content in
  release builds.
- CI now rejects reintroducing the runtime-path and hardcoded-endpoint
  classes; both gates were verified to fail on a reintroduced defect.

Add system_prompt.md and embed it with include_str!. The file was missing
from the repository, so the agent silently used a one-line fallback.
2026-07-28 16:49:30 +00:00