design(name, options?). Every returned authoring handle
is immutable and owned by that builder.
Document definitions
Primitive and profile nodes
Feature nodes
Backend support is checked during evaluation, not authoring. A document may be
valid while a selected kernel lacks one of its features.
Product structure
Repository-only staged product authoring
The source tree contains:src/internal/document-v7-body-set-authoring.ts; it is not exported from the
package root or any package subpath. The public design(...) builder,
DesignDocument alias, evaluator, and migration target remain on frozen v6.
This is repository-only work staged for 0.2, not public 0.1.1 authoring.
The facade privately composes the v6 builder for admitted parameters and
native primitives, then adds staged configuration, material, resource,
imported-body, body-set, part, local assembly, external component, and datum
records. Its complete admitted surface is:
The relevant staged source signatures are:
application/vnd.invariantcad.document+json; they retain a valid requested
output ID and publish no local feature node. The facade constructs canonical
references from captured identity rather than dispatching through mutable
handle methods. Datum authoring returns owner-bound, frozen handles reserved for
later feature consumers; no method in this slice consumes one.
A body-set member keeps its stable ID, authored position, optional name, and
detached JSON metadata; multiple memberships may deliberately reference the
same owned solid DAG root. Every listed member is active, and the facade
neither selects nor infers a primary body. A staged part wraps either one owned
primitive, imported-body, Boolean, or transformed-solid DAG root, or one owned
body set. It cannot wrap another part or assembly, or use a body set, part, or
assembly as a Boolean or transform input.
material(...) authors a document-owned definition with an explicit
mass-density expression. part(...) accepts the existing PartOptions
contract: part number, description, detached metadata, optional explicit
density, and either a legacy descriptive material string or an owned
materialRef, never both. A configuration can substitute another owned
material for an owned part. The selected material determines effective
material identity and supplies density when needed; an explicit part density
still wins. A legacy label and a material name never perform catalogue lookup.
Length, angle, density, and scalar parameters may be specialized by a named
configuration and then by bounded caller overrides during evaluation.
Staged solid Boolean and transform DAGs
StagedSolidRefV7 is the owner-bound handle shared by direct primitive leaves,
imported-body leaves, Boolean results, and transform results. union(...),
subtract(...), and intersect(...) require one target plus a dense,
non-empty tool list. Every operand must be a solid handle issued by the same
builder. A Boolean result can feed a later Boolean, transform, body-set
membership, or part. The evaluator invokes exactly one kernel Boolean with the
target plus a frozen tool array in authored order. Backend implementation
strategy is kernel-owned, but it may not reorder operands or reinterpret the
authored operation.
transform(...) requires at least one operation and captures its dense ordered
operation list as plain own data.
translate(...), rotate(...), scale(...), and mirror(...) author one
typed operation each; their vectors use length, angle, scalar, and scalar
expressions respectively. A transform result can feed another transform, a
Boolean, body-set membership, or a part’s single-solid geometry.
The staged evaluator plans the selected closure iteratively, deduplicates
shared nodes, and executes every dependency before its consuming Boolean or
transform. maxDistinctSolids counts primitive and imported leaves.
maxSolidGraphNodes counts all distinct admitted solid nodes,
maxSolidDependencyLinks counts every transform input edge plus every Boolean
target and tool edge, including repeated tool references, and
maxTransformOperations counts the ordered operations stored on distinct
transform nodes. Each defaults to 100,000 in the staged body-set, part, and
product-assembly evaluators.
Transform expressions must resolve to finite values. Scale components must be
nonzero, and a mirror normal must be finite and nonzero. The selected kernel
must advertise and implement transform; each transform must return a fresh,
valid, positive-volume owned shape. Failure is transactional and releases all
shapes created for the graph.
The selected kernel must advertise the boolean feature and implement the
Boolean method before resource resolution or shape acquisition. Every created
node must return a fresh, valid owned shape. A subtraction or intersection that
returns a null shape or exactly zero volume fails with EMPTY_RESULT; an
impossible empty union, negative/non-finite volume, or any returned shape that
aliases an owned operand or earlier result fails as a kernel protocol
violation. Repeated authored operand references remain allowed and are charged
as separate dependency edges. Staged evaluation has no allowEmpty option.
Failure is transactional and releases every acquired intermediate exactly
once.
Stock OCCT evaluates this graph as exact B-Rep geometry and retains its normal
per-solid topology/native-export capabilities. Its Boolean history remains
partial unless an owned facade honestly advertises the existing
feature-scoped exact indexed-evolution protocol for boolean. A present
malformed exact-evolution envelope fails before resource or kernel work rather
than silently downgrading history. That promise covers the current Boolean
operation; it does not upgrade partial history already carried by an imported
or otherwise partial operand, and exact: true describes geometry rather than
complete persistent history. Manifold evaluates native
primitive/Boolean/transform graphs as approximate mesh geometry and exposes no
topology snapshots. The evaluator never retries an exact failure on Manifold
or silently converts an exact graph to a mesh graph. Any imported leaf,
transformed or Boolean-composed, additionally requires the strong exact B-Rep
single-solid document-import capability, so it cannot fall back to Manifold’s
weak or absent import path.
This is not general shape algebra. A transform input must be an owned
StagedSolidRefV7 created by a primitive, imported body, Boolean, or prior
transform, and the same restriction applies to every Boolean operand. A body
set, part, or assembly cannot be Boolean-composed or transformed. A generic
Boolean or transformed solid also cannot be published directly by
output(...): it must be retained by a body set or part. The one exception to
generic-solid output is the narrower direct StagedImportedBodyRefV7 output
already admitted by the import evaluator.
Fixed-placement products
The stagedassembly(id, build) method passes one
StagedLocalAssemblyBuilderV7 to its callback. Each instance(...) in this
slice references an owned local part, an already-completed owned local assembly,
or an owned external-part or external-assembly handle. A local assembly handle
is published only after its callback succeeds, so the facade can reference
earlier local definitions but cannot author a local cycle. Foreign or forged
handles are rejected.
externalPart(resource, output) and
externalAssembly(resource, output) require a committed InvariantCAD-document
resource owned by the same staged builder. They select a valid named part or
assembly output without publishing a local feature node. Product evaluation
admits the committed child document before child geometry work. A selected
external assembly may contain child-local parts and bounded nested local
assemblies; each active occurrence path may cross only one external-document
boundary.
An instance ID is stable within its containing assembly. Evaluation joins
those IDs into a full root-to-leaf path for each emitted part occurrence. Its
placement is an ordered list of translate, rotate, scale, or mirror operations,
and its configuration selector is exactly one of:
inherit, which evaluates a local component in the containing assembly’s context and maps root base to child base or a root named ID to the same ID in an external document;base, which evaluates a local component in the root base context or an external component in the child base context; ornamed, which selects the referenced configuration in the applicable root or child document.
suppressed: false, and
{ mode: "inherit" }.
The configuration active for every containing assembly controls its
definition-scoped instance suppression and placement expressions.
configuration.instanceSuppressed(...) can target any owned assembly
definition. Passing false explicitly unsuppresses an instance authored with
suppressed: true; omission retains the authored value. Suppression is
resolved before component support is checked, so suppressing an assembly edge
prunes its entire subtree, including external or otherwise unsupported
descendants. A suppressed nested external component therefore performs no
descendant resolution or kernel work. An active direct external part or fixed
subassembly is supported, but an active external descendant inside the admitted
child would cross a second document boundary and is rejected before nested
resolution or child geometry/kernel work.
Occurrence IDs are unique only within their containing assembly. Repeating one
part or subassembly in several instances is expected and does not copy its
document definition. Iterative evaluation expands active assemblies in authored
depth-first leaf order and composes edge placements parent first. Bounded caller
parameter overrides apply to root-document contexts only and never cross an
external boundary. Per-occurrence inherit, base, and named selection can
therefore produce different geometry, material, or density from a shared part
definition.
Evaluation reuses local parts for equal (part, effective configuration)
states and direct external parts for equal
(resource, output, child configuration) states. Fixed-subassembly leaves
share geometry by resource, child part node, and child configuration; distinct
assembly output aliases retain separate component, diagnostic, and BOM identity.
Direct part evaluation may additionally deduplicate solid-DAG acquisition
within a configuration batch. Authoring does not create a persistent or
cross-run cache commitment.
Product evaluation separately bounds nesting with maxAssemblyDepth and the
aggregate stored leaf-path length with maxOccurrencePathSegments, in addition
to its external-document, instance, occurrence, placement, contextual-part,
solid, material, document, and resource ceilings. Solid-graph nodes, all solid
dependency edges, and transform operations are counted globally across the
active product. Repeated occurrences in the same effective context reuse that
work, different contexts are charged independently, and suppressed subtrees are
pruned before these counters advance. Hand-authored cyclic local dependencies
fail strict document admission, and evaluation also rejects a recursive path
rather than looping.
The four datum methods author ordinary Document v7 nodes with stable node IDs.
A point carries a length-valued position. An axis adds one scalar direction. A
plane adds scalar positive-X and normal directions, while a coordinate system
adds scalar positive-X and positive-Y directions. Their owned handles establish
builder identity, but datums are not admitted by output(...): callers pass
datum node IDs to the separate source-only datum resolver. That resolver is
kernel-independent, normalizes admitted directions, and returns deterministic
orthonormal right-handed frames. It rejects non-finite or zero directions and
requires each normalized authored direction pair to have an absolute dot
product no greater than 1e-12 before deterministic
re-orthonormalization. Authoring a datum does not yet make it usable as a sketch
plane or shape-algebra input.
A resource commitment describes bytes that an application resolver may later
supply. Its ordered locations are hints only: authoring and evaluation never
dereference them. The facade does not read bytes or compute a digest or byte
length; the caller supplies those commitments. The imported-body method,
rather than mediaType, chooses the reader. STEP always uses
{ mode: "from-file" }. Text and binary BREP require
{ mode: "declared", length: "mm" | "cm" | "m" | "in" }. All staged imports
emit { healing: { mode: "none" } } and expected: "single-solid"; there is
no healing switch, weak-import fallback, or automatic exact-to-mesh conversion.
build({ limits }) accepts a partial DesignDocumentLimits override and
strictly parses the completed document. A failed strict result is raised as a
CadError; no invalid document escapes. During authoring, resources also use
the current default ceilings of 10,000 definitions, 100,000 aggregate
location hints, and 16 MiB of aggregate UTF-8 location text. One bodySet(...)
call is additionally rejected before copying if it exceeds the default
1,000,000 structural-value ceiling, and one instance placement cannot contain
more operations than that ceiling. The completed assembly instance list is
charged to maxStructuralValues during build. Final build limits can be
stricter; they do not raise these immediate safeguards.
Authoring methods fail immediately when a handle comes from another builder, a
namespace is duplicated, a required collection is sparse or empty, member IDs
repeat, a commitment is malformed, a configuration references foreign
definitions, an immediate authoring ceiling is exceeded, or a parameter,
configuration, material, part, assembly instance, placement, resource, import,
unit-policy, datum, or body-member option record contains an accessor or
unknown field. Those inputs must be plain own-data records; required arrays
must be dense own-data arrays. Accessors are not invoked and unsupported
semantics are rejected rather than silently discarded. Build then applies
caller-selected document limits and strict v7 validation before returning the
detached, recursively frozen document.
This facade does not author generic solid or direct primitive outputs,
recursive external-document graphs, cyclic local assembly graphs, datum-backed
sketches, Booleans over body sets/parts/assemblies, transforms over body
sets/parts/assemblies, other body-consuming features, per-body materials, or
general solid graphs beyond primitive/import/Boolean/transform DAGs. It also
does not add datum design outputs, CLI support, location I/O, reader inference,
healing, a primary-body rule, cross-body or assembly topology, aggregate
geometric measurement, mates, motion, interference/collision, or exact
aggregate STEP/BREP export.
Part- and product-level STL/OBJ export is an aggregate tessellation view and is
explicitly approximate/lossy; exact native export and topology remain per-solid
or per-body capabilities. These omissions are product boundaries, not implicit
fallbacks. The staged facade remains repository-only work for 0.2, and the
public 0.1.1 document alias remains v6.
ID rules
All IDs use the shared stable ID grammar and must be unique in their namespace. Avoid generated array positions or user-facing labels that may change. Prefer IDs such ashousing-side-a, left-bearing-seat, and manufacturing-assembly.
Programmer errors
Methods throwTypeError or RangeError for invalid direct calls, including:
- duplicate or malformed IDs
- references from another builder
- wrong-dimensional expressions
- wrong topology kind
- invalid option enum/literal values
- empty required lists
- non-positive tolerances
- references targeting the wrong direct solid