Skip to main content

InvariantCAD architecture

InvariantCAD separates design intent from computation. A document must remain useful after any particular kernel, solver, renderer, or application has disappeared.

Non-negotiable invariants

  1. The document is plain data. DesignDocument contains JSON values, stable IDs, expression trees, feature nodes, and references. It never contains callbacks, class instances, maps, BigInts, WASM handles, or native pointers.
  2. Units are explicit. Internal lengths are millimetres, angles are radians, and scalar expressions are dimensionless. TypeScript rejects incompatible expression composition and semantic validation repeats the check for untrusted JSON.
  3. Modeling is a DAG. Nodes reference earlier or later nodes by stable ID, not array position. Validation detects missing references, kind mismatches, and cycles before a kernel is invoked.
  4. Kernel conversions are explicit. The Manifold backend is a robust triangle-mesh kernel. It is not advertised as exact B-Rep. Every exact backend must declare its representation and conversion losses.
  5. Topology is not an array index. Public APIs never make faces[3] or edges[7] a durable design reference. Serialized selectors combine feature provenance, geometry, adjacency, set algebra, and explicit cardinality. Evaluation-scoped kernel keys are opaque and disposable.
  6. Failures are structured. Normal modeling failures produce stable diagnostics with node IDs and JSON Pointer paths. Programmer misuse of the builder can throw immediately.
  7. WASM lifetime is explicit. Evaluated results own kernel shapes and expose dispose(). Kernel objects never escape through the public mesh or measurement APIs.

Layers

Authoring layer

DesignBuilder, SketchBuilder, dimensioned expressions, and typed references make documents pleasant to create. Builders may mutate internally, but build() returns a recursively frozen document. Explicit names are required for public features and sketch entities. This makes source diffs and diagnostics stable under insertion and reordering.

Document layer

DesignDocument is the source of truth:
  • schema and independent schema version;
  • base-unit policy;
  • parameter definitions and expression ASTs;
  • document-owned material definitions with stable IDs and required explicit density;
  • an optional canonical registry of named configurations containing definition-targeted parameter, assembly-instance suppression, and part-material overrides;
  • an optional Document-v2–v6 registry of normalized persistent topology evidence bound to stable IDs and exact solid-node targets;
  • sketch geometry, constraints, and explicit profiles;
  • feature DAG;
  • parts, assembly occurrences, and outputs;
  • optional JSON metadata.
Canonical serialization sorts object keys and rejects values JSON cannot preserve. Semantic hashes exclude top-level document metadata by default; metadata nested on authored definitions remains semantic. Authored change-impact report v1 is a separate, kernel-free reverse-dependency analysis. analyzeDesignImpact first detaches and validates the supplied document under DesignDocumentLimits, then admits a nonempty, deduplicated, sorted string-ID seed inventory drawn from existing nodes, parameters, materials, configurations, and persistent topology references. Malformed and unknown IDs fail before graph traversal. Propagation keeps evaluation context attached. The base context and each named configuration with evaluation overrides close independently, and only then are their results existentially unioned. Parameter defaults are replaced only by the selected configuration’s override while bounds remain live; material-to-part edges use the effective material; assembly component and placement edges exist only for active instances. Mutually exclusive configurations therefore cannot form one synthetic path. The analysis uses pre-indexed dependency edges and maxStructuralValues as a context-work ceiling as well as a detached-document/seed ceiling. The deeply frozen report contains sorted impacted parameter, material, configuration, node, and output inventories. Node entries retain deterministic direct and immediate node-dependency reasons; direct is true when at least one non-node dependency or node seed reaches that node before feature-DAG propagation in at least one context. The report describes possible impact over the current authored dependencies only. Seeds are ID-level rather than field-level, and v1 cannot predict added or deleted definitions or newly introduced edges. It does not automatically diff document values, evaluate geometry, compare B-Reps, validate reusable artifacts, infer topology identity, or prove that geometry changed. Its version is independent of document, topology-signature, descriptor, exact-evolution, and facade-ABI versions. Document schema v1 is retained as the original grammar. Schema v2 adds only the persistent topology registry and selector atom. Schema v3 adds only the five bounded ruled-loft roles to origin queries and stored lineage/adjacency evidence. Schema v4 adds only the six bounded-sweep roles in those same closed role locations. Schema v5 adds only fillet.face.blend and chamfer.face.bevel. Schema v6 is current and adds the vertex topology kind, vertex position query, edge↔vertex adjacency, and protocol-v2 stored references without adding semantic vertex roles. Parse, clone, stringify, hash, validation, and direct evaluation preserve supplied v1–v5 documents under their frozen grammars. migrateDocument upgrades a validated v1–v5 document to v6 and is idempotent for v6. It changes the version envelope without capturing, relabeling, protocol-upgrading, or rewriting any stored descriptor fingerprint, lineage, geometry, or adjacency evidence. Compatibility tests pin legacy v1/v2/v3/v4/v5 bytes and hashes separately from current builder hashes. Future strict grammar expansions require another document version and an explicit migration path. Node-kind membership and top-level document-body fields are independently enumerated for every document version in both TypeScript and Zod. Shared schema helpers cannot grant a new kind or field to an older version: changing either closed set requires a new document version, a version-specific type/schema boundary, and an explicit migration. Existing per-node interfaces remain structurally shared only while their serialized fields are identical; changing an existing node’s fields likewise requires a version-specific node interface. Topology selectors are also plain document data. Commutative and and or operands are flattened, deduplicated, and canonically sorted for serialization and hashing. A selector resolves to an unordered set and must state its accepted cardinality; evaluation never breaks ambiguity by taking the first kernel result. Selected edges for fillets and chamfers are tangent-contour seeds, not hard modification boundaries. Every seed expands to the maximal connected contour whose consecutive edges are tangent and whose incident face chains continue tangentially on both sides. Duplicate or overlapping seeds are idempotent, and selector cardinality applies before this expansion. Backends use their effective B-Rep tolerances to classify continuity, so geometry near a tolerance boundary can still differ between kernels; a future explicit stopping-boundary mode must be a distinct serialized contract. Shell openings are exact selected input faces, not propagation seeds. No tangent or coplanar neighbor is removed unless the selector also matches it, so shell selector cardinality describes the actual opening set. Shell thickness is a positive magnitude; serialized inward and outward directions determine which side of the unselected input boundary receives the offset wall. The current document grammar fixes offset-face transitions to round/arc joins, and kernel conformance checks geometry that distinguishes those joins from intersection/miter behavior. The authoring API materializes its default inward direction and absolute reconstruction tolerance in every shell node, making both part of canonical serialization and semantic hashing. Tolerance must be positive and less than thickness. Whole-solid offset is a separate 3D feature contract. It takes one positive distance magnitude, a materialized outward or inward direction, and a materialized absolute tolerance. The current document grammar fixes skin offset semantics and round/arc transitions; it does not expose intersection, self-intersection, internal-edge, or healing switches. The operation accepts and returns exactly one valid positive-volume solid with no loose lower-dimensional topology. A result that collapses, becomes inside-out, splits into multiple bodies, or changes volume contrary to its direction is a failure. Two-dimensional profile/wire offset is intentionally reserved for a future distinct node. Draft is an atomic selected-face feature. The document stores the exact semantic face query, signed angle, nonzero pull direction, and an arbitrary neutral plane with independent origin and nonzero normal. The angle must satisfy 1e-4 < abs(angleRadians) < pi/2; values at or below the lower bound can become silent no-ops in the pinned kernel. Pull direction and neutral-plane normal are passed independently rather than deriving or normalizing one from the other. A Boolean node has one authored target followed by one or more authored tools. That order is semantic: union and intersection reduce sequentially from the target through the tools, while subtraction removes the complete tool set from the target in one multi-tool cut. Backends may optimize inside those boundaries but may not reorder operands or reinterpret subtraction as an unordered reduction.

Solver layer

SketchSolverBackend consumes canonical sketch entities and constraints and returns solved coordinates, radii, residuals, degrees of freedom, status, and diagnostics. Solved profiles preserve analytic lines, arcs, and circles in sketch-local coordinates. Each boundary curve may carry the stable sketch and entity IDs that generated it. Mesh kernels tessellate this representation explicitly; exact kernels consume the analytic curves directly. A solver must never force every downstream kernel to treat a sampled polygon as the authoritative design boundary. The built-in reference solver uses damped nonlinear least squares with numerical Jacobians. It gives the core a dependency-free, permissively licensed vertical slice. Its capability declaration is deliberately separate so PlaneGCS, EZPZ, or another industrial solver can be integrated without changing documents.

Incremental identity and artifact layer

Feature-hash protocol v1 gives each node a kernel-independent identity under one effective evaluation context. hashDesignFeatures detaches and validates the document, resolves parameters with evaluator precedence, applies the selected configuration’s suppression and material substitutions, canonicalizes commutative topology-query structure, and normalizes consumed persistent-reference evidence. Each SHA-256 envelope contains the node ID and kind, units, effective local node intent, resolved direct parameter values, ordered direct dependency IDs/kinds/hashes, consumed reference hashes, and effective material data where applicable. The result is a Merkle DAG: a changed child invalidates its consumers, while an isolated branch retains its identity. Effectively suppressed assembly instances contribute neither a component hash nor placement parameters to their containing assembly. This identity is intentionally narrower than geometry. Equal feature hashes mean equal bytes under effective-intent protocol v1; they do not prove equal B-Reps, meshes, topology identity, solver output, or kernel behavior. Conversely, IDs and other admitted authored intent can differ even when a kernel would produce equal geometry. FeatureHashLimits bound feature count, dependency links, and canonical bytes, while HashDesignFeaturesOptions.signal gives cancellation a structured EVALUATION_ABORTED boundary. The hash report identifies one selected configuration and all resolved parameters, but a configuration name is not salted into each node when its effective intent is otherwise equal. Artifact-cache protocol v1 is the separate compatibility and storage foundation. createKernelShapeArtifactCacheKey consumes an ArtifactCacheFeature, the node/output-kind/hash projection of one feature-report entry, and rejects non-solid entries or untagged hashes. The resulting key includes the feature protocol/digest and node ID, artifact-cache protocol, evaluator-semantics version, kernel ID, backend artifact protocol/format/format-version/compatibility fingerprint, and sketch-solver ID/compatibility fingerprint. The topology-signature fingerprint is not a substitute: it describes persistent matching evidence, not complete shape serialization or runtime semantics. KernelCapabilities.shapeArtifacts is an optional all-or-nothing declaration paired with encodeShapeArtifact and decodeShapeArtifact. Encoding retains the source handle; decoding creates one new live current-kernel shape owned by the caller. The codec promise covers every evaluator-observable shape semantic under the advertised exact compatibility fingerprint. Native exchange is weaker. In particular, the OCCT adapter’s ordinary STEP/BREP path reconstructs geometry with partial history and does not retain its wrapper-level semantic lineage, history completeness, topology annotations, analytic volume overrides, or cached evaluator state, so those bytes cannot be relabelled as a shape artifact. The unreleased 0.2 KernelCapabilities.stepExport contract is a separate optional strong envelope for the much narrower question of deterministic single-product STEP serialization; it is not in the current 0.1.1 package. Protocol v1 binds AP214IS bytes to one backend shape representation, resolved metadata/options, implementation, and exact runtime artifact. Only the bundled zero-override createOcctKernel() stock writer is currently qualified; its otherwise volatile timestamp and product counter are replaced through a bounded structural Part 21 pass. Explicit wasm, moduleFactory, and attested-runtime paths keep weak raw STEP export and omit the envelope. This does not preserve evaluator semantics like an artifact codec, canonicalize equivalent B-Reps, or make STEP a cross-runtime cache format. The qualified writer still materializes its original string synchronously before JavaScript can enforce post-write cancellation and size limits. The repository-private OCCT artifact candidate is a development hook below that public capability boundary. Format v3 retains binary BREP geometry and bounded canonical sidecar v2, then adds native identity format v1 as a separate section. The 44-byte v3 envelope header declares fingerprint, sidecar, identity, BREP, and total lengths. Sidecar v2 retains its fixed 48-byte big-endian header and key-neutral face/edge/vertex structure and incidence, wrapper lineage, complete/partial history, analytic volume semantics, and root/subshape orientation evidence. It declares exact topology-item, adjacency-link, lineage-record, UTF-16BE string-byte, and native-orientation totals. The enclosing private candidate limits its compatibility fingerprint to 2,048 UTF-8 bytes before envelope allocation. Arbitrary JavaScript strings are length-prefixed UTF-16BE code units, finite binary64 values use one big-endian encoding with signed zero normalized, and enum tags and optional-field masks are closed. Encoding detaches and canonicalizes once, performs a counting pass before allocation, and then writes exact-size sections. Decode validates headers, declared totals, and conservative minimum representation before topology-table allocation; nested readers charge those totals, require sorted unique in-range collections, and accept only exact end-of-input. Those exact-end rules cover the envelope, sidecar v2, and identity v1. The stock occt-wasm BREP reader tolerates suffix bytes after a valid native archive, so strict consumption inside the BREP section is guaranteed only by the owned ABI 0.7+ transport; stock acceptance followed by canonical re-encoding can discard that suffix. Native identity v1 assigns each unique located solid, shell, wire, face, edge, and vertex the zero-based direct-child path from the serialized root to its first IsSame occurrence. It also carries a complete rooted pre-order stream of every serialized child occurrence. Each fixed 12-byte occurrence record contains shape type, composed orientation, direct-child count, and the canonical IsSame class index for those six indexed kinds; compound, compsolid, and generic-shape occurrences are unindexed but retain exact structure, order, orientation, and multiplicity. The 64-byte identity header records exact identity length, aggregate first-path components, all six unique-class counts, occurrence count, and record width. It admits at most 100,000 unique paths and 1,000,000 path components, with maximum depth 64, maximum child index 999,999, 100,000 occurrence records/traversal visits, and 1,000,000 candidate IsSame comparisons. Producers lexicographically sort first paths within each kind and apply the same permutation jointly to face/edge/vertex topology records, all six native-orientation arrays, and every occurrence class index, so producer TopExp enumeration does not enter the bytes. The consumer captures its restored raw order, maps each stored first path to that fresh index, exact-compares the complete occurrence stream by class path, and verifies face/edge/vertex geometry and incidence before restoring semantic records onto fresh evaluation-scoped keys. Multiplicity, order, composed orientation, IsSame-class membership, shape type, child count, geometry, incidence, or root-structure substitution fails closed and disposes the partial owner. The duplicate-occurrence regression specifically replaces a one-component BREP with two occurrences of the same located TShape and requires transactional rejection. Within one serialized artifact this identifies the unique located IsSame classes for all six indexed kinds and preserves every occurrence’s rooted structure, order, type, composed orientation, multiplicity, and class membership. Compound, compsolid, and generic-shape nodes are structural occurrences rather than indexed public identities. Stock occt-wasm exposes IsSame but not IsPartner, so v3 cannot attest that distinct-location IsSame classes share one underlying TShape rather than independent TShapes. Its paths are coordinates in the exact serialized child hierarchy, not cross-edit topology IDs or persistent assembly identities. Owned facade ABI 0.8 retains ABI 0.7’s candidate-only capped chunked BinTools-v4 writer and bounded-input report-owned reader, whose decoded root transfers into the originating kernel at most once, and adds a fixed 128 MiB cumulative native allocation-request limit plus report telemetry around both calls. ABI 0.9 retains that transport and quota, then parses the exact owned BinTools-v4 profile before OCCT deserialization under 1,000,000 structural work units, 64 nesting levels, and location-power magnitude 1,000,000. The preflight checks canonical geometry/tables/locations and backward-only TShape hierarchy plus reachability, charges bounded TShape metadata to the native quota, and includes conservative squared aggregate geometry, representation, expanded-topology, wire, and face validation envelopes. Global geometry-work squaring deliberately limits admitted aggregate geometry work to roughly fewer than 1,000 units under the shared cap, with other charges reducing it; this is a private artifact-compatibility ceiling, not a CAD modeling limit. Read telemetry records echoed limits, work, maximum depth/location power, consumed bytes, code/completion, and whether deserialization started. Every TypeScript post-transfer failure releases the root. ABI 0.8 remains loadable without the new preflight arguments; ABI 0.7 retains bounded transport without the private request quota; stock and ABI 0.2–0.6 candidate paths retain unbounded native materialization, but use the same v3 envelope, bounded v2 sidecar, and identity v1. The private fingerprint binds nativeIdentity=serialized-first-issame-child-path-v1, nativeOccurrenceManifest=complete-rooted-preorder-type-orientation-child-count-issame-class-v1, nativeOccurrenceRecordBytes=12, nativeIdentityMaxOccurrences=100000, nativeIdentityTraversalOccurrences=100000, every other identity/version/ceiling declaration, and the native-structure contract. A package-private symbol on the OCCT implementation supplies the host operations to repository tests, but neither that symbol nor the candidate codec is exported from a package entry point or exposed on the ordinary GeometryKernel surface, and the OCCT adapter does not advertise shapeArtifacts. The reviewed stock-runtime v3 asymmetric-box fixture is 13,735 bytes. Its fixture witness is invariantcad:kernel-shape-artifact-fixture:v1:sha256:4279e9f76ab1e41dae47b28aea9c426ffa8b5f329ab624f137c65f6881e23918. The independent current semantic witness is invariantcad:kernel-shape-semantic:v2:sha256:b99dd9c39b950700dd22c8be6255db6e816e1a51668f415bf84b80c4c200d588; v2 records OCCT’s unsupported genus as null rather than carrying the former heuristic zero. The artifact bytes and fixture witness did not change for that semantic-protocol migration. The v1 and v2 artifact fixtures remain only as negative compatibility inputs that v3 must reject before native restore. pnpm artifact:fixture:occt -- --check --version v3 reconstructs the cold fixture twice, checks byte identity and source/decoded semantic identity, and compares the reviewed canonical base64 without writing. An unexported host-neutral coordinator owns one disposable asynchronous realm operation. It rejects a pre-aborted signal before calling the realm factory, starts the deadline before factory invocation, settles result, factory failure, abort, and timeout races once, requests termination exactly once, and waits for the adapter’s termination operation before returning. A result does not make termination optional, and a primary failure plus termination failure is retained as an aggregate. The Node adapter observes child close; browser Worker.terminate() returns void, so that adapter can confirm only the termination request, not worker exit. This is internal orchestration for repository gates, not a public worker API. The Chromium production-bundle gate uses that coordinator with a fresh stock-OCCT module worker per operation. The main realm retains the committed v3 fixture and transfers a distinct copied ArrayBuffer; the gate proves that the retained bytes remain immutable and the transferred copy becomes detached. A closed exact-key started then success/failure response protocol rejects inconsistent phases. The worker confirms that the public capability and codec methods remain absent, decodes through the repository-private candidate, observes only scalar volume/topology/candidate metadata, disposes the live shape and kernel, and only then responds. The same browser gate runs real Evaluator.evaluate(...) operations against stock OCCT. Its successful path binds the repository-private cache experiment to an explicit test-only solver fingerprint and trusted in-memory store, evaluates a fixed box cold, disposes that result, and evaluates it warm. The cold path records miss,write and exactly one native box construction; the warm path records hit, decodes the artifact, and performs zero additional box constructions. Detached measurements, topology counts, output count, and diagnostics must match exactly, public artifact capability and codec methods must remain absent, and the worker responds only after evaluated-design and evaluator cleanup. Its deadline and post-start abort paths remain unbound: they report entry into the wrapped box call, complete the real native box, and then stall without yielding before the wrapper returns. The host requests worker termination and a fresh worker reproduces the successful scalar evidence exactly. Because the browser cannot await Worker.terminate(), this establishes the request plus fresh-realm recovery rather than observed exit. No live native handle or object crosses the boundary. The public environment-specific OCCT loaders verify a matched owned runtime before kernel initialization. Both copy caller-owned inputs before their first await, exact-check canonical metadata/release.json against an independently trusted SHA-256 pin, and verify the declared JavaScript/WASM sizes and digests before importing JavaScript. The opaque result is accepted only by createOcctKernel through the evaluated InvariantCAD internal module instance that created it; cloning the visible report does not reproduce executable authority. It is mutually exclusive with raw wasm and moduleFactory overrides. Kernel creation gives every instance a fresh verified WASM copy and requires the initialized facade marker to match the trusted manifest. The Node entry transfers verified JavaScript without a temporary executable file. Node 22.15 and newer use an isolated node:module.registerHooks() hook per load and deregister it after import; Node 22.13 and 22.14 retain the compatible process-wide node:module.register() worker-hook fallback, for which the Permission Model must allow workers. The evaluated module cache remains for the process lifetime on either path. The browser entry uses a unique Blob module URL, revokes it after import, and requires the applicable CSP to permit blob: module scripts. The attestation report separates two identities. runtimePairIdentity hashes the facade declaration plus exact JS/WASM sizes and digests and is added only to the repository-private artifact compatibility fingerprint. declaredBuildIdentity hashes the exact canonical release manifest and records its source/toolchain declarations without claiming that build execution was observed or authenticated. Persistent-topology fingerprints remain semantic contracts and do not gain the pair digest. The evidence also leaves publisher authentication and compatibility certification false. This boundary does not attest the wider application, InvariantCAD library/wrapper, host, JavaScript engine, Node hook chain, or actual machine instructions. The Node owned-runtime gate gives producer A and consumer B separate one-shot child processes. Each child bounds and reads packaged metadata/release.json, JavaScript, and WASM once, uses the public Node loader with the independently maintained reviewed manifest pin, and supplies the resulting opaque pair to createOcctKernel. Producer artifacts and detached evidence are deterministic across fresh producer processes; consumer B preserves its parent-owned input and reproduces the producer’s artifact, capability, runtime-input, and semantic evidence. The parent bounds requests, stdout/stderr, result files, and artifact files, requires exact request IDs and closed result envelopes, uses SIGKILL for post-start timeout or abort, waits for child close, discards an injected-trap process, and proves recovery in another fresh child. A one-byte mutation to the manifest or either runtime file is rejected before supplied JavaScript executes. Additional fresh owned-ABI-0.9 children execute a deterministic two-box Boolean union through the real Evaluator.evaluate(...) path. A successful evaluator result requires exact operation-started then kernel-operation-started events. The Boolean wrapper emits the second marker immediately before the real native call, proving entry rather than completion, and emits non-yielding-stall-started only after that call returns and immediately before the test-only stall. Timeout requires that third marker and abort waits for it before sending SIGKILL; both await close and recover in a fresh evaluator process with identical detached document, measurement, topology, and runtime evidence. The parent rejects every incomplete nonempty event prefix; a runtime-attestation failure before operation start legitimately emits no event. A normal result is emitted only after evaluated-design and evaluator cleanup; an injected cleanup failure cannot produce success. A killed child cannot run that language-level cleanup, so destroying the entire process is its containment and reclamation boundary. Run this evidence directly with pnpm test:occt-artifact-process; the owned facade-bundle gate runs it against the verified packaged runtime automatically. Process protocol v3 adds a separate private evaluator-cache handoff over a fixed 2 × 3 × 5 direct-output box. Two fresh verified producer children must independently model one native box, record miss,write, observe encode but not decode, and emit byte-identical cache records plus identical detached evidence. The parent alone transports the record through an exact binary frame: an 8-byte versioned magic, a little-endian 32-bit canonical-JSON header length capped at 32 KiB, and the exact remaining payload. Fatal UTF-8, closed header fields, protocol/key/metadata/integrity validation, request-specific byte ceilings, SHA-256, exact payload length, and exact EOF are checked before a child can consume it. A fresh compatible read-only consumer records hit, observes decode but not encode, performs zero native box calls, and exactly matches the producer’s measurements and complete topology. A fresh consumer under a different solver fingerprint derives another key, records miss, performs one native box, and invokes neither codec direction. Caller-owned bytes remain detached from process inputs; payload tamper, forged key/metadata, shared or hostile typed-array input, post-start abort, and injected failure are rejected before a subsequent fresh consumer proves recovery. This process result deliberately says certifiesCompatibility: false, buildExecutionObserved: false, buildExecutionAuthenticated: false, and publisherAuthenticated: false; its evaluator evidence also says certifiesOperationalCancellation: false. Exact runtime-pair and declared-manifest identity do not defend a trusted host, same-process module-hook chain, or another process under the same UID, and do not prove live or peak memory. The injected trap tests discard/recovery orchestration rather than a real OCCT fault. Neither isolation gate supplies a public isolated evaluator API, a public or production cache, cross-edit or persistent assembly identity, IsPartner-level shared-TShape ancestry, or a reviewed cross-platform golden matrix. Ordinary public Evaluator.evaluate(...) remains same-thread and cooperatively cancellable. The candidate remains unexported and unadvertised. Artifact records bind exact key metadata to detached bytes, byte length, and a SHA-256 integrity digest. Validation rejects corruption, unknown envelope fields, routing under another key, non-canonical UTF-8 strings, and oversized metadata before canonical hashing. Node IDs are capped at 1,024 UTF-8 bytes, protocol/runtime identities at 256, solver and codec compatibility fingerprints at 2,048, and aggregate canonical key material at 16,384. Record creation copies an admitted non-shared payload before its first asynchronous step, so immediate caller mutation cannot change the record; SharedArrayBuffer-backed payloads are rejected. ArtifactCacheStore requires whole-record publication and bounded reads; a custom store uses ArtifactCacheStoreLimitError to refuse a known oversized entry before materialization, and the reference memory store copies records at its boundary. Standalone helpers bound one operation. ArtifactCacheSession serializes concurrent calls so its operation and cumulative read/write counters cannot race, consumes failed work conservatively, exposes frozen usage, applies read-only/write-only modes, resolves a queued abort without letting later operations overtake the active call, and contains synchronous or asynchronous event-listener failures. Its package-private encode/write transaction reserves one operation, passes the encoder the exact smaller of the entry and remaining aggregate-write budgets, validates and copies the bytes, charges them conservatively, hashes once, and publishes one complete record. Entry-size, cancellation, codec, and store failures remain structured results. Integrity is corruption detection, not geometric validation, origin authentication, or authorization. One package-private evaluator binding now exercises that stack for a deliberately narrow OCCT candidate milestone. Callers inside the repository must assert trust: "trusted" for a tenant-isolated store and provide a solver with an explicit artifact compatibility fingerprint. The binding is unavailable from every package entry point and does not change CreateEvaluatorOptions, EvaluationOptions, GeometryKernel, or advertised kernel capabilities. Its evaluator entry point, session state, queue, and atomic transaction use ECMAScript # privacy rather than the erased TypeScript-only modifier; session construction requires an unexported runtime token, and the public session projection is frozen. Packed-package checks require both internal subpaths and every coordination method to remain unreachable. It admits only a requested solid output whose referenced node is itself a box; dependent transforms and every other feature still follow ordinary modeling. Cancellation is checked before capability or positive-dimension validation, and both validations occur before any store operation. The evaluator snapshots the document, selected configuration, parameter overrides, outputs, limits, and signal into one detached request before awaiting cache work, creates a fresh cache session per evaluation, and rejects overlapping evaluations or disposal while that private operation is active. On a miss, the private path constructs and owns the box, applies the ordinary status/measurement/empty-result checks, then encodes and writes before exposing the result. On a hit, it decodes a fresh current-kernel owner and applies those same checks. Integrity or decode corruption in read-write mode emits invalidation evidence, deletes the record, recomputes, and rewrites; read-only poison, failed eviction, store failure, codec failure, and write failure are strict evaluation failures with transactional cleanup. A key that is ineligible only because its bounded metadata cannot be represented bypasses the experiment and models normally. The box-only boundary is intentional: short-circuiting a dependency subtree would require a versioned diagnostic/topology-policy transcript so a warm evaluation cannot silently omit observable behavior. The public invariantcad/conformance boundary audits a codec without coupling it to a test framework or making it eligible. Candidate mode receives a separate development codec and requires the production kernel capability to remain absent; advertised mode captures the complete codec already published by a fresh production kernel. Neither path wraps or mutates a kernel, synthesizes a fingerprint, or conditionally skips missing support. The audit exact-matches kernel ID, artifact protocol, format, format version, and compatibility fingerprint, then runs exact semantic witnesses and golden fixtures across fresh kernel instances. For each self case it also creates a dedicated fresh producer and fresh consumers, encodes a separate pre-witness source before the audit calls status or witness code, and then observes cross-instance decodes under both disposal orders. The reviewed source factory must itself avoid observation; a black-box harness cannot enforce its internals or process-global coldness. That pre-witness branch covers the positive full-limit round trip and ownership; reduced-limit, cancellation, and malformed-input checks use the ordinary observed paths. The audit directly checks live status, ownership and mutation isolation, returned-byte limits, empty/truncated input, and pre-abort behavior. Native allocation ceilings, in-flight cancellation, hidden resource cleanup, and cross-process portability still require backend hooks and an external matrix. Passing evidence describes only the supplied corpus and runtime invocation. It is neither certification nor a cache-eligibility proof. Semantic-observation protocols v1 and v2, also exported from invariantcad/conformance, supply repository-owned release-witness projections. V1 remains byte-for-byte frozen and exact-genus-only: observeKernelShapeSemantics fails when genus is unsupported, while its existing encoder, hash prefix, types, and canonical bytes are unchanged. V2 uses the separate observeKernelShapeSemanticsV2, encodeKernelShapeSemanticObservationV2, and hashKernelShapeSemanticObservationV2 boundary and preserves unsupported genus as JSON null under a distinct v2 witness domain. The v1 and v2 codec audits are likewise separate, so accepting a v2 witness never widens v1 admission. Both protocols capture bounded, detached, deeply frozen observations. Finite IEEE-754 binary64 measurements/options/topology and Float32 mesh coordinates are big-endian hexadecimal with only negative zero normalized. Meshes become sorted oriented-triangle multisets: cyclic corner rotation and enumeration disappear, winding and multiplicity remain. Topology becomes an exact key-neutral incidence graph containing history, geometry, lineage, roles, sketch sources, and adjacency. Color refinement plus exhaustive individualization selects the lexically least labeling under separate canonical-state and node/link-work budgets rather than using ephemeral keys or enumeration to break symmetry. An observation plan must cover every feature advertised by that runtime with exactly one downstream probe or one explicit non-applicability reason, and cannot name an unadvertised feature. Successful probe results and native imports are new observer-owned shapes, are snapshotted and disposed, cannot alias the borrowed source, and are followed by source re-observation; a failing callback that mutates borrowed state violates its contract and cannot be rolled back. Requested native round trips retain the imported semantics but omit the native bytes. Relevant kernel methods, capability arrays, plans, and returned records are captured once before validation. Exact byte-size preflight occurs before full canonical stringification, and conservative triangle/topology guards avoid building an already-oversized observation. Asynchronous probes are abort-raced. Synchronous TypeScript loops and native calls do not yield to same-thread timer cancellation, so resource ceilings and an external worker/process timeout remain necessary. Trusted probes must honor their derived-shape allowance; accepted-result limits do not sandbox arbitrary callback code. The protocol is an exact normalized evaluator-semantic quotient for one reviewed plan, not a native representation identity or a proof that the plan covers every possible semantic. This layer is not in the public evaluation pipeline. No shipped Manifold, stock OCCT, or owned OCCT backend advertises shapeArtifacts; protocol test doubles and the repository-private OCCT candidate exercise codecs, and only the unexported direct-output box binding invokes one during evaluation. An ordinary evaluator created through the public API never reads, decodes, encodes, writes, deletes, or emits cache events. In the lockfile-tested Manifold 3.5.1 runtime, public Float32 Mesh reconstruction of a 1 × 2 × 3 box translated by 0.1 on X changes X bounds from [-0.4, 0.6] to [-0.4000000059604645, 0.6000000238418579] and volume from 6 to 6.000000178813934; resetting tolerance cannot restore that rounded geometry. ABI 0.7 enforces native output bytes before TypeScript materialization, checks borrowed input length before its one native snapshot, validates exact archive consumption, caps the retained decoded topology graph before full validity analysis, and owns the result transactionally. ABI 0.8 additionally limits admitted cumulative requests observed at private linker-wrapped allocator entry points to 128 MiB and reports request/allocation telemetry. ABI 0.9 closes the owned-profile BinTools grammar/count/product gap before BinTools::Read and reports bounded structural-preflight telemetry. Binary sidecar v2 closes the former intermediate-JSON amplification path, while candidate v3 removes raw producer/consumer enumeration order for canonical unique classes and verifies the complete rooted occurrence manifest. The browser-worker and Node child-process gates prove forced containment and fresh recovery around real evaluator-invoked native work in their isolated repository cases, while the browser additionally proves one private cold/write and warm/decode box cycle. The Node gate proves fresh-process owned producer/consumer agreement through the independently pinned exact-runtime loader. The private candidate fingerprint binds the verified runtime pair plus the v3 envelope, sidecar-v2, native-identity-v1 paths, occurrence-manifest schema and record width, and resource-ceiling declarations. These controls materially reduce the candidate’s attack surface, but cumulative requests are not live/peak-memory accounting, conservative structural work is not a memory proof, SHA-256 record integrity is not store authenticity, and the declared-build identity does not authenticate build execution or a publisher. The process gate does not protect against a trusted same-UID host; stock occt-wasm cannot prove shared TShape ancestry for distinct-location classes, serialized paths are not cross-edit or persistent assembly IDs, and one owned producer/consumer scenario is not a reviewed cross-platform golden matrix. Production still requires reviewed cross-platform owned-facade goldens, expansion from the private box slice to a public diagnostic-preserving evaluator contract, and a public operational isolation boundary wherever hard cancellation is promised before capability advertising.

Kernel layer

GeometryKernel owns primitives, profile features, booleans, transformations, selected-edge fillets/chamfers, selected-face shells and drafts, whole-solid offsets, tessellation, measurements, status, and lifetime management. ShapeMeasurements extends the smaller VolumetricMassProperties contract with required volume, surface area, bounds, nullable genus, tolerance, center of mass, and inertia fields. Numeric genus is the validated exact sum for connected components in the backend representation; null means unsupported and is never interchangeable with exact zero. Manifold advertises exact-per-connected-component, decomposes its mesh, validates and safe-sums every component, and releases every temporary component. Stock and owned OCCT advertise genus as unsupported because their current facade does not expose the native degenerate-edge predicate required for a correct bounded B-Rep formula. Assemblies return null because their aggregate occurrence mesh is not a Boolean-unioned closed boundary. Volume, area, center, inertia, bounds, and tolerance are unaffected. centerOfMass is a world-coordinate Vec3 | null; only an empty or zero-volume result uses null. InertiaTensor is readonly [Vec3, Vec3, Vec3], with rows expressed in world axes. It is the standard mechanics tensor about the center of mass, integral(((r dot r) I - r r^T) dV), where r is center-relative, for homogeneous unit volumetric density. Its units are mm^5. Empty and zero-volume results carry a zero tensor. Principal decomposition, point/line parallel-axis shifts, and radii of gyration live in a pure public TypeScript analysis layer rather than in the kernel protocol. The symmetric eigensolver scales the tensor, follows a fixed cyclic Jacobi pivot order, sorts moments ascending, canonicalizes a right-handed frame, and reports repeated-eigenvalue degeneracy separately from its deterministic representative axes. The same functions accept geometric volume-weighted or physical mass-weighted properties. They validate finite, symmetric, mechanically admissible tensors and never retain kernel handles. The protocol is explicitly versioned. Backends declare primitive, feature, native-import, native-export, and topology capabilities; the evaluator rejects unsupported operations before invoking them. Shell capability requires face-topology selection and the complete inward/outward, fixed-round-join, explicit-tolerance contract. Offset capability requires the complete whole-solid direction, fixed-round-join, explicit-tolerance, and body-cardinality contract but no topology selector capability. Draft requires both ordinary feature support and the stronger feature-scoped exactIndexedTopologyEvolution v1 promise. Boolean, fillet, chamfer, shell, and offset require ordinary feature support; exact indexed evolution is additive and optional for those operations, so its absence retains the base partial-history path while malformed advertised metadata is a protocol failure. Exact fillet/chamfer and shell metadata is preflighted before their selectors resolve. These scoped promises guarantee complete mapping for only their listed features without upgrading the backend’s global topology provenance beyond feature. Shape validity is normalized into backend-neutral status data, while meshing accepts explicit linear/angular deflection options. Stable feature IDs and cancellation signals travel through KernelFeatureContext without entering kernel shape handles. A topology-capable kernel returns an evaluation-scoped snapshot of exact B-Rep faces, edges, and vertices. Face and edge descriptors contain an opaque key, analytic geometry where available, measurements, bounds, adjacency, and proven lineage; a vertex descriptor contains its key, exact point, incident edges, and lineage. Keys exist only to connect one snapshot to the immediately following kernel call. They are never written to a document or used as persistent identity. Snapshot validation rejects duplicate keys across all three kinds, non-finite geometry, dangling adjacency, and non-reciprocal face↔edge or edge↔vertex incidence as kernel protocol failures. Ordinary topology-selection explanation version 1 runs the same query algebra and cardinality analysis as resolveTopologySelection. A completed, deeply frozen TopologySelectionResolutionExplanation records the topology kind, current history mode, universe and match counts, and requested minimum/maximum cardinality; the maximum is null when unbounded. Missing and ambiguous cardinality are successful explanation outcomes, while invalid selectors, snapshots, query evaluation, and any nested selection failure—including persistent-reference resolution—remain failed operations. Only a resolved explanation contains the sorted current evaluation-scoped keys. Missing and ambiguous explanations expose no keys. Legacy missing/ambiguous resolution diagnostics carry the corresponding report in details.explanation. Each direct resolve or explain call performs its own normalization and selection pass; ordinary selection explanations do not introduce a shared cross-call session. Topology-signature protocol v2 is the current bounded cross-evaluation reference layer over those snapshots. EvaluatedSolid.topology() validates the kernel response and exposes a detached, deeply frozen face/edge/vertex snapshot through a CadResult; captureTopologyReference then replaces one evaluation-scoped key with a deeply frozen, key-free PersistentTopologyReference. The reference records its topology kind, capture-history status, caller-selected linear/angular/relative tolerances, canonical semantic lineage, structured geometry, and canonically ordered one-hop adjacency evidence. V2 face evidence includes edges, edge evidence includes faces and vertices, and vertex evidence includes its point and incident edges. Positional and bounds comparisons use absolute linear tolerance, independent of world-space origin; relative tolerance is reserved for measures and radii. The reference contains no native index, snapshot ordinal, or enumeration-derived discriminator. Capture must find exactly one matching item in the source snapshot, so symmetric topology—including distinct coincident vertices with indistinguishable evidence—is rejected instead of receiving an invented identity. Compatibility is additive and optional. KernelTopologyCapabilities.signatures, when present, declares the primary protocol and a non-empty semantic descriptor fingerprint; signatureProfiles may add exact older protocol/fingerprint pairs without repeating the primary. A fingerprint declares matching descriptor semantics, not a cryptographic digest or attestation of native JavaScript, WASM, or other runtime bytes. Resolution requires exact protocol and fingerprint equality. The known stock runtime and every recognized owned facade advertise protocol v2 with primary invariantcad-topology-descriptor@6. They also expose one exact protocol-v1 compatibility profile: stock and owned ABI 0.2–0.4 use precisely the descriptor @4 fingerprint they advertised before v2, while owned ABI 0.5+ uses precisely its former descriptor @5 fingerprint. Evaluation selects the highest compatible protocol deterministically, so new captures use v2/@6 while stored v1 @4/@5 variants continue to resolve without recapture. Protocol v1’s face/edge wire structure, canonical bytes, evidence construction, and matching remain frozen; in particular, it ignores vertex descriptors and edge-vertex incidence. Descriptor versions are independent of Document v6, signature protocol versions, exact-evolution protocol v1, and facade ABI 0.9. ABI 0.9 retains ABI 0.6’s modeling/history surface, ABI 0.7’s bounded artifact transport, and ABI 0.8’s private cumulative native allocation-request budget, then adds exact owned-profile BinTools-v4 structural preflight only for the repository-private candidate. The OCCT adapter advertises full fingerprints for its known default stock runtime and recognized owned facades; an explicit binary override or unknown custom module factory receives no declaration unless owned-facade probing recognizes it. A kernel without an optional declaration makes no persistent-reference promise. Malformed references and signature inputs fail with signature diagnostics, while malformed kernel snapshots remain kernel protocol failures. Exact indexed evolution remains identity-only at the persistent boundary. PRESERVED and MODIFIED successors may carry already-proven semantic roles and sketch sources. GENERATED does not copy source identity, and residual source-less CREATED items record only feature causality. Descriptor @5 adds one strict exception that names a generated class without copying identity: an identity-less fillet/chamfer result face receives fillet.face.blend or chamfer.face.bevel only when the complete graph has an incoming exact GENERATED relation from a source edge. The reduction does not inspect surface type, result enumeration, or the authored seed indices. Generated edges, vertex-caused faces, residual-created topology, and generated Boolean/shell/offset topology remain unnamed. The roles are class-level: several result faces may share the same { feature, role } anchor, in which case persistent capture or resolution fails ambiguous rather than using geometry to choose one. The owned ABI 0.6 persistence gate pins semantic survival across amount changes, downstream role consumption, two-contour ambiguity, and geometry-only behavior for the remaining unnamed topology. Resolution separates design evidence from geometric evidence. When both snapshots have complete history and the item has a stable role or sketch-source creation anchor, exact anchor agreement produces semantic-lineage evidence and conflicting anchors are authoritative. A protocol-v2 vertex has no direct role, but when every incident edge on both sides has authoritative semantic anchors, exact one-to-one agreement of that complete edge-anchor set likewise produces semantic-lineage; this lets a proved corner survive translation or dimensional change without treating its old point as identity. If that complete anchored context is unavailable, including whenever either snapshot has partial history, matching falls back to toleranced geometry-adjacency evidence for the item and its incident one-hop neighbors. Exactly one candidate returns its new evaluation-scoped key; zero and multiple candidates produce structured missing and ambiguous failures. V2 covers faces, edges, and vertices; v1 remains the frozen face/edge protocol. Distinct vertices with indistinguishable point and edge evidence remain ambiguous. Topology-reference explanation version 1 instruments its bounded matching pass without an additional candidate traversal inside that analysis. Its frozen aggregate records history modes, stored-anchor count, and considered/matched totals split between the semantic and geometry/adjacency strategies. A completed explanation treats missing and ambiguous identity as explicit outcomes, while malformed inputs, incompatible fingerprints, and exhausted limits remain failed operations. Only a uniquely resolved report contains a current key; non-resolved reports intentionally contain no candidate samples or per-candidate rejection claims because those would expose model data or freeze matcher short-circuit details as public semantics. Separate direct resolution and explanation calls each normalize and search their inputs. The explainable operation-local session instead caches one shared analysis by reference-object identity and projects both explanation and legacy fail-closed resolution without another snapshot read, candidate traversal, or budget charge. Document schema v2 owns persistent intent in an optional topologyReferences registry. Each stable reference ID binds one topology kind, one exact solid-node target, and a nonempty set of normalized variants unique by signature-protocol version and kernel fingerprint. A persistentReference query atom names that entry and composes with the ordinary logical and adjacency algebra. Document v3 retains that surface and first admits loft roles; v4 adds the six sweep roles; v5 adds the two exact edge-treatment face roles in origin queries and every stored lineage/adjacency location; v6 adds vertex references, vertex position queries, and face↔edge/edge↔vertex adjacency while leaving the v5 role set unchanged. The target must be the consuming fillet, chamfer, shell, or draft feature’s direct input; an ancestor, descendant, unrelated target, or foreign authoring handle is invalid. Stored historical lineage IDs are evidence rather than graph dependencies and need not remain live nodes. Registry contents are canonical document semantics and therefore affect serialization and hashes. V1 remains parseable and hash-preserving and rejects the persistent atom and registry; v1/v2 reject loft, sweep, and treatment roles; v3 rejects sweep and treatment roles; v4 rejects treatment roles; v5 admits them but remains face/edge-only; v6 admits vertices. Explicit migration upgrades v1–v5 to v6 while retaining every stored protocol version, descriptor fingerprint, and evidence record verbatim, and v6 migration is idempotent. Evaluation preflights persistent selectors before resolving input geometry: the kernel must expose every topology kind and evidence surface required by the selected signature profile, and every referenced entry must contain an exactly matching protocol/fingerprint variant. A v2 profile requires complete face, edge, and vertex descriptor support; a v1 profile retains its original face/edge requirement. One operation-local resolution group detaches the snapshot once; its profile-specific matchers share one cumulative matching budget, reuse compiled evidence within each profile, and cache repeated reference IDs. The same detached snapshot serves ordinary atoms in the expression. Reference failure is fatal through and, or, not, and nested adjacency; set algebra never converts an invalid or ambiguous reference into success. Capture, direct resolution, and document evaluation accept partial operational TopologySignatureLimits, normalized against the frozen DEFAULT_TOPOLOGY_SIGNATURE_LIMITS: 100_000 topology items, 1_000_000 adjacency entries, 1_000_000 lineage evidence records, 20_000 stored reference variants inspected per persistent-selection operation, 1_000_000 candidate-pair checks, and 10_000_000 evidence-comparison/adjacency-matching steps. A valid snapshot records each face↔edge and edge↔vertex incidence reciprocally, so each incidence consumes two adjacency entries. Resolution copies and meters its reference and snapshot independently against the adjacency/evidence size ceilings in their respective normalization passes, using one captured length per array and never invoking caller iteration hooks. Operation-scoped counters count stored variants across distinct reference IDs, then share outer topology comparisons, neighbor-pair checks, lineage comparisons, and iterative matching steps across every profile. During document evaluation, one such operation is scoped to one feature resolution. Canonical descriptor evidence, shared neighbor signatures, sort keys, anchors, and created-feature sets are compiled once per operation rather than recomputed for each candidate. One-hop adjacency compatibility is solved by an iterative augmenting-path bipartite matcher; neither evidence construction nor matching recursively follows neighbors-of-neighbors. Exceeding any ceiling returns TOPOLOGY_SIGNATURE_LIMIT_EXCEEDED with the resource, limit, and actual count. Overrides must be non-negative safe integers and may not contain unknown keys. These limits bound TypeScript signature processing after the snapshot has been produced, not kernel topology enumeration, native operation memory, or the independent exact-history record budgets. Untrusted document values are copied once into a detached, plain snapshot under DesignDocumentLimits before recursive schema validation or freezing. Schemas consume only that snapshot, preventing accessors or proxies from changing data after preflight. The pass bounds UTF-8 text bytes, every structural occurrence including aliases, nesting, actual selector-query nodes, registry entries and variants, stored adjacency, and stored lineage evidence; it also rejects sparse arrays, object cycles, and non-JSON object instances. These parse limits are operational API options and never enter canonical IR or hashes. Semantic roles are a closed, kernel-neutral document vocabulary. A role records construction intent in per-subshape lineage: signed local box faces, unique box face-intersection edges, cylinder/cone caps and rims, the sphere surface, extrusion caps/sides/rims/lateral edges, revolution swept/cap faces, five bounded ruled-loft roles, and six bounded-sweep roles. Extrusion side faces and start/end rim edges may carry the sketch and curve entity that generated them. Each revolution boundary curve that produces a face similarly maps to a source-aware revolve.face.swept; a boundary line contained in the local-v revolution axis collapses and maps to no face. Partial turns add source-free start/end cap roles, while full turns omit caps. Every revolution edge, seam, pole, and other kernel artifact remains unnamed. For an ordered ruled loft, loft.face.start-cap and loft.face.end-cap name the first and last section faces without a sketch-curve source. loft.face.side names the single ruled face between corresponding curve indices on each adjacent profile pair and records both participating boundary curves as separate sketch-entity sources when the resolved curves provide them. loft.edge.section-rim names each authored section-boundary edge and likewise carries only an available curve source. Direct source-free profiles keep semantic roles without gaining invented sources. For a non-circular curve, loft.edge.lateral names the source-free edge joining its authored starts across one adjacent section pair; a circle has no authored boundary start, so its kernel seam stays unnamed. These semantics are limited to the current compatible, parallel-plane, hole-free ruled-solid contract with aligned authored curve phase; a cyclic loop-index shift is rejected instead of delegating correspondence to OCCT. They assign no semantic roles to the loft’s vertices. For a bounded sweep, let C be the direct profile’s boundary-curve count, S the authored path-segment count, and V the count of authored non-circular profile-curve starts. The exact inventory is one sweep.face.start-cap, one sweep.face.end-cap, C*S sweep.face.side faces, C sweep.edge.start-rim edges, C sweep.edge.end-rim edges, and V*S sweep.edge.lateral edges. Start and end follow authored path direction rather than world orientation. A side, start rim, or end rim carries only the optional sketch-entity source of its corresponding direct-profile curve. Caps and laterals are source-free, and direct calls whose resolved profiles have no sources keep their roles without gaining invented sources. Path segments have no source identity. Edges internal to path joints and right-corner miter fragments are unnamed, as are arbitrary seams for circular profile curves. The OCCT adapter proves construction-specific feature lineage for primitives, extrusions, revolutions, lofts, bounded sweeps, and topology-preserving transforms when every required correspondence closes. It classifies primitive roles from construction-aware geometry and maps extrusion and revolution sources with analytic per-curve seeds. Revolution annotation separately constructs each expected swept face and, for a partial turn, both caps; every seed must correspond to exactly one result face. Ruled-loft annotation retains the section faces and analytic section curves, constructs each adjacent pair’s per-curve ruled side independently, and locates each required non-circular lateral edge by its two authored start points. It also verifies complete per-role coverage, counting each topology item once per role even when a side carries two sources. Any construction failure, missing or non-unique required side/lateral seed, ambiguous result correspondence, or incomplete expected coverage downgrades the complete loft snapshot to partial history instead of silently publishing a possibly incomplete role map. Sweep annotation instead proves the local segment boundary graph against the final result graph. It geometry-matches the retained direct profile to exactly one start cap, maps each direct-profile curve to one start rim and first-layer side, walks one unique side-face layer per authored segment without reusing or skipping result faces, derives the sole remaining terminal cap and its rims, and verifies the same-segment neighboring-curve laterals plus the exact role inventory. A branch, disappearance, reused candidate, ambiguous seed, incomplete graph coverage, unexpected nonlocal adjacency, or distant false mapping sets the entire sweep history to partial. It never fills a gap from path-segment identity because no such source identity exists. A transform applies the identical operation sequence to retained input subshapes, then requires one-to-one geometric coverage before carrying their lineage forward. The owned facade ABI 0.4 adds complete Boolean evolution, ABI 0.5 adds complete fillet/chamfer evolution, and ABI 0.6 adds complete shell/whole-solid-offset evolution. Stock OCCT and earlier owned ABIs retain partial history for each otherwise-supported feature family. Manifold supports its declared geometry features but advertises no topology snapshot capability. An origin selector against partial history fails explicitly; geometry-only selectors can still operate on an available snapshot because they do not claim lost provenance. The pinned OCCT wrapper’s high-level evolution extractor omits destruction of its Embind-owned result container. On stock OCCT and owned ABIs 0.2–0.4, InvariantCAD therefore invokes the compatible raw history entry points for fillets and chamfers, copies their result before adoption, and deterministically releases the returned container plus every input and output vector. This legacy path closes the native lifetime gap but remains explicitly partial because its face-hash payload cannot prove complete indexed face/edge/vertex identity. ABI 0.5 uses a separate owned transaction rather than promoting that payload. The owned facade contains an internal atomic multi-face draft ABI with arbitrary neutral planes and an independent pull direction. It validates every adapter-trusted raw face reference before a single build, rejects the pinned kernel’s silent abs(angleRad) <= 1e-4 no-op range, and keeps the result report-owned until an exactly-once transfer into the originating kernel. Facade ABI 0.2 introduced a versioned six-field indexed evolution envelope and refuses success unless every input face, edge, and vertex has a unique same-kind result successor and every result is claimed. Its zero-based indices are evaluation-scoped positions in unique located-subshape maps, not persistent IDs, oriented occurrences, assemblies, or an incidence graph. IsSame defines map membership while IsEqual distinguishes preserved from orientation-modified occurrences. The immutable history survives report cloning and result transfer. Facade ABI 0.3 adds a separate transactional PipeShell report. Native code validates the two wire IDs, fixes corrected-Frenet and right-corner semantics, applies the three TypeScript-selected tolerances, builds and solidifies at most once (exactly once on success), and exposes OCCT’s measured surface approximation error. A successful result remains report-owned outside the arena until a same-kernel one-shot transfer. TypeScript validates exact tolerance echoes, build counters, quality bounds, transfer state, topology, body purity, authored edge geometry, and an independent transported-profile volume oracle before ownership can escape. Facade ABI 0.4 retains the draft and PipeShell surfaces and adds a transactional, potentially multi-tool Boolean report for union, subtraction, and intersection. Its input table is fixed as target source 0, then authored tool sources 1..N. Union and intersection run ordered sequential Fuse/Common steps; subtraction runs one Cut whose arguments contain the target and whose tools contain the complete authored tool set. Native code first makes a topology-independent working copy of every operand while sharing immutable geometry, proves a one-to-one original-to-copy mapping for each indexed face, edge, and vertex, and exposes only those copies to OCCT’s non-destructive Boolean builders. This isolates the arena-owned target and tool TShapes, including their serialized status flags, so their BREP bytes remain stable. Native code freezes the resulting BRepTools_History into a complete version-1 graph over every unique located face, edge, and vertex before exposing success. The complete graph contract has five relations. PRESERVED and MODIFIED link a source to a same-kind result. GENERATED links an input cause to a result and may cross topology kind. The facade retains every available native relation of those three kinds. DELETED proves that a source has no final identity successor and uses resultKind = NONE plus resultIndex = -1; an intermediate stale OCCT removal flag cannot delete a source that is present or modified in the final result. Every input subshape must have at least one identity successor or a DELETED record, exclusively; generated links may coexist but do not satisfy that identity/deletion requirement. Native history can leave final topology unattributed to a particular operand. After harvesting all operand claims, each such residual result uses source-less CREATED with the exact source sentinel -1/NONE/-1. Every result must have one or more operand claims or exactly one CREATED record, never both. Duplicate records are canonicalized, contradictory links and incomplete coverage fail the history stage, and a valid empty result is represented by zero result counts rather than fabricated records. The TypeScript draft adapter validates its envelope as an exact face/edge/vertex bijection. The Boolean adapter instead validates the complete non-bijective graph, exact operation and build-count echoes, target/tool count and order, and raw topology counts for every input and the result. maxExactBooleanHistoryRecords is a caller-controlled signed 32-bit resource budget with a 1_000_000 default. It is passed into the native operation, which refuses to materialize more report records, while TypeScript validates the returned count before making any indexed record call. The budget does not cover the mandatory isolated operand copies or OCCT’s internal Boolean workspace, both of which scale with input topology. Both adapters copy and freeze report-owned data before transfer, require a READY same-kernel one-shot transfer, and release a transferred root exactly once if adoption or post-transfer reduction fails. A malformed exact report is authoritative protocol failure; it is never silently downgraded to partial history. Public Boolean lineage follows identity rather than causality. Only same-kind PRESERVED and MODIFIED predecessors inherit prior feature lineage, semantic roles, or sketch sources. GENERATED records prove causal coverage but never copy source naming, while source-less CREATED records prove residual result coverage without inventing an operand cause. A generated-only or source-less-created face or edge receives only { feature: currentBoolean, relation: "created" }; a result with an identity predecessor retains that identity and records the current Boolean as modified only when an identity link says it changed. Reduction is canonical in target/tool and subshape-index order, independent of native record order. Partial input history remains partial even when the current graph is complete. Facade ABI 0.5 retains every earlier surface and adds one transactional edge-treatment operation with stable fillet/chamfer operation codes. TypeScript deduplicates selected edge keys and sorts their input-snapshot indices before native execution. Native code echoes that canonical list, expands each first seed to the maximal tangent contour, skips later seeds already covered by an admitted contour, and stages every admitted contour into one builder invocation. Thus selector cardinality remains seed cardinality, overlapping seeds are idempotent, and native diagnostics prove the exact selection and contour progress used by the operation. Before fillet or chamfer construction, ABI 0.5 extracts the sole solid from either a direct solid or a recursively nested one-child compound/compsolid wrapper; any loose or multiple topology fails validation. This permits exact Boolean output to compose directly into an edge treatment, while successful maker output is normalized back to the contained solid. Native code makes a deep independent B-Rep working copy of that solid, including its curve and surface geometry, and proves one-to-one original/copy face-edge-vertex correspondence before the builder runs. Only the copy is treated, leaving the arena input BREP byte-stable. A successful report owns the result and freezes a complete version-1 graph over every source and result face, edge, and vertex. It retains all available preserved, modified, and generated relations, emits deletion only without a final identity successor, and uses source-less CREATED only for otherwise-unclaimed result topology. Public reduction retains the Boolean identity rule, then assigns the operation’s one class role only to identity-less result faces proved by incoming exact edge→face GENERATED records. The role carries no source identity; all residual-created faces and all generated/residual-created edges remain unnamed. An exact local graph never upgrades partial input history. The edge-treatment adapter validates operation, amount, canonical seed echo, build/contour counters, raw topology counts, sentinels, and complete graph coverage before accepting a READY same-kernel one-shot transfer. maxExactEdgeTreatmentHistoryRecords is its separate caller-controlled signed 32-bit record budget with a 1_000_000 default; it is enforced natively before record materialization and checked before indexed JavaScript copying. It is independent of maxExactBooleanHistoryRecords and does not bound the mandatory operand copy or OCCT builder workspace. Report-owned and transferred results each have one release path, so validation, adoption, cancellation, or lineage-reduction failure cannot leak or expose a half-adopted shape. Facade ABI 0.6 retains every earlier surface and adds one transactional solid-offset report with stable shell/offset and inward/outward codes. Shell openings are deduplicated and sorted by input face index before native execution, and the report must echo that canonical selection; whole-solid offset accepts no opening faces. Both modes validate a pure single solid, map any selected openings onto a deep topology-independent BREP copy, run exactly one fixed-round-join builder, and require one valid positive-volume single-solid result with direction-consistent volume. Only the copy enters the builder, so success and failure leave the arena-owned input BREP byte-stable. The pinned BRepOffset history can report a source with only Generated successors while IsDeleted remains false even though that source identity is absent from the final shape. Before building the complete graph, ABI 0.6 reconciles this case from exact final-result membership: absent identity plus no Modified successor becomes terminal deletion while all generated links are retained. This is not applied mechanically to shell openings. A selected opening is a maker input, and OCCT can report that source face as MODIFIED into the planar opening rim; selection alone never forces DELETED. The solid-offset adapter validates operation, direction, amount, tolerance, canonical opening echo, build/status fields, raw topology counts, sentinels, and complete graph coverage before accepting a READY same-kernel one-shot transfer. It reduces public lineage with the same identity-only rule as Boolean and edge treatment. maxExactSolidOffsetHistoryRecords is a third, independently enforced signed 32-bit record budget with a 1_000_000 default; it shares neither of the existing budgets and does not bound the mandatory deep operand copy or OCCT builder workspace. Report-owned and transferred results retain exactly one release path through validation, adoption, cancellation, and lineage reduction. createOcctKernel advertises draft only when an InvariantCAD-owned generated runtime loads a module whose exact facade probe succeeds. ABI 0.2 advertises exact evolution for draft, ABI 0.3 retains that and adds controlled PipeShell, ABI 0.4 adds exact Boolean evolution, ABI 0.5 adds fillet/chamfer evolution, and ABI 0.6 advertises exactIndexedTopologyEvolution v1 for draft, boolean, fillet, chamfer, shell, and offset. Current ABI 0.9 retains that complete modeling/history capability set, ABI 0.7’s bounded artifact transport, and ABI 0.8’s private cumulative native allocation-request budget, then adds exact owned-profile BinTools-v4 structural preflight only for the repository-private candidate; it still does not advertise shapeArtifacts. Before its first asynchronous import, createOcctKernel snapshots every caller-owned initialization field: it brand-checks and copies raw ArrayBuffer/Uint8Array WASM input, captures even a cross-realm URL’s href, copies tessellation options, captures the factory, tolerance, output callbacks, normalized history limits, and any opaque attested runtime authority, and later builds both the module and runtime fingerprint from those call-time values. Mutation after the call therefore cannot make an explicitly supplied runtime execute under a false stock identity. An attested runtime supplies its module factory and a fresh verified WASM copy together, cannot be combined with wasm or moduleFactory, and adds its exact pair identity only to the private artifact fingerprint. Raw factories may still locate their matched sibling WASM or accept an explicit wasm override, but those direct paths do not acquire an attested pair identity. Default initialization loads stock OCCT, retains its other exact geometry features, and leaves draft plus exact indexed Boolean, edge-treatment, and solid-offset evolution unadvertised. Stock and legacy owned facades therefore remain valid partial-history implementations where they support the base geometry operation; Manifold remains a geometry-only backend without topology snapshots. A partial, unknown, or mismatched facade probe fails closed. The owned generated pair remains outside the npm tarball. Repository tooling can copy a completed local build into a versioned, package-neutral directory and deterministic .tar.gz, add checksums, provenance, an SBOM, source/relinking information, notices, and licenses, and verify both representations before the packed npm library is installed in a clean temporary consumer and its public adapter is exercised against the explicitly supplied bundled runtime. The ordinary npm package smoke stays artifact-independent. Packaging never builds or downloads native code, and runtime initialization never discovers or fetches the bundle implicitly. These generated compliance materials support a release review but do not certify legal compliance. Publishing the bundle remains a separate, externally reviewed release step. ManifoldKernel is the initial implementation. It copies upstream mesh buffers into InvariantCAD’s stable MeshData, checks kernel status, and destroys every WASM object. Center of mass and inertia are integrated from the closed emitted polyhedron after translating coordinates near the solid, reducing cancellation at large world offsets. The public API sees only typed arrays and measurements. The exact backend uses OpenCascade for analytic profile evaluation, B-Rep primitives and core features, native recentered B-Rep mass-property integration, exact face-selected inward/outward shelling, exact whole-solid offsets, exact STEP/BREP exchange, and the bounded semantic-topology slice described above. Its known stock and recognized owned runtimes advertise topology-signature protocol v2 with primary descriptor @6; they additionally retain one exact protocol-v1 compatibility profile using descriptor @4 for stock/owned ABI 0.2–0.4 or descriptor @5 for owned ABI 0.5+, with runtime-family and modeling-tolerance fields completing every fingerprint. The matched owned ABI 0.9 facade retains the complete ABI 0.6 modeling/history surface: atomic semantic-face draft, all three Boolean operations, constant-radius fillet/equal-distance chamfer, and shell/whole-solid offset with exact indexed face/edge/vertex evolution, plus ABI 0.3’s controlled composite PipeShell transfer for the advertised major multi-arc/eccentric-profile refinements. It retains ABI 0.7’s bounded shape-artifact transport and ABI 0.8’s 128 MiB cumulative native allocation-request budget, then adds exact owned-profile structural preflight before OCCT artifact deserialization; all remain reachable only through the repository-private candidate and are not advertised as a kernel capability. Shell and offset both enforce one-solid/no-loose-topology boundaries rather than applying implicitly to disconnected bodies. The offset adapter operates on the extracted sole solid because applying the pinned raw operation to a compound wrapper can return a shell instead of a solid. It also normalizes reversed inputs before mapping direction and rejects negative-volume results rather than repairing an inside-out collapse. STL and OBJ remain backend-neutral exports of explicitly tessellated meshes. NURBS authoring, public healing controls, exact history beyond the owned feature-scoped paths, broader feature-family naming, semantic vertex roles, and comprehensive topology identity remain roadmap work. Every backend implements the same conformance corpus, comparing toleranced geometry rather than byte-identical tessellations.

Evaluation layer

Evaluation performs these operations in order:
  1. structural and semantic validation;
  2. exact named-configuration selection;
  3. parameter dependency resolution and bounds checking, with call-time values taking precedence over selected-configuration expressions and then authored defaults;
  4. document-owned material-density resolution and positivity checks;
  5. lazy feature-DAG traversal from selected outputs;
  6. sketch solving;
  7. geometry-derived feature/refinement and topology capability preflight, plus selector resolution for consuming features;
  8. kernel feature execution and status checks;
  9. configuration-aware part and nested-assembly occurrence resolution;
  10. construction of disposable evaluated outputs.
Evaluated assemblies aggregate occurrence mass properties rather than treating their combined tessellation as one opaque measurement. Each occurrence’s center and central second moment follow its full affine placement; the aggregate center and tensor then use volume weighting and parallel-axis shifts. This preserves correct translation, rotation, reflection, and nonuniform-scale semantics while counting repeated definitions once per occurrence. Physical properties form a separate typed layer. DesignDocument.materials owns reusable definitions keyed by stable material ID; every definition contains an explicit massDensity expression in the canonical kg/mm^3 unit. A part records that relationship as PartNodeIR.materialId, authored with a same-builder typed materialRef. The existing PartNodeIR.material string remains a descriptive compatibility field and has no implicit lookup behavior; authoring makes the label and reference mutually exclusive. A selected configuration’s partMaterialOverrides replaces the authored material reference for the targeted part definition. Density resolution is strictly part.massDensity first, then the effective referenced or substituted definition’s massDensity, then missing. IDs and names are never searched or heuristically matched. Every supplied density resolves during evaluation and must be finite and strictly positive. DesignDocument.configurations, when present, is a canonical registry keyed by stable configuration ID. Each non-empty entry may contain parameterOverrides, instanceSuppressions, and partMaterialOverrides, plus description and metadata. The registry is omitted rather than serialized as an empty object when the design has no configurations. Parameter overrides are dimension-checked expressions. Instance suppression is keyed first by an assembly-definition node and then by one of its direct authored instance IDs; material substitution is keyed by a part-definition node and resolves to a document-owned material ID. These definition-scoped targets avoid ambiguous flattened occurrence paths and make a reused subassembly or part respond consistently in every occurrence. An explicit false suppression value re-enables an authored-suppressed instance. Geometry measurements may be cached by KernelShape, but density-scaled results may not: multiple part definitions can deliberately share geometry while using different densities. EvaluatedPart scales its central volumetric properties directly. EvaluatedAssembly first checks that every active flattened leaf has density, transforms each cached geometric property through the occurrence’s full affine placement, scales it independently, and combines bodies by mass-weighted centers and parallel-axis shifts. Missing density is a structured CadResult failure for complete physical-property analysis, while suppressed leaves and empty assemblies retain explicit zero semantics. The bill-of-materials layer deliberately follows product structure rather than geometry identity or display text. Active nested assembly leaves are flattened to stable occurrence paths, authored- or configuration-suppressed branches are omitted, and items are grouped by part-node ID. Part number, description, and effective material are reported attributes; missing or duplicate values never cause two definitions to be silently merged. Item order, occurrence-path order, and diagnostics are deterministic. Each BOM item reports both its unplaced definition mass and the sum of its placed occurrence masses. The latter uses the full affine transform, including reflection and volume-changing scale, rather than assuming definitionMass * quantity. Overlap remains additive. Missing density is a warning-level partial result: quantity remains exact, knownMass sums the computable occurrences, massComplete is false, and totalMass is null. Complete and empty BOMs have a non-null total. Every successful BOM includes the selected configurationId, or null for the base design; EvaluatedDesign exposes the same identity alongside its effective parameter map. Effectivity and alternate/substitute components remain outside this base contract. Composite-sweep refinement preflight is kernel-neutral. A shared classifier resolves the exact arc sweeps, computes certified analytic profile area/centroid moments, and derives the canonical major-multiple-arcs / major-eccentric-profile subset before kernel execution. Missing support produces a capability diagnostic; malformed versioned metadata produces a protocol diagnostic. Geometry that needs neither refinement does not depend on the optional envelope. Exact Boolean evolution preflight is also optional and kernel-neutral. Missing metadata means the evaluator executes the declared Boolean feature with partial history. Well-formed ABI 0.4-or-later metadata selects the owned exact transaction; malformed metadata fails before kernel invocation. Empty intersections or cuts are valid kernel results at this layer and then pass through the evaluator’s ordinary EMPTY_RESULT diagnostic, becoming a warning only when allowEmpty is enabled. Exact fillet/chamfer evolution uses the same optional feature-scoped preflight, but it runs before the edge selector is resolved. Missing metadata or a well-formed feature omission preserves the legacy partial-history path. ABI 0.5 metadata requires an exact kernel with face and edge topology, feature/history provenance, and topology(); malformed or insufficient declarations fail before topology inspection or the edge-treatment kernel method is invoked. Exact shell/offset evolution is optional and feature-scoped too. Missing metadata or a well-formed omission preserves stock or legacy owned exact geometry with partial history. ABI 0.6 shell metadata is validated before its face selector resolves, while offset metadata is validated before kernel execution; malformed metadata or an insufficient exact/topology declaration fails at that boundary rather than downgrading or exposing a result. One feature is evaluated once per run. Protocol-v1/v2 topology descriptor fingerprints gate detached reference matching only; they are not complete evaluation or cache keys. Authored change-impact reports do not validate cached geometry. Feature-hash v1 supplies bounded effective-intent Merkle identity, artifact-cache v1 formalizes compatibility-bound keys, codec ownership, integrity-checked records, stores, and limits, and semantic-observation v1/v2 supplies versioned canonical finite conformance quotients. None validates a cached shape by itself. Kernel codecs return detached caller-owned bytes, borrow decode input, enforce byte ceilings and cancellation, and clean partial native work on failure. Solver compatibility is separately fail-closed: the built-in floating-point reference solver advertises no cross-run artifact fingerprint until exact runtime conformance is established. These foundations do not make cross-run reuse operational: no production backend supplies the complete codec and the evaluator has no cache read/decode or encode/write path. Evaluated shapes are owned by exactly one evaluation result. Disposing that result releases its backend handles; disposing it again is safe. A kernel rejects foreign handles, and destroying the kernel releases any shapes that remain live.

Coordinate conventions

  • Right-handed 3D coordinates.
  • Millimetres and radians in documents.
  • Positive extrusion follows the sketch-plane normal.
  • Principal-plane bases are:
    • XY: U=+X, V=+Y, N=+Z
    • XZ: U=+X, V=+Z, N=-Y
    • YZ: U=+Y, V=+Z, N=+X
  • Revolve uses the sketch’s local V/Y axis.
  • Loft section stations follow the sketch-plane normal and must be strictly monotonic; current lofts are ruled solids with ordered curve-index correspondence.
  • Polyline sweep paths are open, explicitly segmented 3D values. Current solid sweeps seat a hole-free profile at the path start, require its plane normal to be parallel to the first segment in either direction, and use corrected-Frenet transport with right-corner intersection transitions.
  • Circular-arc sweep paths are one exact oriented circle trajectory selected by authored start, through, and end points. They use the analytic start tangent, admit minor or major arcs below one full turn, and require the profile envelope to remain strictly inside the circumradius. For one circular edge, corrected-Frenet transport is exactly a revolution about the resolved circle axis; the OCCT adapter snaps a profile origin already within the admitted tolerance to the exact path start, uses that specialized construction, supports near-full open arcs without an artificial endpoint-clearance rule, and adds a minimum three-point triangle-angle sine floor of 3e-8.
  • Composite sweep paths are ordered exact line/circular-arc chains. Every segment start is structurally the preceding endpoint, so no tolerance healing or independent reorientation is permitted. The current bounded contract requires at least two segments and one arc, permits right-corner line-line joins, requires forward G1 tangency at every arc-bearing join, and rejects redundant same-line/same-circle splits. Minor, major, and near-full traversals below one turn share the same exact arc representation. For each adjacent arc-bearing pair, only the triangular intrinsic domain below (π - junctionTurn) * min(radius) is treated as the shared local neighborhood; every remaining parameter pair is certified by recursive exact-chord and circular-sagitta distance bounds. The same bounds certify all nonadjacent line/arc pairs. Path simplicity uses path tolerance, sweep clearance uses the complete profile diameter plus tolerance, and numeric ambiguity fails explicitly instead of becoming sampled acceptance. Arcs strictly above π + 1e-12 trigger refinement classification. Exact line/arc/circle Green-theorem moments determine the seated local profile centroid; semantic holes subtract independently of authored winding, and compensated arithmetic plus explicit roundoff bounds prevents an equality-at-tolerance profile from being spuriously classified as eccentric.
  • Circular-revolution results retain the exact swept volume computed from the planar profile area, the profile-normal component of its centroid’s rotational velocity, and the selected sweep. This is Pappus’s theorem under exact tangent alignment and remains correct for the small tolerance-admitted angular mismatch. It avoids cancellation in OCCT’s native volume integration for very thin sections at large radii; rigid transforms preserve the value and scale transforms apply their absolute determinant.
  • When a sweep carries that authoritative analytic volume, OCCT’s native central tensor is rescaled by the analytic-to-native volume ratio after recentered integration. The native center is unchanged. This keeps the returned density-one volume and tensor mutually normalized without replacing exact sweep-volume semantics.
  • Circular and composite volume semantics use the analytic local area/centroid moments as their sole source. Arc geometry exposes a center offset from its authored start, and volume identities consume that plus the seated centroid offset, so neither path nor profile arithmetic reconstructs a small relative vector by subtracting rounded world coordinates. OCCT profile-face area and centroid are retained only as an independent certificate before path allocation. Its allowance combines analytic roundoff, exact boundary length, a conservative boundary radius about the actual centroid offset, modeling tolerance, reliable remaining area, and per-world-axis ULPs; the plane-normal axis is checked separately and cannot loosen in-plane agreement. Circular transfer then uses the certified native face area/centroid and the actual rounded OCCT revolution axis to reproduce the analytic target inside that same representability envelope before allocating the result; this checks construction drift without relying on cancellation-prone native solid-volume integration. A profile mismatch raises the runtime-frozen OcctProfileMassPropertyError with a stable reason and numeric diagnostics.
  • OCCT pipe-shell transfer is used for polyline and composite sweeps and rejects profile or spine edges at or below the conservative 1e-4 mm transfer floor before allocating native sweep topology. Composite arcs also require all three authored point-pair separations above that floor and the 3e-8 three-point conditioning floor. Exact segment type, endpoints, tangents, length, wire cardinality/length, result validity, body purity, and segment-to-profile face correspondence are checked before ownership transfers. The stock binding does not expose PipeShell’s coarse angular tolerance, so the shared preflight admits a stock major-arc composite only when it needs neither the multi-arc nor eccentric-profile refinement. Direct calls classify against the requested context tolerance, matching document evaluation rather than silently substituting the adapter’s modeling tolerance. ABI 0.3 introduced explicit linear/boundary tolerances and a 1e-9 angular tolerance, rejection of measured surface error above the selected linear bound, and certification of major multi-arc/eccentric-profile results; ABI 0.6 retains that PipeShell contract. All composite volumes must agree with the compensated transported-centroid oracle; strong term cancellation or an unsupported miter fails closed.
  • Measurement precision follows the representation. OCCT integrates the B-Rep natively, while Manifold integrates its emitted closed polyhedron; assembly aggregation uses those occurrence properties. Cross-backend comparisons therefore use modeling or meshing tolerances, not bitwise equality.
  • Transform operations are applied in list order.

Backend conformance

Every geometry kernel should run the same corpus for:
  • primitives and transforms;
  • nested profile holes;
  • extrude, partial/full revolve, and bounded ruled solid lofts;
  • explicit open polyline/circular-arc/composite paths and bounded exact solid sweeps;
  • overlapping and empty booleans, authored target/tool order, ordered union/intersection versus cut-all subtraction, and partial-backend compatibility;
  • bounds, volume, surface area, center of mass, centroidal inertia, and topological class;
  • translated, rotated, reflected, nonuniformly scaled, and multi-occurrence mass-property aggregation, including parallel-axis behavior;
  • nested and suppressed deterministic BOM quantities, part-node grouping, affine occurrence mass, and partial-mass warnings;
  • parameter extremes and degenerate geometry;
  • cancellation and resource teardown;
  • face/edge/vertex topology set semantics, cardinality, face↔edge and edge↔vertex adjacency reciprocity, vertex position queries, and history loss;
  • protocol-v2 face/edge/vertex persistence, byte- and behavior-frozen protocol-v1 face/edge compatibility profiles, exact fingerprint gating, and missing/ambiguous coincident-vertex behavior;
  • primitive, extrusion, revolution, bounded ruled-loft, and bounded-sweep role inventories; exact sweep counts C*S, C, C, and V*S; direct-profile-only sweep sources; unnamed path-joint fragments and circular seams; partial/full revolution caps; axis-contained boundary collapse; negative/symmetric sweeps; fail-closed loft and sweep-graph correspondence; and provenance-preserving transforms;
  • selector-driven features without enumeration-order dependence;
  • exact shell openings, inward/outward direction, tolerance validation, and collapse rejection;
  • exact whole-solid offsets, fixed round joins, direction/volume monotonicity, strict body cardinality, and collapse rejection;
  • atomic semantic-face draft, signed-angle bounds, independent pull/neutral-plane vectors, exact indexed evolution, and transactional ownership;
  • owned exact multi-input union/subtraction/intersection, complete face/edge/vertex PRESERVED/MODIFIED/GENERATED/DELETED/residual CREATED coverage, identity-only public lineage, isolated operand copies with byte-stable arena inputs, bounded record materialization, empty-result graphs, capability fallback, and transactional rollback;
  • owned exact constant-radius fillet/equal-distance chamfer, canonical tangent-contour seeds, complete face/edge/vertex evolution, strict generated edge→face blend/bevel class roles, residual-created and generated-edge non-naming, class-level ambiguity, an independent byte-stable operand copy, a separate bounded record budget, optional capability fallback, and transactional rollback;
  • owned exact face-selected shell/whole-solid offset, canonical opening echo, generated-only replacement reconciliation, selected-opening modified-rim semantics, complete face/edge/vertex evolution, a deep byte-stable operand copy, an independent bounded record budget, optional capability fallback, and transactional rollback;
  • ruled loft profile compatibility, monotonic section order, strict output topology cardinality, and transactional ownership;
  • polyline, circular-arc, and composite sweep simplicity/clearance, exact profile moments, geometry-derived additive refinement preflight, tolerance boundaries, frame and transition semantics, strict one-body validation, and transactional ownership;
  • Node and browser initialization.
Results are compared by tolerances and topological expectations, never by triangle ordering or exported-file bytes.