diff --git a/ROADMAP.md b/ROADMAP.md index 20834a7d..3a2f15ba 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -59,6 +59,16 @@ PCB / Package, Render, Animation, Simulation, Manufacture/CAM, Drawings. | M14 | Configurations: a table of rows (parameter expressions and feature suppressions per row) switched with config.activate (undoable, all or nothing), kept through parameter renames and feature deletes (config.configure, config.table, config.column/row/activate). Per-row body materials and appearances (library looks, custom colour/opacity and clearing overrides), undoable activation and save/reopen: done. Ordered typed configuration rules, atomic validation and structured rule editing: done. Component appearance and certified semantic face style columns, atomic preview/apply and independent-copy remapping: done. Exact constructed sketch-side and immutable imported-face lineage now preserve legacy names and reject retargeting. Left: ambiguous shifted/two-sided caps | in progress | 4 | | M13 | Never lose work: atomic saves (temporary file, flush, rename; a crash at any moment leaves the old file or the new one) with the replaced version kept as `.bak`; autosave of unsaved changes to the recovery folder every 5 minutes (preference) and after big operations, only when something changed; "Recover unsaved design?" on the next launch (`doc.recovery_list`, `doc.recover`, `doc.recovery_discard`); a kill-mid-save test (process killed while saving a 0.5 MB design 25 times). File format: `"format": "solidcraft/12"`, older formats upgraded step by step (`doc::format`), newer ones refused with a message, out-of-range numbers and broken placements refused; a corpus of designs saved by M0, components-era, joints-era and current builds (apps/solidcraft-cli/tests/corpus) that must open and evaluate as saved; damaged and hostile variants (truncation, bit flips, hostile values, removed keys, repeated features, deep nesting) never panic | done | 6 | +## Library foundations (#785, #786, #787) + +- Proposed phases cover offline bundled/project/user packs, physical materials and + appearances, editable wood mapping, and parameterized component/assembly families. + Stable identity/revision, copied design definitions, provenance and resource limits + apply from the first implementation. Existing material, appearance and standard-part + commands remain the application paths. See [the proposal](docs/book/src/dev/libraries.md) + for source/license review and acceptance gates. This is planning only: pack loading, + texture rendering and expanded component families are not implemented by this entry. + ## Render foundation - A bounded cooperative Radiance RGBE input utility is available in L1 render; diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md index cee25bdc..f77cd2f7 100644 --- a/docs/book/src/SUMMARY.md +++ b/docs/book/src/SUMMARY.md @@ -20,6 +20,7 @@ - [Contributing](dev/contributing.md) - [Architecture](dev/architecture.md) +- [Extensible library proposal](dev/libraries.md) - [The command engine](dev/commands.md) - [The kernel boundary and truck](dev/kernel.md) - [Persistent naming](dev/naming.md) diff --git a/docs/book/src/dev/libraries.md b/docs/book/src/dev/libraries.md new file mode 100644 index 00000000..5f61101f --- /dev/null +++ b/docs/book/src/dev/libraries.md @@ -0,0 +1,192 @@ +# Extensible libraries: materials, appearances and components + +Proposal for [#785](https://github.com/bherbruck/solidcraft/issues/785), +[#786](https://github.com/bherbruck/solidcraft/issues/786) and +[#787](https://github.com/bherbruck/solidcraft/issues/787). This page describes planned +contracts and acceptance gates, not an implemented pack format or new commands. It does +not bring the deferred Simulation or Render workspaces into scope. + +## Reuse the existing paths + +Physical materials already have built-in densities and design-local definitions +(`material.create`, `material.edit`, `material.delete`, `material.list`, `material.assign`). +They drive `component.properties`, survive reopening and participate in configurations. +Appearances have a built-in color/opacity library and body, face and component overrides. +`parts.library`, `parts.insert` and `parts.resize` already generate seven families of +fasteners, pins and bearing envelopes as editable components. + +Extend those routes. A shared catalog supplies identity, discovery and provenance; +each entry kind retains its own payload and application rules. A physical material is +not a texture, and a reusable component is not executable plugin code. + +## Portable, independently extensible packs + +Use one versioned, offline pack envelope for three kinds: physical material, appearance +and component family. Both project contributors and users can author packs without +rebuilding SolidCraft. Start with a directory and JSON manifest, not a new archive format +or an online marketplace. The exact schema belongs in the bounded-loader PR, accompanied +by machine-checked examples; the following are its design requirements: + +| Record | Required meaning | +|---|---| +| Pack | Schema version, stable namespaced ID, immutable revision, display name, author, source and license metadata | +| Entry | ID scoped to its pack, immutable revision, kind, label, category/tags, typed payload and per-entry provenance | +| Resource | Relative path, content digest, byte count, media role, author, source, license and included license text where required | +| Dependency | Explicit entry/revision reference; bounded acyclic resolution within explicitly selected packs | +| Selection | Pack ID + entry ID + exact revision; labels and filesystem paths are not identities | + +Pack revisions and schema versions are different: the former identifies content, the +latter describes how to read it. Changing content under an existing revision is an error. +Unknown schema versions, entry kinds and required capabilities produce a clear refusal; +they are never silently interpreted as an older format. Optional extensions need an +explicit namespace and preservation rules before being accepted. + +Provide three independent scopes: + +- **Bundled:** reviewed with SolidCraft and read-only in the library editor. +- **Project:** packs explicitly opened for the current project/team; never discovered + by silently executing or trusting files beside a design. +- **User:** local packs the user creates, imports, edits or exports. Native file access + belongs in the app; browser users import/export through the web storage/file workflow. + +Discovery order is deterministic. Duplicate labels can coexist, with their source shown. +Duplicate qualified identities/revisions with different contents are errors, not overrides +chosen by scan order. Editing a bundled entry uses **Save a copy** into a user namespace. +Updating a pack is explicit and leaves existing design instances unchanged. + +## Designs own their selected definitions + +On assignment/insertion, copy the definition, chosen revision, parameters, provenance and +required resource bytes into the design's existing container/resource mechanism. Keep the +source identity for inspection and an eventual explicit Update action. A saved design must +open, rebuild and render the supported appearance without the original pack, network or +another user's home directory. Installing a pack never changes a design or undo history. + +Assignment/insertion/update is a normal engine command, atomic and undoable. Preview is +non-mutating. A failed import, unresolved dependency, name collision or unsupported recipe +leaves the document and undo/redo stacks intact. Existing material names and appearance +precedence retain their legacy meaning; introduce stable IDs through a documented migration +rather than reinterpret old name-based assignments. Design-format changes need their own +version/migration and reopen tests, separate from the pack schema version. + +## Physical properties (#785) + +Keep physical material and appearance selection independent, with an optional default look. +Convert imported density units explicitly to the existing g/cm³ representation; geometry +continues to use millimetres and radians. Never infer units from magnitudes. Properties +need source, edition/date, grade, processing condition and applicable temperature/moisture +when relevant. Unknown properties stay unknown, not zero or guessed values. + +Start with density and mass integration through the existing commands. Reserve typed +extensions for elastic constants, yield/ultimate strength, thermal properties and +orthotropic axes, but do not expose these as FEA-ready until their model, units and +validation are implemented. A generic wood density is not an engineering material grade. +User-measured data can be stored with its own provenance and edited without changing the +bundled library. + +## Wood and sheet appearances (#786) + +Begin with body-local mapping, an explicit physical repeat size and a user-editable grain +frame. Suggest the longest **local** body-bound axis once, with X/Y/Z order for equal +extents; store the chosen frame rather than recompute it on every resize. Manual rotation +and scale survive parameter rebuilds, instance placement, undo and reopening. Shared +component instances transform the same definition-local mapping with their placement. +Non-finite or degenerate frames refuse; automatic choice remains a suggestion. + +Visual grain does not rotate the body, its geometric bounding box or a manufacturing +stock frame. Structural grain direction and grain-aware nesting/cut lists are distinct +features, coordinated with [#137](https://github.com/bherbruck/solidcraft/issues/137). +An anisotropic shading effect also does not imply mechanical anisotropy. + +After basic wood mapping, add sheet-specific top/bottom/edge looks: MDF, chipboard, +plywood and compact laminate, then melamine, laminate, linoleum and veneer finishes. +Appearance layers initially describe presentation only. Physical finish thickness or +mass must be explicit modelling/material inputs, never an invisible side effect of paint. +Face/edge assignments require durable identities and must refuse a lost association +rather than paint a nearby replacement face. + +Keep texture role, color space, normal-map convention and physical scale explicit. +Coordinate with the [render capability contract](https://github.com/bherbruck/solidcraft/blob/main/docs/render-backends.md): +the existing color/opacity viewport is not proof of PBR or texture support. A renderer +must report what it supports; unavailable maps use a documented preview fallback with +a visible notice. Export either preserves supported mapping/resources or reports loss. + +## Standard and user component families (#787) + +Keep the existing fastener insertion/resize path. Add original parameterized BAR, SHS, +RHS and CHS recipes first, with explicit length units, parameter bounds, section frames +and insertion/connection frames. Validate wall thickness against the outer size and +state whether corners are sharp or rounded. Do not label approximate geometry as a +certified standard section. UB/UC need actual flange/web radii and tapers; identifying a +standard does not grant redistribution rights to its published size tables. + +A family revision defines a bounded parameter schema, permitted recipe and optional +reviewed size table. A size designation identifies a row, not an arbitrary filename. +Changing size rebuilds the same component identity and preserves supported connections. +Initial recipes must use a small allowlist of ordinary modelling operations. No embedded +native code, shell commands, scripts, arbitrary command IDs or network hooks. Reject +cycles, excessive expansion and unsupported operations before mutating the design. + +Custom assemblies follow single components: bounded dependencies, named connection +frames, explicit shared/independent instance semantics and one-step insertion undo. +Store selected parameters and definition snapshots so missing or changed catalogs cannot +silently substitute another part. Geometric envelope models, including existing bearing +envelopes, must remain distinguishable from detailed/manufacturing-ready models. + +## Sources and licensing + +SolidCraft is MIT OR Apache-2.0. Code and generated recipes must follow the clean-room +rules; never copy commercial CAD materials, templates, geometry, icons or catalogs. +Third-party assets retain their own licenses. Every bundled resource needs its author, +source, license and `ATTRIBUTION.md` row, even if attribution is optional under CC0. +Record hashes and retrieval dates when admitting actual files. A manifest's claimed +license is provenance to review, not automatic evidence of permission. + +Sources checked on 2026-10-13; no external assets or datasets are bundled by this proposal: + +| Source | Suitable use / admission condition | +|---|---| +| [ambientCG license](https://docs.ambientcg.com/license/) | Downloadable assets and material preview renders are CC0. Candidate wood/sheet texture source; choose and attribute individual files. | +| [Poly Haven license](https://polyhaven.com/license) | Assets are CC0. Site text, logos and other site content have separate rights; API access has separate terms. Do not copy provider implementation code. | +| [Wikidata structured-data license](https://www.wikidata.org/wiki/Wikidata:Copyright) | Structured entity/property data are CC0; other page text has different terms. Candidate for individual referenced quantities and identifiers, not unverified engineering-grade defaults. Preserve the underlying measurement references, qualifiers and units. | +| [USDA Wood Handbook, revised 2021](https://research.fs.usda.gov/fpl/wood-handbook) | Reference for moisture, physical and mechanical wood properties. Verify the specific table's rights, species, units and conditions before importing data; no wholesale dataset approval is implied. | +| [NIST data/publication rights](https://www.nist.gov/open/copyright-fair-use-and-licensing-statements-srd-data-software-and-technical-series-publications) and [repository terms](https://materialsdata.nist.gov/terms/) | Candidate property references only. Uploaded data use provider-selected terms; public availability is not a blanket redistribution license. Review each dataset. | +| [Khronos PBR overview](https://www.khronos.org/gltf/pbr) | Public rendering conventions for texture roles and shading properties; a design reference, not a source of CAD material data. | +| Original SolidCraft recipes / user measurements | Preferred initial component recipes and illustrative procedural previews; preserve authorship and label illustrative versus measured values. | + +Prefer CC0 resources for the starter texture pack and original recipes for the starter +component pack. Defer uncertain or restrictive data rather than scrape supplier sites, +copy standards publications or assume a downloadable CAD file can be redistributed. + +## Phases and acceptance gates + +Each implementation PR references these issues without closing them prematurely. + +| Phase | Deliverable | Required evidence before calling it complete | +|---|---|---| +| 0 | This proposal, source review and roadmap | Maintainer-reviewable contract; distinguish existing functions from planned ones; no runtime or format changes. | +| 1 | Shared bounded manifest parser, resolver and pack validation/import/export | Project and user manifests use the same schema; deterministic conflicts, invalid versions/IDs, missing resources/dependencies, cycles, path traversal and budget exhaustion fail atomically; native + wasm pass. | +| 2 | Material and appearance catalog integration and browser UI | Create/copy/edit/import/export from the UI; existing commands used; analytic box mass before/after assignment; configurations, undo and offline cold reopening; actual screenshots. | +| 3 | Wood mapping and a small reviewed starter pack | Rotate/scale grain on a public-safe block and placed instance; no flip on resize; reopen without pack; rendering capability/fallback tests and screenshots; attribution for each shipped asset. | +| 4 | Parameterized section families and reviewed standard size data | BAR: area = width × height; sharp RHS/SHS: outer area minus inner area; CHS: π(outer_diameter² − inner_diameter²)/4. Check volume = area × length, hollow membership, insertion frame, resize, connections, undo and offline reopening; screenshots. | +| 5 | Custom assemblies, sheet face/edge layers and expanded catalogs | Bounded nested insertion, shared/independent semantics, durable face associations, explicit updates and loss reporting; measured tests and screenshots for each workflow. | + +After phase 1, material/appearance integration and section-family work can advance +independently. Wood mapping depends on actual renderer support, not on section families. +Phase 5 is several separate PRs, each following its relevant earlier workflow, rather +than one change coupling assembly insertion to face painting. + +Keep parsing/resource I/O in `io`, durable selected definitions in `doc`, application +and validation commands in `engine`, renderer-specific interpretation in `render`/its +adapters, and discovery/editing UI in `ui-egui`. Lower layers do not depend on the UI +or platform file dialogs. Reuse container resource deduplication; avoid a second blob store. + +Before allocating/decoding, enforce manifest byte/entry/string/dependency limits, total +resource bytes, image dimensions/decoded bytes and recipe expansion bounds. Paths must be +relative, normalized and confined to the selected pack, including symlink handling. Phase 1 +must publish exact limits and test their boundaries. Do not auto-fetch missing files or +install executable extensions. Explicit import/export is enough for the first delivery. + +Run `cargo xtask ci` for each implementation arc and check remote PR results. Geometry +tests use analytic values; UI and observable CAD changes include actual app evidence. +The three issues remain open until their individual workflows pass these gates.