Appearance
File Format (.tfp / .tfa direction)
TrueForm’s part file type is a .tfp container that stores the authoritative IR plus optional preview artifacts (mesh + isometric thumbnail). The IR is the source of truth. Preview artifacts are caches and can be regenerated.
Step 1 contract direction:
- Part connectors are stored with part intent (
.tfp). - Assembly intent is stored in a separate assembly container/file (
.tfadraft).
Container Types
.tfp(part container): implemented..tfa(assembly container): draft target only; schema and tooling are not yet a complete shipped contract.
Container Layout
.tfp is a zip container with fixed top-level entries:
my_part.tfp
manifest.json
document.json
artifacts/
part.mesh.json
preview.pngDraft .tfa layout:
my_assembly.tfa
manifest.json
document.json
artifacts/
assembly.preview.jsondocument.json (Authoritative IR)
The document is the canonical, kernel-agnostic intent model.
Part document (.tfp) example:
{
"schema": "trueform.ir.v1",
"document": {
"id": "doc-1",
"parts": [ /* IntentPart[] */ ],
"assemblies": [],
"capabilities": {},
"constraints": [],
"assertions": [],
"context": {
"units": "mm",
"kernel": { "name": "ocjs", "version": "X.Y.Z" },
"tolerance": { "linear": 1e-6, "angular": 1e-6 }
}
}
}Assembly document (.tfa) draft example:
This is a target-shape example, not a statement that the current shipped IntentDocument and container helpers fully support .tfa assembly documents today.
{
"schema": "trueform.ir.v1",
"document": {
"id": "asm-doc-1",
"imports": [
{
"id": "part:plate",
"path": "parts/plate.tfp",
"partId": "plate",
"documentHash": "sha256:..."
},
{
"id": "part:peg",
"path": "parts/peg.tfp",
"partId": "peg",
"documentHash": "sha256:..."
}
],
"parts": [],
"assemblies": [ /* IntentAssembly[] */ ],
"capabilities": {},
"constraints": [],
"assertions": [],
"context": {
"units": "mm",
"kernel": { "name": "ocjs", "version": "X.Y.Z" },
"tolerance": { "linear": 1e-6, "angular": 1e-6 }
}
}
}Assembly -> Part References (Draft Direction)
To connect assembly documents to part documents, use document.imports in assembly files:
{
"id": "part:plate",
"path": "parts/plate.tfp",
"partId": "plate",
"documentHash": "sha256:..."
}Field meaning:
id: local import key within the assembly document.path: relative location of the part container (.tfp).partId: target part id inside the imported part document.documentHash: optional integrity lock for reproducible builds.
Assembly instance resolution rule (draft):
AssemblyInstance.partrefers toimports[].id, not a free-form global id.AssemblyRef = { instance, connector }stays unchanged.- Connectors remain defined in the referenced part document.
Notes:
- This is a Step 1 contract direction; schema/tooling implementation is pending.
- Existing inline/bundle workflows are still supported during migration.
Bundle Compatibility And Migration (Step 1)
Legacy bundle format (single document with both parts and assemblies) remains the current practical compatibility shape while split assembly containers are still draft-only.
Target read compatibility once split assembly containers land:
- Loaders should accept legacy bundles and split formats.
- For legacy bundles, loaders synthesize virtual imports:
id = "part:<part.id>"partId = <part.id>pathomitted (in-document source)
Target write behavior once split assembly containers land:
- Default write mode should be split:
- part documents in
.tfp - assembly documents in
.tfawithdocument.imports
- part documents in
- Legacy bundle write mode should remain compatibility-only and explicit.
Deprecation direction:
- Transition: read both formats; write split by default.
- Next minor: warn on legacy bundle writes.
- Next major: remove legacy bundle writes; retain legacy bundle reads.
Notes:
- The IR stores no kernel history or B-Rep.
- Feature order in arrays is preserved.
- In v1 direction, part connectors are defined in part documents.
- In v1 direction, assembly intent is serialized in separate assembly documents.
- Current implementation note:
src/tf/container.tsimplements the generic container read/write path for current document payloads; do not assume complete.tfaread/write behavior until the v1 contract explicitly promotes it.
manifest.json (Container Metadata)
The manifest declares schema versions, document hashes, and optional preview artifacts.
{
"schema": "trueform.container.v1",
"createdAt": "2026-02-07T00:00:00Z",
"document": {
"path": "document.json",
"schema": "trueform.ir.v1",
"hash": "sha256:...",
"bytes": 12345
},
"artifacts": [
{
"type": "mesh",
"path": "artifacts/part.mesh.json",
"hash": "sha256:...",
"bytes": 23456
},
{
"type": "preview",
"path": "artifacts/preview.png",
"hash": "sha256:...",
"bytes": 1024
}
]
}Notes:
- Hashes are SHA-256 over canonical JSON.
- Artifacts are optional and non-authoritative.
meshartifacts are intended for lightweight previews (low or medium resolution).previewartifacts are isometric thumbnails.- Keep export-quality meshes and other artifacts as sidecar files (e.g.
*.mesh.json,*.iso.png,*.pmi.json).
Canonical JSON and Hashing
When hashing document.json:
- Object keys are sorted lexicographically.
- Array order is preserved.
undefinedvalues are omitted.
This ensures stable hashes for caching and diffing.
File Handling
Open:
- Unzip the
.tfpcontainer, or a.tfacontainer once split assembly containers are explicitly promoted. - Parse
manifest.jsonanddocument.json. - Validate schema versions.
- Hash
document.jsonand compare to manifest. - Load artifacts if present and hashes match.
Save:
- Serialize the IR to
document.json. - Compute document hash and update
manifest.json. - Optionally include preview mesh + thumbnail artifacts and hashes.
- Zip into a
.tfp(part) container today, or a.tfa(assembly) container once split assembly storage is explicitly promoted. - Optionally regenerate sidecar artifacts.
Minimal Example
The repository includes a minimal example container:
tools/tf/examples/minimal.tfp
It is generated by:
node tools/tf/build_minimal_example.mjsThe implementation lives in:
src/tf/container.ts