nigig-org/crates/apps/cad/cad-ui/EXECUTION_PLAN.md
Arena Agent 4665973b57
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
docs(cad-ui): add audited remediation execution plan
2026-09-12 07:59:51 +00:00

38 KiB
Raw Permalink Blame History

cad-ui — Remediation Execution Plan

Plan date: 2026-09-12 Audit baseline: e899a271c69efca0e11ae274b879378d2f26485f (main) Scope: crates/apps/cad/cad-ui, its standalone app, and its integration boundary with cad-core and nigig-build Status: Proposed; no implementation tranche below is complete Release posture: Prototype only. Do not promise lossless projects, trustworthy exports, safe AI cancellation, or production-scale CAD until the P0 gates are complete.

This plan supersedes optimistic status comments where code and tests disagree. src/ARCHITECTURE.md is useful descriptive history, but it is not proof that the named invariants hold.


1. Executive verdict

cad-ui is a 41,000-line feature accumulation with substantial local test effort and no trustworthy document boundary. It has multiple overlapping stores and caches, a CadDocument name that wraps only a parts list rather than a versioned lossless project, direct mutations that bypass undo, project switching that can retain another project's state, and save/rebuild paths that can persist a different revision from the one rendered successfully.

The visual surface is materially ahead of the architecture beneath it. Picking, snapping, work planes, exploded views, 2D modes, PDF/SVG/GLB, AI generation, scripting, and screenshots exist as controls, but several use different coordinate/transform models or are approximations presented without qualification. Some output is outright synthetic: F12 encodes a valid PNG of a generated gradient rather than the framebuffer or scene.

The current state is dangerous because it looks more complete than it is. The priority is not another tool button. It is one document, one revision, one transaction path, one project lifecycle, bounded native work, and truthful capability gates.

Current grade: architecture D, data integrity D-, geometry interaction D+, performance safety D, security C-, UX honesty D+, test credibility C.


2. Audit baseline and evidence

2.1 Observed validation

Check Result at baseline Interpretation
cargo test --locked -p cad-ui --lib -- --test-threads=1 795 passed, 1 failed, 20 ignored Not green. The failing semantic wall-classification test in demo.rs is not cosmetic.
cad-core library tests 252 passed Useful dependency baseline, not proof of project or export integrity.
CAD-specific Forgejo workflow Absent CAD regressions are not crate-owned CI gates.
Existing CAD coverage scripts Point repeatedly at removed nigig-build/.../workspace/cad paths A grep that scans nothing can pass and create false confidence.
Runtime project-switch/save/reopen matrix Absent The highest-risk behavior is largely untested end to end.

2.2 Evidence map

  • src/lib.rs, workspace.rs, viewport.rs: oversized stateful UI roots, AI worker, work-plane state, rebuild/export/session coordination.
  • scene_holder.rs, cad_store.rs, project_store.rs, document.rs, persistence.rs: overlapping document, project, parts, and persistence concepts.
  • commands.rs, tools.rs, script_bindings.rs: partial undo coverage, direct mutation, generated commands, script/native CSG boundary.
  • bvh.rs, snap.rs, viewport_input.rs, viewport_2d.rs, viewport_render.rs: invalid acceleration structure assumptions and inconsistent interaction geometry.
  • arch_pdf.rs, arch_svg.rs, arch_gltf.rs, exporters.rs, render_export.rs: divergent export semantics, unbounded workers/materialization, and synthetic screenshot output.
  • demo.rs: currently failing semantic expectation.

3. Release-blocking invariants

These must be encoded in types and tests:

  1. Exactly one open document per CAD session. Source text, canonical entities, selection, undo history, derived scene, caches, and save revision all identify that same document and revision.
  2. Project switches are transactions. Opening/creating/closing a project either replaces all document-owned state or leaves the prior session untouched. No geometry, selection, history, source, worker result, or cache crosses the boundary.
  3. Canonical document wins. cad-core::CadDocument is persisted. Script is an editable artifact with a source revision; it is not used to regenerate away direct edits silently.
  4. Every mutation is a command. Tools, property panels, script rebuilds, paste, AI, imports, layer/material operations, and project load commit through one revision-checked transaction API.
  5. Save means durable. A success message identifies the persisted document revision and is emitted only after write, sync/atomic replace, and manifest update succeed.
  6. Rebuild is two phase. Parse/evaluate/build a candidate under limits, then atomically commit only if its request/document/base revision is current. Empty valid output clears old entities.
  7. Stale async results are harmless. Every rebuild, AI request, export, picker, and expensive derived job has an operation ID, document ID, base revision, cancellation state, and bounded queue.
  8. One transform/coordinate model. Render, pick, snap, marquee, section, explode, work planes, 2D projection, and export consume the same world transforms and units.
  9. No fake mode. A disabled, approximate, or synthetic feature is labelled and gated as such. It is never represented as production output.
  10. Untrusted work is bounded. Script, AI output, attachment decode, CSG, tessellation, BVH, cache, export, and file input all have byte/count/time limits.
  11. Prompting is not delivery. A file dialog launch is not “saved”; only the final picker/copy/write callback can complete the operation.
  12. Tests never touch the production CAD root. Every storage test receives an isolated temporary repository explicitly.

4. Severity-ranked findings

P0 — release blockers

ID Finding Concrete risk
UI-P0-01 No canonical versioned project document; CadDocument in scene_holder.rs is only a shared PartsStore. Source, rendered parts, metadata, and exports can disagree with no authoritative recovery point.
UI-P0-02 Project create/open/switch does not atomically replace all document state. Empty rebuilds can retain stale nodes. One customer's/project's geometry and history can appear in another project.
UI-P0-03 Save may use source/state that did not produce the current successful scene; generated source is lossy. Reopening a “saved” project loses names, domain kinds, materials, layers, visibility, hierarchy, metadata, scale, and direct/script-derived edits.
UI-P0-04 Direct scene mutations bypass document-level undo transactions. Script replacement can leave stale commands. Undo can restore an incoherent mixture of old and new state.
UI-P0-05 Script limits omit source size, dimensions, generated entity/triangle counts, and native CSG interruption. VM deadline cannot stop one native CSG call. Crafted input can hang a worker or exhaust process memory; catch_unwind cannot recover from allocation abort.
UI-P0-06 AI backend choices both construct Claude; streamed output destructively replaces source; cancellation has no request identity. Wrong provider, data loss during partial output, and stale post-cancel output applied to a newer prompt/document.
UI-P0-07 Export requests can spawn unbounded workers and materialize full files; prompted save outcome is not reliably surfaced. CPU/memory exhaustion and false success.
UI-P0-08 CSG cache identity uses pointer address; cache validity relies on a 64-bit hash and has no byte budget. Wrong mesh reuse is possible; memory residency grows without a production ceiling.
UI-P0-09 BVH node/index ranges are not a valid mapping to source triangles. “Accelerated” picking can miss or select the wrong geometry. Shallow tests do not detect it.
UI-P0-10 STEP is selectable despite known invalid topology/schema output in cad-core. Users receive files presented as CAD interchange that other tools may reject or misinterpret.

P1 — major correctness, UX, and security

ID Finding Consequence
UI-P1-01 Work-plane enum labels, grid axes, and point conversion disagree. Drawing on a named plane can place geometry on another plane.
UI-P1-02 Picking, snapping, and marquee use approximations, copy-heavy linear scans, stale dependencies, and mixed world/screen units. Selection changes with zoom/mode or misses visible geometry.
UI-P1-03 Exploded-view transforms diverge from selection/picking/export transforms. User clicks one visual position while the model acts at another.
UI-P1-04 Projection and visual mode labels overstate behavior; render2d is inert and 2D primitives are not faithfully persisted. UI states imply capabilities that do not exist.
UI-P1-05 PDF fabricates CSG footprints; SVG fit/polygon/grid behavior is unsafe or wrong; GLB flattens hierarchy and drops visibility/units. Output differs materially by format.
UI-P1-06 SVG/PDF grid loops can receive invalid spacing. Infinite/huge loops or unusable output.
UI-P1-07 F12 writes a generated gradient, not framebuffer or scene data. A syntactically valid image is falsely represented as a render.
UI-P1-08 Persistence is duplicated, non-atomic in paths, permissive on malformed metadata, and vulnerable to ID/path collisions or traversal. Silent loss, overwrite, or reading/writing outside the intended project directory.
UI-P1-09 Debug logging includes source snippets; AI attachments and prompts contain project data without an explicit privacy boundary. Confidential design information can leave the process or enter logs unexpectedly.
UI-P1-10 Production-root-affecting helpers are callable from tests. A test can delete or mutate real CAD project state.

P2 — maintainability and measured-performance debt

  • viewport.rs (~6.3k lines), workspace.rs (~4.2k), viewport_render.rs (~3k), lib.rs (~2.7k), and commands.rs (~2.5k) mix unrelated responsibilities.
  • Multiple action/event protocols use global/static or weakly correlated state.
  • A large passing unit count overweights tiny helpers and behavior locks while the runtime lifecycle is ignored.
  • Cached derived state has count tests but not ownership/byte/revision accounting.
  • Many comments claim measured optimization without a reproducible, current, target-device artifact.

5. Target architecture

CadApp / Makepad widgets
        │ intents + display state only
        ▼
CadSessionController
  ├─ SessionIdentity { session_id, project_id, document_id }
  ├─ Canonical cad_core::CadDocument @ revision N
  ├─ CommandJournal / UndoBudget
  ├─ Selection + view preferences (revision-aware)
  ├─ RebuildCoordinator
  ├─ JobCoordinator { bounded queues, operation IDs, cancellation }
  └─ ProjectRepository
        │
        ├─ atomic manifest + canonical document
        ├─ optional script artifact @ source revision
        └─ recovery/backup metadata

Derived services (never authoritative)
  ├─ SceneSnapshot @ document revision
  ├─ WorldMesh / render buffers @ document revision
  ├─ BVH @ geometry revision
  ├─ snap indexes @ geometry + work-plane revision
  └─ bounded mesh/CSG cache

Boundary rules

  • Widgets dispatch intents and render immutable snapshots; they do not mutate vectors directly.
  • CadSessionController is the only owner allowed to advance a document revision.
  • ProjectRepository never reads thread-local active-project state; every operation takes typed IDs.
  • Jobs return data only. The controller verifies operation/document/base revision before applying it.
  • cad-core supplies validation, transactions, world transforms, units, and export-neutral mesh traversal.
  • View-only explode/section/selection state never mutates persisted geometry unless committed as an explicit command.

6. Initial budgets

Budget changes require an ADR and measurements. Mobile limits may be lower but never unbounded.

Resource Desktop limit Mobile limit Behavior on limit
Script source 1 MiB 512 KiB Reject before VM creation.
AI response retained 1 MiB 512 KiB Cancel and keep original source unchanged.
Image attachment to AI 10 MiB compressed; 40 MP decoded same Reject before base64/decoded allocation.
Script instructions 10,000,000 3,000,000 Deterministic budget error.
Script call depth 256 128 Deterministic budget error.
Native CSG operation 5 s / 2M output triangles 3 s / 500k Run in killable isolation; abort candidate.
Whole rebuild 30 s 15 s Cancel candidate, retain prior document.
Undo journal 200 commands or 256 MiB 100 or 64 MiB Evict oldest complete transaction; disclose boundary.
Mesh/CSG cache 512 MiB 128 MiB LRU by measured bytes and revision.
Active exports 1 1 Bounded queue of 2; reject the fourth request.
Background CPU jobs min(4, available_parallelism) 2 Shared fixed pool; no per-click thread creation.
Hover pick p95 <= 4 ms on 1M-triangle fixture p95 <= 8 ms on mobile fixture Skip/coalesce stale hover work.
Click pick p95 <= 16 ms p95 <= 24 ms Busy indicator only if asynchronous.
UI event handler p95 <= 8 ms p95 <= 12 ms No disk, network, CSG, tessellation, or full export.
Frame pacing p95 <= 16.7 ms at 60 Hz reference scene p95 <= 33.3 ms at 30 Hz Profile before adding rendering work.
Project manifest 8 MiB 8 MiB Recovery error, never parse unbounded.

cad-core document/entity/triangle/output ceilings apply in addition to this table.


7. Dependency-ordered implementation tranches

Every tranche is one tested commit and one remote-safe push. If a tranche grows beyond reviewable size, split it by the stated exit criterion rather than merging unrelated work.

UI-00 — Truthful CI and baseline repair

Priority: P0 Effort: 23 person-days Depends on: none

Change

  • Add/consume the CAD-owned workflow from cad-core CORE-00.
  • Fix stale coverage paths and make empty source scans fail.
  • Preserve the current demo.rs semantic failure as red until corrected; do not delete or invert it.
  • Inventory all 20 ignored tests with owner, issue, failure reason, and expiry.
  • Separate pure library, integration, and real runtime UI results in CI artifacts.

Tests / exit

  • cad-ui has a reproducible green baseline only after the semantic defect is fixed legitimately.
  • A deliberately broken path makes coverage/gates red.
  • CI fails if ignored count grows or an expiry passes.
  • Both library and standalone binary compile.

Rollback: workflow mechanics may be reverted if the runner is wrong; semantic tests may not be weakened.

UI-01 — Immediate capability containment and honest copy

Priority: P0 Effort: 12 person-days Depends on: UI-00

Change

  • Hide/disable STEP in default builds and label experimental builds unmistakably.
  • Replace F12 “render/screenshot” action with disabled copy until actual capture exists.
  • Hide or label render2d, ray/x-ray modes, unsupported 2D primitives, and formats according to tested capability.
  • Ensure launch/config cannot re-enable a contained capability accidentally.

Tests / exit

  • Default feature builds contain no reachable STEP action.
  • UI snapshots contain no claim that F12 captured the scene while it produces synthetic pixels.
  • One capability matrix drives menu visibility, labels, docs, and dispatch.

Rollback: contained features stay off; rollback cannot restore misleading availability.

UI-02 — Single CadSessionController

Priority: P0 Effort: 812 person-days Depends on: cad-core CORE-03 and CORE-06

Change

  • Introduce a controller owning typed session/project/document identity and canonical revision.
  • Replace scene_holder::CadDocument, loose PartsStore, cad_store, project_store, and dead document.rs authority with adapters to the controller.
  • Make scene/render/cache state derived from document revision.
  • Remove public mutable access to the parts vector and unchecked ID allocation.

Tests / exit

  • Compile-time/API tests show widgets cannot mutate canonical entities directly.
  • Every derived snapshot carries document ID and revision.
  • Multiple viewports observe one document without copying/reconciling authoritative parts.
  • ID exhaustion/collision returns an error, never wraps/reuses.

Migration: keep read adapters for old project metadata; write only the new manifest/document after successful conversion.

Rollback: compatibility adapters can remain for one release, but there is only one mutable owner.

UI-03 — Transactional project repository and switching

Priority: P0 Effort: 69 person-days Depends on: UI-02

Change

  • Make all repository APIs take ProjectId/DocumentId and an injected root; remove thread-local path authority.
  • Validate project IDs as opaque values, never path fragments.
  • Save manifest/document/source with unique temp files, file sync, atomic replace, and parent-directory sync where supported.
  • Model open result as Ready, NeedsMigration, Locked/Busy, Corrupt, UnsupportedFuture, or IoError.
  • Build a candidate session off-screen and swap it atomically only after load/migration/validation succeeds.
  • On switch, cancel and drain jobs; reset undo, selection, tool sessions, temporary geometry, source, explode/section state, and revision-keyed caches.

Tests / exit

  • A/B sentinel test proves no entity, source token, selection, undo command, cache entry, or stale worker result crosses A → B → A.
  • Opening a valid empty project clears every old node.
  • Injected failures at each filesystem step preserve prior durable revision and produce no success message.
  • Traversal/collision/symlink and malformed/future metadata corpora fail closed.
  • All tests use temporary roots; production-root access is structurally impossible under cfg(test).

Migration: preserve legacy files byte-for-byte; import into a new versioned project directory and switch only after verification.

Rollback: point the active manifest back to the last verified revision; never recover by creating a blank project over corrupt data.

UI-04 — Revision-safe two-phase rebuild

Priority: P0 Effort: 68 person-days Depends on: UI-02, UI-03, cad-core CORE-04/05

Change

  • Define RebuildRequest { operation_id, document_id, base_revision, source_hash, source }.
  • Parse/evaluate/build/validate in a candidate document under explicit limits.
  • Commit candidate and source artifact together as one command only if identity and base revision still match.
  • A successful empty result replaces the document with empty; parse/evaluation failure retains prior state.
  • Save only the committed source/document revision; remove default-script restoration from empty user input.

Tests / exit

  • Out-of-order A/B results cannot let A overwrite newer B.
  • Cancel, project switch, editor edit during build, worker crash, empty script, valid-empty output, and save-after-build race tests are deterministic.
  • Reopening a saved revision reproduces canonical serialization and scene hash.
  • Stale commands from a replaced script cannot remain undoable against the new document.

Rollback: prior canonical revision remains available until candidate commit; cancellation is equivalent to no change.

UI-05 — Universal command/undo transactions

Priority: P0 Effort: 710 person-days Depends on: UI-02, UI-04

Change

  • Route tools, transforms, properties, layers, materials, delete/paste, script/AI replacement, imports, and bulk edits through cad-core::DocumentEdit.
  • Group pointer drags into one coalesced transaction with before/after revision.
  • Store bounded inverse patches or immutable before-state, not unbounded full project clones.
  • Clear redo only on successful divergent commit; rejected commands do not alter history.

Tests / exit

  • For every command family: apply → undo restores byte-identical canonical document → redo restores result.
  • Failed command leaves document/history/cache revisions unchanged.
  • Random command sequences preserve core invariants and reverse completely within retained history.
  • Undo budget behavior is deterministic and disclosed in UI.

Rollback: command adapters may call old implementations only inside a validated transaction; no direct-mutation escape hatch remains.

UI-06 — Script sandbox and killable native geometry

Priority: P0 security/performance Effort: 812 person-days Depends on: UI-04, core geometry budgets

Change

  • Enforce source bytes, AST nodes, call depth, instructions, string/array sizes, numeric finiteness/dimension range, entities, vertices, triangles, and output bytes.
  • Preflight predictable geometry costs before native allocation.
  • Move native CSG/tessellation invoked by untrusted script into killable process/isolate boundaries; a Rust thread timeout is not cancellation.
  • Use bounded request/result channels and terminate abandoned operations.
  • Return stable budget/cancel/crash errors with no partial document.

Tests / exit

  • Corpus covers huge dimensions, deep nesting, massive arrays/profiles, infinite loops, one expensive native call, worker crash, memory ceiling, and cancellation.
  • Parent process stays responsive and prior document survives every failure.
  • No catch_unwind test is accepted as evidence against OOM/abort.
  • Limits are identical for user, AI, and imported scripts.

Rollback: disable script execution and retain source editing if isolation is unavailable on a target.

UI-07 — Correct, private, correlated AI generation

Priority: P0 Effort: 58 person-days Depends on: UI-04, UI-06, core exact URL policy

Change

  • Instantiate the selected provider correctly; provider kind and credentials must match.
  • Add request/document/base revision IDs to every command/event and reject stale/duplicate/post-cancel events.
  • Stream into a bounded preview buffer; never replace editor/canonical state until a complete response parses, evaluates, validates, and the user accepts it.
  • Treat timeout partial text as failure, not a valid script.
  • Add explicit consent/data summary before sending source or images to a remote provider; redact logs and never print source snippets.
  • Store secrets through platform credential APIs, not project files or status logs.

Tests / exit

  • Fake providers prove backend selection, stale rejection, cancellation, timeout, malformed response, oversized stream, function call, and project switch behavior.
  • Original source/document is unchanged on every failure path.
  • Network tests assert exact parsed local-host policy and production TLS policy.
  • Privacy UI names provider and data classes before first remote send.

Rollback: AI remains disabled while manual script editing/rebuild continues safely.

UI-08 — Revisioned, collision-safe, byte-bounded caches

Priority: P0 Effort: 57 person-days Depends on: UI-02, core canonical geometry

Change

  • Replace pointer-address CSG identity with stable canonical geometry identity/revision.
  • Do not use a bare 64-bit hash as proof of equality; pair a collision-resistant digest with canonical identity or verify equality.
  • Account actual CPU/GPU bytes, ownership, document ID, geometry revision, dependencies, and last use.
  • Implement LRU/clock eviction under §6 limits and purge on project close.
  • Make invalidation dependency-driven rather than scattered manual clears.

Tests / exit

  • Forced hash collision cannot return another mesh.
  • Allocator address reuse cannot create a hit.
  • Parameter edit invalidates; pure transform/material edit follows the canonical local/world mesh contract.
  • A/B project switch and eviction tests prove residency returns below budget.
  • Metrics expose hit/miss/build/eviction/bytes, not entry count alone.

Rollback: cache can be disabled for correctness; uncached path must remain bounded.

UI-09 — Replace the BVH and prove picking differentially

Priority: P0 correctness Effort: 58 person-days Depends on: UI-08

Change

  • Build leaves over a stable primitive-index permutation with valid half-open ranges.
  • Validate node bounds, child indices, reachability, no cycles, full primitive coverage, and no duplicate ownership.
  • Traverse near-first with robust slab tests and correct transformed triangles.
  • Build/rebuild off the UI thread, revision-keyed and cancellable.

Tests / exit

  • Randomized differential raycasts compare BVH nearest hit with brute force across empty, degenerate, overlapping, transformed, huge, and non-finite-rejected scenes.
  • Structural validator checks every generated tree.
  • Mutation/project-switch tests reject stale BVHs.
  • Performance meets picking budgets without changing hit identity.

Rollback: use bounded brute force for small scenes and disable hover on large scenes; never use a known-invalid BVH.

UI-10 — One coordinate, work-plane, and interaction model

Priority: P1 Effort: 812 person-days Depends on: UI-02, UI-09, core world transforms/units

Change

  • Define world handedness/up axis, camera rays, plane basis (origin, u, v, normal), screen/world tolerance conversion, and unit conversion once.
  • Derive grids, cursor conversion, drawing tools, snap, measure, and labels from the same plane basis.
  • Use exact world geometry/BVH for click/hover; derive marquee from projected bounds/triangles under a documented containment/intersection rule.
  • Key snap dependencies to geometry/plane/camera revisions; eliminate copy-heavy full scans.
  • Apply view-only explode/section transforms consistently to draw and interaction, while export uses canonical geometry unless user explicitly commits a transform.

Tests / exit

  • Round-trip screen → ray → plane → screen tests for every named plane and rotated custom plane.
  • Golden rays/selections across perspective/orthographic and viewport sizes.
  • Snap identity remains stable across zoom/DPI; tolerance is specified in pixels then converted once.
  • What is drawn, highlighted, measured, and selected agrees within tolerance.

Rollback: disable inconsistent planes/modes individually through the capability matrix.

UI-11 — Rendering truth and real capture

Priority: P1 Effort: 58 person-days Depends on: UI-08, UI-10

Change

  • Make every view/shading mode map to a tested renderer behavior; rename approximations.
  • Apply hierarchy, scale, visibility, normals, and materials from canonical scene derivation.
  • Implement F12 as actual pass/framebuffer readback or an explicit scene render at chosen resolution.
  • Encode off-thread after bounded pixel allocation; correlate completion to operation/document/revision.
  • Surface readback/encode/picker/write failures.

Tests / exit

  • Screenshot pixels change predictably with scene/camera and are not the old synthetic gradient.
  • Golden image tests use tolerances and retain failure artifacts; structural PNG tests are supplemental only.
  • Hidden/scaled/hierarchical fixtures match pick bounds and export bounds.
  • Zero/huge resolutions and GPU readback failure are bounded errors.

Rollback: capture action stays disabled if a platform cannot provide correct readback.

UI-12 — One bounded export coordinator

Priority: P0/P1 Effort: 57 person-days Depends on: UI-03, UI-08, cad-core CORE-07

Change

  • Replace per-request thread spawning with one bounded coordinator/shared pool.
  • Define ExportRequest { operation_id, document_id, revision, format, options, destination }.
  • Snapshot one immutable canonical revision, stream through core's world-mesh pipeline, and use counting/cancellable writers.
  • Treat dialog launch, serialization, destination copy, sync, and final delivery as distinct states.
  • Cancel/reject stale or duplicate requests and return structured metrics/warnings.

Tests / exit

  • Four rapid requests produce one active, two queued, one explicit rejection.
  • Prompt cancellation is Cancelled, not Saved or Failed.
  • Project switch cannot deliver old output under the new project's name/status.
  • Partial write, disk full, unwritable path, callback loss, and worker panic never emit success.
  • Peak memory/output obey core/UI budgets.

Rollback: disable asynchronous export dispatch and permit one synchronous developer-only export outside UI; do not restore unbounded spawning.

UI-13 — PDF/SVG/GLB and 2D capability correction

Priority: P1 Effort: 1015 person-days Depends on: UI-10, UI-12, core format pipeline

Change

  • Define a supported-semantics matrix per format before code changes.
  • PDF/SVG consume one finite 2D projection service; validate paper, scale, bounds, and grid spacing before loops.
  • Stop fabricating CSG footprints. Unsupported exact outlines are warnings/errors, not guessed rectangles.
  • Correct SVG fitting/polygon closure and escape all text/options.
  • GLB applies full world transforms or preserves hierarchy deliberately, carries units in metadata, honors visibility, validates accessors/alignment/counts, and bounds buffers.
  • Either implement lossless rect2d/circle2d/polygon2d/render2d persistence or keep them disabled.

Tests / exit

  • Cross-format golden fixture compares supported bounds, visibility, entity count, and units.
  • Independent PDF/SVG/GLB parsers validate output; a browser token check alone is insufficient.
  • Grid spacing zero/negative/NaN/subnormal and giant page ranges terminate with errors.
  • GLB re-import verifies semantics, not just JSON chunks.
  • Capability matrix is generated/tested against menus and docs.

Rollback: disable the affected format/mode; never silently fall back to fabricated geometry.

UI-14 — Lifecycle-aware performance and code decomposition

Priority: P2 after correctness Effort: 812 person-days Depends on: UI-02 through UI-13

Change

  • Split controller, repository, job coordination, tool state, interaction queries, renderer, and widgets out of god files along actual ownership boundaries.
  • Stop timers/redraw and heavy hover work when hidden, idle, terminal, or superseded.
  • Coalesce editor rebuilds, hover picks, saves, and cache rebuilds.
  • Add spans/metrics for event, script, CSG, scene derivation, BVH, pick, draw submission, GPU frame, export, queue depth, and bytes.
  • Profile target scenes before algorithmic optimization.

Tests / exit

  • No dependency cycle recreates widget-to-storage authority.
  • Idle hidden CAD view performs no continuous rebuild/pick/export work.
  • Reference scene meets §6 budgets on declared hardware/toolchain/commit.
  • Metrics are disabled/low overhead by default and contain no project content.

Rollback: revert one extraction at a time; controller/repository invariants remain intact.

UI-15 — Runtime, migration, and adversarial release matrix

Priority: P0 release gate Effort: 610 person-days plus platform/device time Depends on: all preceding required tranches

Change

  • Add real Makepad runtime tests for create/open/edit/save/restart/switch/undo/export/cancel and desktop/mobile interaction.
  • Add migration corpus, randomized command/BVH tests, script/AI adversarial corpus, and format interop jobs.
  • Remove ignores or convert genuine infrastructure blockers into required nightly/device jobs with expiry.
  • Run long-session soak with cache/job/file metrics and forced failures.

Tests / exit

  • Zero unexplained failures and zero expired ignores.
  • A/B isolation and save/reopen tests pass across process restart.
  • Runtime tests assert actions and durable state, not only widget visibility.
  • Soak stays within memory/job/file budgets and drains cleanly on exit.
  • nigig-build integration passes against the same CAD contracts.

Rollback: release is blocked. Test infrastructure failure is not permission to ship untested lifecycle behavior.


8. Project migration and recovery

  1. Check in sanitized legacy project fixtures: manifest records, active marker, .cad scripts, direct-edited parts, empty scripts, malformed metadata, and ID collisions.
  2. Never overwrite legacy files in place. Create a new versioned project directory beside them.
  3. Decode script as an artifact. If a script rebuild is valid, compare it with any recoverable parts state and report divergence; do not choose silently.
  4. Convert to cad-core::CadDocument, validate, persist revision 1 atomically, reopen it, and compare canonical hash before activating it.
  5. Preserve unknown metadata and domain hints in extension fields.
  6. Map the old zero-scale default through core's explicit migration rule and retain a warning.
  7. Corrupt/unsupported projects open in recovery/read-only mode with original bytes available. They do not become empty demos.
  8. Keep a last-known-good revision and manifest pointer so interrupted saves can roll back without guessing.
  9. Remove the old writer after one compatibility release; retain a read-only importer as long as supported by product policy.

9. Required CI commands

At minimum for every cad-ui change:

cargo fmt -p cad-ui -- --check
cargo check --locked -p cad-core --all-targets
cargo test --locked -p cad-core --all-targets -- --test-threads=1
cargo check --locked -p cad-ui --all-targets
cargo test --locked -p cad-ui --lib -- --test-threads=1
cargo clippy --locked -p cad-ui --all-targets -- -D warnings
cargo check --locked -p nigig-build --all-targets
git diff --check

Required specialized jobs as their tranches land:

cargo test --locked -p cad-ui --test project_lifecycle -- --test-threads=1
cargo test --locked -p cad-ui --test script_limits -- --test-threads=1
cargo test --locked -p cad-ui --test bvh_differential -- --test-threads=1
cargo test --locked -p cad-ui --test export_interop -- --test-threads=1
cargo test --locked -p cad-ui --test runtime_ui -- --test-threads=1

CI rules:

  • Do not suppress cargo/clippy failures with || true.
  • Do not count a process that exits before AppStarted as a UI assertion pass or failure; classify it as harness failure and block the runtime job.
  • No source scan may pass with zero files.
  • Test count floors are secondary; named lifecycle/invariant tests are mandatory.
  • External parser/device jobs may be scheduled separately but are hard release gates.

10. Release gates

  • cad-core canonical document, graph, transform, geometry, and world-mesh prerequisites are complete.
  • One CadSessionController owns one typed project/document/revision.
  • Project A/B switching has zero state leakage, including stale async results.
  • Save/reopen is lossless for the supported canonical schema and success is durable.
  • Every mutation is transactional and undo/redo round trips canonical bytes.
  • Script and native CSG workloads are bounded and killable; failures preserve prior state.
  • AI backend selection, privacy consent, request correlation, cancellation, and accept-before-commit are proven.
  • Cache collisions/address reuse cannot return wrong geometry; byte ceilings are enforced.
  • BVH passes structural and randomized brute-force differential tests.
  • Render/pick/snap/marquee/work-plane/explode use one coordinate/transform contract.
  • F12 captures actual pixels or is disabled.
  • Export concurrency/output/memory are bounded and final delivery outcome is surfaced.
  • Enabled PDF/SVG/GLB/STL/DXF formats pass independent semantic checks.
  • STEP and unimplemented 2D features remain disabled unless their own gates pass.
  • cad-ui has zero test failures and zero unexplained/expired ignores.
  • Desktop and supported mobile runtime lifecycle tests pass.
  • No storage test can access the production CAD root.
  • Performance budgets are measured on declared reference hardware with artifacts.

11. Delivery and remote-safety protocol

For each UI-NN tranche:

  1. Record the starting SHA and ensure the worktree is clean.
  2. Add a regression test that fails against the parent revision.
  3. Run the tranche-specific tests, the core consumer matrix, and git diff --check.
  4. Commit only the tranche, using its ID in the message.
  5. Run git fetch origin main immediately before push.
  6. If remote moved, inspect and rebase/merge without discarding either side; rerun all tests after resolution.
  7. Push without force and verify the remote contains the exact commit before beginning the next tranche.
  8. If authentication is unavailable, report the blocker and keep the tested commit local. Never claim it was pushed and never overwrite remote work later to make history match.

Feature containment is the default rollback for unsafe optional capabilities. Data changes roll back by switching the manifest to the prior verified canonical revision or restoring preserved legacy bytes—not by discarding state, generating defaults, or accepting stale worker output.


12. Critical path and cross-plan dependencies

UI-00 → UI-01
  │
  └─ cad-core CORE-03 + CORE-06 → UI-02 → UI-03 → UI-04 → UI-05
                                      │       │       └→ UI-06 → UI-07
                                      │       └→ UI-08 → UI-09 → UI-10 → UI-11
                                      └─ cad-core CORE-07 ─────────────→ UI-12 → UI-13
                                                                            └→ UI-14 → UI-15
  • nigig-build must establish a real project-context/repository boundary before adopting this session, or CAD state will still leak at the host-app level.
  • cad-core owns canonical transforms, validation, and mesh traversal; cad-ui must not fork them for schedule convenience.
  • Makepad API drift must be resolved in the pinned dependency revision or workspace integration, never by editing Cargo's checkout.
  • STEP certification is not on the release critical path because the safe state is disabled.