# nigig-build — Remediation Execution Plan **Plan date:** 2026-09-12 **Audit baseline:** `e899a271c69efca0e11ae274b879378d2f26485f` (`main`) **Scope:** `crates/apps/nigig-build` and its project-scoped integrations with CAD, documents, spreadsheets, scheduling, invoices, and solar design **Status:** Proposed; no implementation tranche below is complete **Release posture:** **Do not represent this as an operational construction-management system. It is a prototype shell containing three explicit primary-tab scaffolds and several global, lossy, or mathematically unsafe workspaces.** --- ## 1. Executive verdict The app has broad product ambition but no reliable project boundary. A construction app that opens CAD, spreadsheet, invoice, schedule, and solar tools without making a typed project context mandatory does not have separate projects; it has multiple views over mutable global state. That is the central defect and must be repaired before adding workflows. The visible completeness is misleading: - Materials, Workers, and Progress—the primary navigation for core construction work—literally tell the developer to replace the scaffold. - Desktop does not provide a real project-selection/open lifecycle. Mobile renders only the first three projects. - Spreadsheet, invoice, schedule, and calculator state is global rather than project-owned. - Project-management production code concatenates local copies of modules that also exist as separately tested files. Tests can be green against code the app does not execute. - Scheduling uses convergence loops rather than a validated DAG algorithm. One critical-path loop can fail to terminate; automatic scheduling can stop without convergence and still return success. - Invoice data is pipe-delimited line-item text written to a `.json` filename. It drops invoice identity, parties, dates, terms, currency, tax, discount, shipping, and other visible metadata. Write failures are discarded while UI reports success. - Financial and engineering inputs use unrestricted `f64`. NaN, infinity, negative values, rounding ambiguity, unsafe array topology, and physically incomplete solar designs are not rejected. - CI contains a large block of CAD checks aimed at a directory that no longer exists and omits the runtime targets that are broken. The 94 passing library tests and 264 passing non-runtime integration tests are not an acceptance signal. Production/test source divergence invalidates part of that evidence, and all 97 runtime UI cases terminate with exit code 127 before exercising their assertions. **Current grade:** architecture D-, data integrity D-, scheduling correctness F, financial correctness F, engineering safety F, UX completeness D, security C-, test credibility D. --- ## 2. Evidence and current baseline ### 2.1 Observed validation | Check | Result | Honest interpretation | |---|---:|---| | `cargo test --locked -p nigig-build --lib` | **94 passed** | Pure/local regression value only. | | Non-runtime integration cases | **264 passed** | Many duplicate algorithms or extracted modules instead of production wiring. | | Runtime UI cases | **0 of 97 exercised; every case exits 127 before assertions** | Harness/startup failure, not 97 product assertion failures and certainly not a pass. | | `.forgejo/workflows/nigig-build.yml` | Present | Misnamed “CAD”, scans removed CAD paths, suppresses/omits meaningful broken targets. | | Primary Materials/Workers/Progress screens | Explicit scaffolds | Core advertised workflows do not exist. | ### 2.2 Primary evidence locations - `src/construction_frame/pages/{materials,workers,progress}.rs`: identical scaffold structure and explicit replacement copy. - `src/construction_frame/pages/workspace/project/mod.rs`: project list lifecycle, per-draw I/O, adaptive desktop/mobile divergence, spreadsheet underflow, workspace routing without mandatory context. - `src/construction_frame/pages/workspace/project_management/{mod,logic,persistence,task,history}.rs`: production/test duplication, unconstrained graph/date logic, global persistence, full-string history. - `src/construction_frame/pages/workspace/invoice/mod.rs`: build-tree storage path, lossy fake JSON, discarded save errors, unrestricted financial values. - `src/construction_frame/pages/workspace/solar_calculator/{mod,engine}.rs`: parse-to-zero behavior, unchecked indices, unused autonomy input, incomplete array/battery/electrical design. - `.forgejo/workflows/nigig-build.yml`, `tools/test-cad-coverage.sh`, `tools/test-cad-widget-coverage.sh`: stale ownership and false-positive gates. --- ## 3. Non-negotiable product invariants 1. **No workspace without `ProjectContext`.** CAD, documents, spreadsheets, invoices, schedules, solar designs, materials, workers, and progress receive a typed `ProjectId`; they cannot open or persist with an implicit global project. 2. **One project repository.** All project data uses one injected repository rooted in the platform app-data directory. No runtime path is derived from `CARGO_MANIFEST_DIR`. 3. **Versioned data, atomic commits.** Every aggregate has schema version, aggregate ID, project ID, revision, timestamps, and checksum/integrity metadata where appropriate. Successful writes are atomic and errors reach the UI. 4. **No corruption-to-demo.** Missing, empty, corrupt, future-version, and valid-empty are distinct states. Demo fixtures require an explicit command and are never recovery behavior. 5. **Production code is tested directly.** There is one implementation of task, scheduling, persistence, invoice math, and spreadsheet commands. Integration tests import it rather than copying it. 6. **Valid graph before schedule.** Task IDs are unique; dependencies exist; self-links/cycles are rejected; dates/durations/calendars are bounded. Scheduling is deterministic and terminates in O(V+E) for the supported model. 7. **Money is not binary floating point.** Amounts use checked minor units/fixed decimal, explicit ISO currency, explicit tax/rounding policy, and bounded quantities. 8. **Engineering output is qualified.** A solar result is either a validated preliminary design with assumptions/warnings or a blocked/incomplete result. It is never presented as safe system sizing from an incomplete formula. 9. **All primary navigation is honest.** Scaffold or unavailable workflows are marked unavailable; production labels appear only when acceptance criteria are met. 10. **No I/O in draw.** Rendering reads in-memory snapshots. Repository load/save and heavy calculation run through lifecycle events and bounded jobs. 11. **Desktop and mobile share the same domain actions.** Adaptive layout changes presentation, not project identity, data, limits, or business rules. 12. **PII and commercial records have lifecycle controls.** Worker/client/contact data has purpose, access boundary, export policy, and deletion/retention behavior. --- ## 4. Severity-ranked findings ### P0 — release blockers | ID | Finding | Failure mode | |---|---|---| | BUILD-P0-01 | Workspaces can open without selecting/binding a project; each persists globally. | Data entered for Project A appears in Project B or is overwritten by it. | | BUILD-P0-02 | Desktop project creation does not establish an active project; desktop cards are not a real open/select workflow. Mobile exposes only three records. | Users cannot reliably navigate projects, and platform behavior diverges. | | BUILD-P0-03 | Runtime persistence uses build/source-tree paths in invoice and project-management code. | Installed/read-only builds fail or write into developer checkout; multiple users/projects collide. | | BUILD-P0-04 | Writes are non-atomic or discarded, and UI can say “Saved” unconditionally. | Silent durable-data loss. | | BUILD-P0-05 | Project-management `mod.rs` contains concatenated shadow implementations while extracted modules are separately tested. | Tests and production execute different scheduling/persistence logic. | | BUILD-P0-06 | Critical-path propagation uses an unbounded `while changed`; automatic scheduling stops at `tasks.len() * 2` without proving convergence. | Hang, wrong dates, or wrong critical path with no error. | | BUILD-P0-07 | Duplicate/missing task IDs, dangling dependencies, cycles, negative/huge durations and excessive spans are not a hard precondition failure. | Order-dependent or non-terminating schedules and integer/date overflow. | | BUILD-P0-08 | Invoice `.json` is a lossy pipe format and only persists line items. | Saved invoice is not the invoice shown to the user; legal/commercial metadata disappears. | | BUILD-P0-09 | Invoice quantity/price/tax/discount/shipping use unrestricted `f64` and accept malformed, negative, NaN, or infinite values. | Invalid totals, non-deterministic rounding, and unrepresentable persisted output. | | BUILD-P0-10 | Spreadsheet aggregate actions subtract before checking row/column zero. | Debug panic or release underflow/wrong cell access at the first row/column. | | BUILD-P0-11 | Solar output omits critical electrical and design constraints but is presented as a system design. | Unsafe strings, controllers, batteries, inverter, conductors, or protection can be recommended. | ### P1 — major product, security, and correctness gaps | ID | Finding | Consequence | |---|---|---| | BUILD-P1-01 | Materials, Workers, and Progress primary tabs are explicit scaffolds. | The advertised core product workflow is absent. | | BUILD-P1-02 | Project list is reloaded during `draw_walk`; adaptive transitions use disk as synchronization. | UI-thread I/O, jank, hidden error handling, and state races. | | BUILD-P1-03 | Timestamp-derived project IDs can collide; project IDs are used without a unified path-safe type. | Record overwrite or path confusion. | | BUILD-P1-04 | Schedule and invoice undo store full serialized strings and omit aggregate-level transaction semantics. | Memory growth and partial undo across visible metadata. | | BUILD-P1-05 | Parsers replace invalid input with defaults/zero and deserializers seed plausible records. | User error/corruption becomes believable but false business data. | | BUILD-P1-06 | Schedule serialization is hand-rolled and permissive. | Escaping, forward-compatibility, and malformed-data behavior are unreliable. | | BUILD-P1-07 | Invoice “Save As” accepts a filename into a joined path and does not use a final picker/delivery lifecycle. | Traversal/overwrite risk and misleading saved destination. | | BUILD-P1-08 | `days_of_autonomy` is collected but not applied to capacity; battery count ignores voltage topology. | Results contradict entered requirements. | | BUILD-P1-09 | PV sizing omits temperature-corrected Voc, MPPT window/current, parallel-string current, irradiance/weather, inverter limits, conductor/protection, and applicable code checks. | A numerically neat result is not an electrically valid design. | | BUILD-P1-10 | Worker/client/commercial data lacks an explicit data-protection and access model. | PII or pricing can be disclosed or retained without policy. | | BUILD-P1-11 | Tool copy and demo records look operational. | Users may mistake fixtures for their project records. | ### P2 — maintainability, performance, and UX debt - Multi-thousand-line widgets combine domain, persistence, formatting, hit testing, keyboard input, and rendering. - Mobile and desktop handlers duplicate actions and differ semantically. - Fixed mobile project buttons make list behavior non-scalable and inaccessible. - Formula/schedule operations lack observable cost and cancellation. - There is no explicit offline conflict model if multi-device storage is added later. - CI spends substantial time on stale CAD source scans while meaningful production runtime behavior is absent. --- ## 5. Target architecture ```text BuildApp / Makepad views │ user intents ▼ ProjectSession ├─ ProjectContext { ProjectId, revision, permissions/capabilities } ├─ WorkspaceRouter (refuses MissingContext) ├─ ProjectRepository └─ Aggregate controllers ├─ ScheduleController -> Schedule aggregate ├─ SpreadsheetController -> Workbook reference/aggregate ├─ InvoiceController -> Invoice aggregate ├─ SolarDesignController -> PreliminarySolarDesign aggregate ├─ MaterialsController -> Material ledger/procurement links ├─ WorkersController -> roster/assignment/attendance ├─ ProgressController -> evidence + computed progress └─ CadSession / DocsSession (typed project/document references) ProjectRepository /manifest.json /aggregates//.json /attachments/ /journal/... ``` ### Domain/repository rules - IDs are opaque random 128-bit values (or another reviewed collision-resistant type), never timestamps or filenames. - Repositories accept typed project/aggregate IDs and an injected root; UI code cannot construct storage paths. - Each aggregate update is revision-checked and returns a durable commit result. - Makepad widgets depend on controller traits and view models, not `std::fs`. - Cross-workspace references contain project ID and target aggregate ID and are validated before commit. - Derived totals, schedule dates, and progress are recomputed from typed source data, not independently edited copies. --- ## 6. Initial safety and performance budgets | Resource | Initial limit/target | Enforcement | |---|---:|---| | Projects per local repository | 10,000 | Paginated/virtualized query; never load all in draw. | | Aggregate file input | 16 MiB | Check metadata/read cap before deserialize. | | Schedule tasks | 10,000 | Decoder/command validation. | | Schedule dependency edges | 100,000 | Decoder/graph builder. | | Task duration | 1–36,500 working days | Typed constructor. | | Schedule span | 100 years | Calendar validation before arithmetic. | | Scheduler complexity | O(V+E); p95 < 100 ms for 10k tasks/100k edges on reference runner | Benchmark and complexity review. | | Invoice line items | 10,000 | Command validation and virtualized UI. | | Invoice serialized bytes | 16 MiB | Repository. | | Money absolute amount | Product-configured, default <= 9×10^15 minor units | Checked `i64` arithmetic; overflow is error. | | Quantity decimal | <= 6 fractional digits and configured non-negative maximum | Fixed-decimal constructor. | | Workbook | 100,000 non-empty cells, 1,000,000 dependency edges | Workbook engine. | | Formula bytes / AST depth | 8 KiB / 128 | Parser before evaluation. | | Formula recalculation | p95 < 100 ms for reference 100k-cell workbook; cancellable beyond one frame | Worker + benchmark. | | Undo | 200 commands or 64 MiB per aggregate | Bounded journal by measured bytes. | | UI event handler | p95 < 8 ms desktop / 12 ms mobile | No I/O or large calculation. | | Repository save | debounced <= 500 ms; explicit save completion reports final durability | Bounded single-writer per project. | | Attachment | 25 MiB each, 1 GiB/project default quota | Streamed content store; configurable policy. | A budget failure is a named error and leaves the last durable aggregate intact. It is never converted to zero, an empty list, or demo content. --- ## 7. Dependency-ordered implementation tranches ### BUILD-00 — Make CI test the product that ships **Priority:** P0 **Effort:** 2–4 person-days **Depends on:** none **Change** - Remove/move stale CAD gates aimed at `crates/apps/nigig-build/.../workspace/cad`; CAD is now owned by `cad-core`/`cad-ui` workflows. - Make every source scan assert a non-empty target set. - Compile/test production module paths rather than copied integration algorithms. - Repair runtime UI startup so tests reach `AppStarted`; classify exit 127 as harness failure. - Run library, integration, binary, runtime UI, clippy, supply-chain, and migration jobs separately with artifacts. **Tests / exit** - Deliberately empty a gate target and prove CI fails. - Add a production-only mutation fixture and prove integration tests catch it. - At least one runtime test proves an assertion executes after app startup on each supported CI platform. - No command suppresses Cargo failure and then reports green from filtered output. **Rollback:** CI mechanics may be corrected; stale scans and unexercised-runtime green status may not return. ### BUILD-01 — Immediate containment and honest navigation **Priority:** P0/P1 **Effort:** 1–2 person-days **Depends on:** BUILD-00 **Change** - Label Materials, Workers, and Progress as unavailable prototypes or remove them from production navigation. - Mark schedule, invoice, spreadsheet, solar, and CAD as project-scoped and block entry when no project is selected. - Remove unconditional “Saved” copy from invoice and project-management actions. - Label solar output “unvalidated estimate—not an electrical design” until BUILD-10 passes. - Visually identify demo/template records and never load them automatically as user state. **Tests / exit** - Capability matrix drives navigation and copy on desktop/mobile. - No missing-context route reaches a mutable workspace. - Simulated write failure cannot display a save-success message. - No scaffold is presented as an operational feature. **Rollback:** unsafe/incomplete capabilities remain blocked or labelled; rollback cannot restore deceptive copy. ### BUILD-02 — Mandatory typed `ProjectContext` **Priority:** P0 **Effort:** 5–8 person-days **Depends on:** BUILD-01 **Change** - Add typed `ProjectId`, `AggregateId`, `ProjectContext`, and explicit `NoProjectSelected` state. - Implement one `ProjectSession` and one router; every workspace constructor/action receives context. - Replace timestamp project IDs with collision-resistant opaque IDs. - Implement project select/open/close/delete/archive actions once, shared by adaptive views. - Replace fixed three-item mobile controls with a virtualized, paginated list; provide the same lifecycle on desktop. **Tests / exit** - Compile/API tests prevent repository/workspace mutation without `ProjectContext`. - A/B sentinel suite proves schedule, workbook, invoice, solar, CAD, and documents cannot cross project IDs. - Creating/selecting/opening the 4th and 1,000th project works on mobile and desktop. - ID collision injection is handled without overwrite. **Migration:** map legacy timestamp IDs to new opaque IDs through a durable lookup table; never derive a path from the old raw value. **Rollback:** retain a read-only legacy ID alias, but new writes always use typed IDs. ### BUILD-03 — Versioned atomic `ProjectRepository` **Priority:** P0 **Effort:** 6–9 person-days **Depends on:** BUILD-02 **Change** - Create an injected repository root from platform app-data; ban runtime `CARGO_MANIFEST_DIR` paths. - Define versioned project manifest and aggregate envelope with project/aggregate ID, revision, created/updated timestamp, payload kind, and schema version. - Use unique same-directory temp files, write/flush/sync, atomic replace, and directory sync where supported. - Serialize with a maintained codec rather than hand-built JSON. - Distinguish missing, valid empty, corrupt, unsupported future, permission, lock/conflict, quota, and I/O errors. - Serialize writes per project and reject stale expected revisions. **Tests / exit** - Fault injection at create/write/flush/sync/rename/manifest steps preserves the previous revision. - Concurrent stale writers receive conflicts rather than last-writer overwrite. - Corrupt/future/truncated/oversized files never become empty or demo state. - Symlink/path traversal and read-only-root tests fail safely. - No `std::fs` remains in widget modules except a reviewed picker handoff adapter. **Migration:** copy legacy global/build-tree files into a quarantine area, parse with bounded readers, assign project explicitly, write/reopen/verify new aggregate, then mark legacy source migrated. Ambiguous global state requires user choice. **Rollback:** manifest points to the last verified revision; preserve original legacy bytes. ### BUILD-04 — Eliminate project-management source divergence **Priority:** P0 **Effort:** 3–5 person-days **Depends on:** BUILD-00, BUILD-03 **Change** - Make `project_management/mod.rs` only compose/import `task`, `logic`, `persistence`, `history`, `interaction`, and `renderer` modules. - Remove concatenated duplicate definitions and comments describing inline copies as intentional. - Move pure domain/scheduler code into a Makepad-independent module or small crate. - Make production widget call exactly the functions imported by tests. **Tests / exit** - Static uniqueness test reports one definition of each core task/scheduler/serializer type/function. - Existing tests are moved to/import the production module with no algorithm copies. - Mutation testing of a production scheduler branch makes the corresponding integration test fail. - Public API docs name one source of truth. **Rollback:** revert as a unit if module registration breaks, but do not keep duplicate algorithms active. ### BUILD-05 — Validated deterministic scheduling engine **Priority:** P0 **Effort:** 7–11 person-days **Depends on:** BUILD-04 **Change** - Define typed task/dependency IDs, positive working-day durations, supported dependency relation (initially Finish-to-Start unless others are fully implemented), lag bounds, calendar, and date domain. - Validate unique IDs, references, self-links, cycles, hierarchy, milestones, duration/date bounds, and edge/task limits before calculation. - Topologically schedule earliest starts/finishes in O(V+E); reject rather than “iterate until maybe stable.” - Compute latest dates/slack/critical path in reverse topological order against one explicit project finish. - Return `ScheduleResult` with warnings and calculation revision; never mutate input partially. **Tests / exit** - Golden DAGs, multiple roots/sinks, diamonds, milestones, lag, calendars, unordered input, duplicate/dangling/self/cyclic graphs, and boundary dates. - Property tests prove every valid dependency constraint and deterministic output under input permutation. - Differential fixtures compare a reviewed reference implementation/tool for the supported subset. - Scheduler terminates and meets §6; no `while changed` remains. **Rollback:** retain manual dates and disable automatic scheduling; do not restore best-effort unconverged output. ### BUILD-06 — Project-scoped schedule persistence and commands **Priority:** P0/P1 **Effort:** 5–8 person-days **Depends on:** BUILD-03, BUILD-05 **Change** - Persist a versioned `Schedule` aggregate under project context. - Route add/edit/move/resize/link/delete/indent/bulk operations through revision-checked commands that validate and schedule a candidate before commit. - Use bounded typed inverse commands rather than full serialized strings. - Separate explicit “create demo schedule” from open/recovery. - Preserve user-entered constraints and distinguish them from computed dates. **Tests / exit** - Apply → undo → redo restores canonical aggregate bytes/results. - Rejected link/cycle/date edit leaves schedule/history/revision unchanged. - A/B project and restart tests preserve independent schedules. - Corrupt state opens recovery; valid empty remains empty. - Save success waits for repository durability. **Rollback:** switch manifest to prior schedule revision; no demo seeding. ### BUILD-07 — Spreadsheet boundary and correctness hardening **Priority:** P0/P1 **Effort:** 6–10 person-days across this app and `spreadsheet-ui` **Depends on:** BUILD-02, BUILD-03 **Change** - Bind workbook ID to project context and remove global `WorkspaceModel::load_saved()`/`save()` from adaptive transitions. - Share one in-memory workbook controller between desktop/mobile; layout switch is not a disk synchronization protocol. - Fix row/column-zero subtraction by checking before access and centralizing range/neighbor operations. - Enforce cell/formula/dependency/AST budgets, cycle handling, finite numeric semantics, and cancellable incremental recalculation. - Persist workbook revision atomically through `ProjectRepository` or a repository adapter with the same contract. **Tests / exit** - First row/column, empty/single/multi-cell selections, reversed ranges, max boundaries, and aggregate actions do not panic or underflow. - Desktop ↔ mobile resize preserves unsaved edits without disk round trip. - A/B project and restart tests preserve distinct workbooks. - Formula cycles, huge ranges, depth bombs, non-finite results, and cancellation are deterministic bounded errors. **Rollback:** disable affected aggregate shortcuts and keep manual cell edit; never access wrapped coordinates. ### BUILD-08 — Lossless typed invoice aggregate and migration **Priority:** P0 **Effort:** 6–9 person-days **Depends on:** BUILD-03 **Change** - Define `Invoice` with ID, project ID, number, status, issuer snapshot, client snapshot, billing/service address, issue/due date, currency, terms, references, line IDs/items, discounts, shipping, taxes, notes, revision, and audit timestamps. - Use checked minor-unit/fixed-decimal `Money`, fixed-decimal `Quantity`, ISO currency, and typed tax rate/category. No financial `f64`. - Define line/tax/discount/rounding order and inclusive/exclusive policy explicitly. - Serialize real versioned JSON (or documented codec) losslessly and validate on decode. - Make invoice number uniqueness project/account scoped and enforce status transitions. **Tests / exit** - Every visible field survives save/reopen and undo/redo. - Currency mismatch, overflow, negative disallowed values, NaN/inf legacy tokens, invalid dates, duplicate IDs/numbers, and future schema fail with precise errors. - Golden totals cover taxable/non-taxable lines, line/document discounts, shipping, zero/maximum values, and half-way rounding. - Legacy pipe data is recognized as legacy, never as JSON. **Migration:** import line items into a draft invoice, require the user to supply/confirm all lost metadata, retain original bytes and migration warning, then save only after explicit review. **Rollback:** restore the prior invoice revision/original legacy bytes; no lossy down-conversion. ### BUILD-09 — Honest invoice UI, delivery, and audit **Priority:** P1 **Effort:** 5–8 person-days **Depends on:** BUILD-08 **Change** - Bind every header/party/date/term/total control to the aggregate, not static demo labels or table-only serialization. - Surface field validation inline; invalid text is not silently replaced by 8.5/25/100. - Route mutations through aggregate commands and bounded undo. - Implement Save/Save As/export state machine: pending picker, cancelled, writing, durable, failed. Sanitize suggested names; destination is picker-provided, not joined user text. - Record status transitions and immutable issued-invoice revisions; editing an issued invoice creates a revision/credit-note flow according to product policy. **Tests / exit** - UI-to-domain round trip covers all invoice fields and errors. - Injected write/disk-full/picker-cancel cannot show saved. - Keyboard/touch row editing respects validation and accessibility focus. - Printed/exported totals equal domain totals exactly; no UI recomputation. **Rollback:** invoices remain draft/read-only if issuance/export is unavailable. ### BUILD-10 — Validate or constrain the solar design engine **Priority:** P0 safety **Effort:** 12–20 person-days plus qualified electrical review **Depends on:** BUILD-02, BUILD-03 **Change** - First narrow product claim to “preliminary estimate” and list required assumptions/omissions. - Replace parse-to-zero with typed validated inputs and structured errors. Reject NaN/inf, negative, zero where invalid, unchecked dropdown index, and out-of-policy bounds. - Model energy demand profile, system losses, location/weather dataset and provenance, autonomy days, battery chemistry/capacity/voltage/series-parallel topology, DoD, efficiency, temperature, aging, and surge/continuous inverter demand. - Model panel temperature coefficient, minimum temperature, corrected Voc, Vmp/MPPT window, string/parallel current, controller/inverter input limits, DC/AC ratio, conductors, voltage drop, disconnects/overcurrent protection, and applicable local code assumptions. - Return design validity, assumptions, warnings, and unresolved decisions—not just six numbers. - Version component specifications with source/date rather than unexplained static spreadsheet values. **Tests / exit** - Independent hand calculations and a reviewed engineering tool agree within documented tolerance for the supported scope. - Cold-Voc, hot-Vmp, current, surge, autonomy, series/parallel battery, controller, conductor/protection, extreme climate, and unavailable-data cases. - `days_of_autonomy` materially affects output and is verified. - A licensed/qualified electrical or solar engineer approves formulas, assumptions, warnings, and product wording for target jurisdictions. - If any required design constraint is unresolved, output is blocked or explicitly incomplete. **Migration:** existing results are marked `LegacyUnvalidated`; never silently bless them after engine upgrade. **Rollback:** expose only energy/load worksheets and disable equipment recommendations. ### BUILD-11 — Implement project-scoped Materials workflow **Priority:** P1 product completion **Effort:** 10–16 person-days **Depends on:** BUILD-02, BUILD-03; integrate procurement only through typed references **Change** - Define material/catalog item, unit of measure, planned quantity, requisition/order/receipt/issue/return/waste/adjustment ledger, storage location, supplier reference, unit cost/currency, and audit fields. - Compute stock from immutable movements; do not allow direct total edits without an adjustment reason. - Validate dimensions/finite quantities/unit conversion and project ownership. - Provide list/search/filter, create/edit, receive/issue/adjust, low-stock/variance, and import/export with preview. **Tests / exit** - Ledger conservation, unit conversion, partial receipts, returns, waste, negative-stock policy, concurrent revision, and cost rounding. - Every action is project-scoped, audited, undoable where legally appropriate, and durable. - Mobile/desktop can operate beyond three rows and with keyboard/touch accessibility. **Rollback:** keep tab unavailable rather than replace ledger rules with mutable demo totals. ### BUILD-12 — Implement privacy-aware Workers workflow **Priority:** P1 product completion **Effort:** 10–16 person-days plus privacy review **Depends on:** BUILD-02, BUILD-03 **Change** - Define worker/contractor identity, trade/role, engagement status, contact fields only where necessary, qualifications/expiry, availability, project assignment, attendance/time record, and audit history. - Separate global person record from project assignment if multi-project reuse is required; enforce least-data views. - Add retention/deletion/export policy and redact sensitive fields from logs/diagnostics. - Validate unique references, date ranges, hours, overlaps, qualification expiry, and project ownership. **Tests / exit** - Role/capability tests control sensitive field display/export. - Assignment/attendance/date/overlap/expiry and A/B isolation tests. - Deletion/anonymization/retention and backup behavior are documented and exercised. - No production/demo worker PII seeds automatically. **Rollback:** tab remains unavailable or read-only; no insecure partial roster. ### BUILD-13 — Implement evidence-based Progress workflow **Priority:** P1 product completion **Effort:** 8–14 person-days **Depends on:** BUILD-05, BUILD-06, optionally BUILD-11/12 **Change** - Define progress update with task/quantity reference, reporting period, measured quantity/percent, evidence attachments, author, revision, approval status, and audit. - Derive project/task progress from explicit weights/quantities; prohibit arbitrary double-counting and percent >100 unless policy names the exception. - Compare baseline/current schedule and planned/actual quantities with transparent formulas. - Preserve historical snapshots when baseline or weights change. **Tests / exit** - Weighted rollups, zero weight, overrun, revised baseline, rejected update, duplicate evidence/update, time-zone/date boundary, and A/B isolation. - Displayed progress traces to source updates and formula version. - Mobile/desktop create/review workflows are equivalent and accessible. **Rollback:** show schedule-only status clearly; do not fabricate progress from elapsed time. ### BUILD-14 — Project-scoped CAD and document integration **Priority:** P1 **Effort:** 5–9 person-days after upstream contracts **Depends on:** BUILD-02/03, `cad-core` CORE-03/06, `cad-ui` UI-02/03 **Change** - Bind CAD/document sessions with typed project/document references from `ProjectContext`. - Define link ownership, delete/archive behavior, and revision displayed in Build. - Do not share thread-local active project or global generated files. - Validate all cross-workspace links before commit; stale/deleted targets show explicit broken-link state. **Tests / exit** - A/B project switch cannot retain CAD geometry, document content, selection, undo, or async results. - Archive/delete conflict behavior is deterministic. - Save/restart reopens the referenced exact revisions. - Build consumer tests run against canonical CAD contracts and real document repository APIs. **Rollback:** disable embedded launch and expose read-only external references; never fall back to global state. ### BUILD-15 — Responsive UX, lifecycle performance, and decomposition **Priority:** P2 after domain correctness **Effort:** 8–14 person-days **Depends on:** BUILD-02 through required workflow tranches **Change** - Share domain intents/controllers between desktop/mobile; keep layout-specific rendering only. - Remove repository calls from `draw_walk`; load on session events and update via observed snapshots. - Virtualize project/task/invoice/material/worker lists and use stable IDs/focus. - Move parser/scheduler/recalculation/file work off UI handlers with bounded, revision-correlated jobs. - Split thousand-line widgets into domain controller, view model, renderer, input adapter, and persistence adapter. - Add accessible labels, focus order, touch targets, keyboard navigation, contrast, loading/empty/error states. **Tests / exit** - Draw/event instrumentation detects I/O and fails the test. - 10k-project/task and 100k-cell fixtures remain within §6 UI/compute budgets. - Desktop/mobile conformance suite dispatches the same domain commands/results. - Idle/hidden workspaces stop redraw/timers/background recalculation. **Rollback:** revert presentation extraction independently; domain/project/repository boundaries remain. ### BUILD-16 — Migration, runtime, adversarial, and release evidence **Priority:** P0 release gate **Effort:** 7–12 person-days plus device time **Depends on:** all enabled-feature tranches **Change** - Add real runtime journeys: create/select/switch project, each enabled workspace, save, restart, conflict, recovery, export, mobile/desktop transition. - Add malformed/oversized/future persistence corpus; schedule/formula property tests; financial golden corpus; solar reviewed corpus. - Run forced I/O failures and long-session soak with memory, queue, write, recalculation, and frame metrics. - Publish a capability matrix and release evidence artifact by commit/toolchain/platform. **Tests / exit** - All runtime tests reach app startup and assertions; zero unexplained ignores. - Legacy migration is tested on copies, with rollback demonstrated. - No cross-project sentinel appears after switch/restart/export. - Performance and safety budgets pass on declared reference platforms. - Only workflows whose complete gates pass are labelled operational. **Rollback:** block release or disable the failing capability through BUILD-01's matrix. --- ## 8. Migration strategy ### Legacy sources to inventory - Project records/project types and active CAD marker. - Global spreadsheet workbook. - `generated/current.project.json` schedule plus save-as copies. - `generated/current.invoice.json` and `invoice_copy.json` pipe records. - Solar values/results if persisted elsewhere later. - CAD scripts/documents referenced by current project records. ### Procedure 1. Freeze legacy writers and compute checksums of original files. 2. Copy bounded inputs into a migration quarantine; never parse directly into live state. 3. Ask the user to assign ambiguous global workbook/schedule/invoice data to a project. Do not guess from “active” UI state. 4. Decode with a format-specific legacy reader. Record dropped/ambiguous fields explicitly. 5. Validate the new aggregate, write revision 1 atomically, reopen, and compare its canonical hash/domain totals. 6. Mark migration complete in the new manifest only after all required aggregates verify. 7. Keep original bytes and a mapping of legacy ID/path → new typed ID for the compatibility window. 8. A future schema is read-only; corruption is recoverable; valid empty remains empty. 9. Remove legacy write paths immediately, legacy readers after a documented support window. Invoice migration cannot be lossless because the current file never stored visible metadata. It must create an unissued draft requiring review rather than inventing issuer/client/date/currency/tax terms. --- ## 9. Required CI matrix ```bash cargo fmt -p nigig-build -- --check cargo metadata --locked --format-version 1 >/dev/null cargo check --locked -p nigig-build --all-targets cargo test --locked -p nigig-build --lib -- --test-threads=1 cargo test --locked -p nigig-build --tests -- --test-threads=1 cargo clippy --locked -p nigig-build --all-targets -- -D warnings git diff --check ``` As tranches land: ```bash cargo test --locked -p nigig-build --test project_isolation -- --test-threads=1 cargo test --locked -p nigig-build --test persistence_faults -- --test-threads=1 cargo test --locked -p nigig-build --test schedule_properties -- --test-threads=1 cargo test --locked -p nigig-build --test invoice_golden -- --test-threads=1 cargo test --locked -p nigig-build --test spreadsheet_boundaries -- --test-threads=1 cargo test --locked -p nigig-build --test runtime_ui -- --test-threads=1 ``` Also run direct dependencies/consumers for touched contracts (`spreadsheet-ui`, `doc`, `cad-core`, `cad-ui`, `nigig-core`, `nigig-uikit`). The workflow must use package names confirmed by `cargo metadata`, not guessed directory names. Rules: - No `|| true` around Cargo, clippy, runtime, migration, or source-ownership gates. - Exit 127 before startup is a failed harness job. - Tests that copy a production algorithm are deleted/replaced, not counted. - Source scans fail if no file is scanned. - Engineering review and independent calculation evidence are release artifacts, not unit-test comments. --- ## 10. Release gates - [ ] CI targets the current source tree and runtime tests execute assertions. - [ ] Every mutable workspace requires typed `ProjectContext`. - [ ] Desktop/mobile provide the same scalable select/open/close project lifecycle. - [ ] Versioned atomic repository, conflict detection, recovery, and fault-injection tests pass. - [ ] No runtime path uses `CARGO_MANIFEST_DIR`; no widget performs filesystem I/O. - [ ] A/B sentinel suite proves zero cross-project leakage in every enabled workspace. - [ ] Production scheduling has one implementation and passes graph/property/complexity gates. - [ ] Spreadsheet row/column boundaries, formula limits, and project isolation pass. - [ ] Invoice persistence is lossless and all financial math uses checked decimal/minor-unit types. - [ ] Save/picker/write failures can never produce success UI. - [ ] Solar remains estimate-only or satisfies the complete qualified-review gate. - [ ] Materials/Workers/Progress remain unavailable unless their full workflow criteria pass. - [ ] CAD/doc integration uses typed project/document/revision contracts. - [ ] No automatic demo seeding occurs on missing/corrupt state. - [ ] PII/commercial data lifecycle and export policy are approved and tested. - [ ] Runtime, migration, forced-failure, soak, accessibility, and performance evidence passes on supported platforms. - [ ] Zero unexplained/expired ignored tests and zero warnings suppressed from owned code. --- ## 11. Delivery, push safety, and rollback For every `BUILD-NN` tranche: 1. Start from a clean worktree; record HEAD and the tests that fail before the fix. 2. Implement only one atomic exit criterion when the listed tranche is too broad for review. 3. Run targeted tests, the required consumer matrix, and `git diff --check`. 4. Commit with the tranche ID. 5. Immediately before each push, `git fetch origin main` and compare merge base/remote changes. 6. Rebase or merge without dropping remote work; rerun tests after any reconciliation. 7. Push without force and verify the remote contains that exact commit before beginning the next tested chunk. 8. If authentication is unavailable, retain and report the tested local commit; never pretend it was pushed or later overwrite remote history. Rollback principles: - Optional incomplete workflows are disabled through the capability matrix. - Aggregate rollback selects the prior verified revision; original migration inputs are preserved. - Financial/engineering safety checks are fail-closed and are never removed to restore availability. - Project context and repository boundaries do not get feature-flagged off after migration begins. --- ## 12. Critical path and cross-plan dependencies ```text BUILD-00 → BUILD-01 → BUILD-02 → BUILD-03 │ ├→ BUILD-04 → BUILD-05 → BUILD-06 → BUILD-13 │ ├→ BUILD-07 │ ├→ BUILD-08 → BUILD-09 │ ├→ BUILD-10 │ ├→ BUILD-11 │ └→ BUILD-12 └─ CAD core/UI prerequisites ─→ BUILD-14 All enabled paths → BUILD-15 → BUILD-16 ``` - CAD integration waits for `cad-core`'s canonical document/transaction contracts and `cad-ui`'s session/project isolation. - Spreadsheet changes must be made in its real owner and tested through this app; do not fork its engine into `nigig-build`. - Site data is not silently reused for workers/procurement. Any future integration needs authenticated project/site mapping, field minimization, and conflict semantics. - Solar equipment recommendations remain off the critical path; a safe release can omit them.