# T2DPLM OCF v1.0 — Implementation Guide

**Document type:** Implementation Guide (supersedes *T2DPLM CAD Connector Generation Spec*)
**Format version:** OCF 1.0
**Document revision:** 2 (2026-09-16)
**Scope:** Vendor-neutral. Applies to any CAD or design tool.
**Normative reference:** *T2DPLM Open Connector Format (OCF) v1.0 — Format Specification* ("the Format Specification")
**Reference checker:** *T2DPLM OCF v1.0 Validator*

Hand this document, together with the Format Specification, to a code-generation assistant on your own licensed CAD workstation. Between them they define exactly what a thin "data dumper" producer must do. Neither document contains vendor API code, nor any reference to a specific CAD vendor's SDK internals. You build the producer yourself, on your own machine, using your own tool's official API.

The Format Specification is the contract. This guide is procedure. Where they appear to disagree, the Format Specification wins.

---

## Table of Contents

1. Purpose and audience
2. Instructions for the code-generation assistant
3. Scope of the deliverable
4. Capability map — what the source tool must expose
5. Identity in practice (Rule A)
6. Noise control in practice (Rule B)
7. Traversal and occurrence semantics
8. Fault isolation and logging
9. Configuration
10. Packaging and installation
11. Acceptance test procedures
12. The disclosure document you must ship
13. Licensing and vendor API terms

---

## 1. Purpose and audience

This guide is for whoever builds a **producer** — the plugin, add-in, macro, script or watcher that observes a CAD or design tool and writes OCF files. It is written to be read either by a human engineer or by a code-generation assistant working on a licensed workstation.

It is deliberately tool-agnostic. It never assumes the source tool stores each part in its own file, never assumes it has part numbers, configurations or suppression, and never assumes it exposes a persistent identifier. Section 4 turns each of those into a capability question with a defined answer either way.

## 2. Instructions for the code-generation assistant

Before writing any code, ask the user exactly one question and wait for the answer:

> "Which CAD or design tool is this producer for, and which version?"

Do not ask any other clarifying question before this one. Once the user names the tool:

1. **Use official APIs only.** Implement against that tool's official, publicly documented API or SDK. Unofficial, reverse-engineered or undocumented interfaces are NOT ALLOWED.
2. **Produce the capability map first.** Before any code, fill in the table in Section 4 for the named tool and show it to the user. Every row must say which API surface satisfies it, or that the tool does not offer it and which fallback you will use.
3. **The contract does not bend.** Whatever the tool is, the output must satisfy the Format Specification exactly: the same JSON shape, the same field names, the same types, the same two hard rules.
4. **Flag, never substitute silently.** If the tool has no supported way to obtain a stable persistent identity per component instance (Format Specification §6), say so explicitly before writing code and propose the fallback in §6.3 of that document. Never quietly downgrade to a weaker identity scheme.
5. **Stop rather than half-comply.** If any requirement cannot be met with the named tool's API, stop and state which requirement and why, rather than producing a producer that silently violates it.
6. **Write only the producer.** Something that hooks a save event (or, where the tool does not allow that, is invoked by a custom key combination — Section 4, row 1), walks the design tree, and writes the JSON file. No UI beyond what the tool requires to install or enable the add-in. No network calls. No telemetry. No other features.
7. **No invented fields.** Do not add fields beyond the schema. Do not omit required ones. There is no extension mechanism in v1.0.
8. **Finish with the tests.** Run every acceptance test in Section 11, including the validator, and report the results.

## 3. Scope of the deliverable

What you build:

- the producer itself (plugin / add-in / macro / watcher, whatever the tool supports);
- an external configuration file (Section 9);
- a local log file (Section 8);
- a short disclosure document (Section 12);
- the recorded results of the Section 11 acceptance tests.

What T2DPLM ships you: the Format Specification, this guide, and the validator. No source code, no compiled binary, no vendor API bindings. The producer is built, compiled and run entirely on your own licensed software. T2DPLM never receives, distributes or touches code that calls a CAD vendor's API.

## 4. Capability map — what the source tool must expose

Fill this in for the named tool before writing code. "Required" means the producer cannot be built without it; "Resolved" means the Format Specification defines what to emit when the tool lacks it.

| # | Capability | Status | If the tool lacks it |
|---|---|---|---|
| 1 | A hook that fires on save (or a reliable equivalent, e.g. a document-changed event or a watched-file trigger) | Required, with defined fallback | If the tool does not let a plugin hook the save event, do not stop: register a custom key combination (or the nearest equivalent the tool supports, such as a menu or toolbar command bound to a shortcut) that runs the same export on demand, and tell the user to invoke it after saving. The output requirements do not change: one file per invocation, the same `meta.assemblyId` every time, and every other rule of the Format Specification. Disclose this in the disclosure document (Section 12). |
| 2 | Enumeration of every component instance at every depth | Required | Stop. Partial traversal is NOT ALLOWED (Format Specification §8.2). |
| 3 | Parent/child relationship per instance | Required | Stop. `parentId` cannot be synthesized. |
| 4 | A persistent, stable reference per component instance | Required, with defined fallback | Use the §6.3 fallback ladder and disclose it (Section 5 below). |
| 5 | Position and rotation per instance | Required | Stop, unless the tool genuinely has no placement concept — in which case get written agreement before emitting zeros everywhere. |
| 6 | Per-component user-defined properties | Resolved | Emit `{}`. |
| 7 | A part number or designation | Resolved | Fall back per Format Specification §5.7.2, ending at `""`. |
| 8 | Configurations / variants | Resolved | Emit `""`. |
| 9 | Suppression state | Resolved | Emit `false`. |
| 10 | Virtual / in-context / non-file-backed components | Resolved | Emit `false`. |
| 11 | Per-component file name | Resolved | Fall back per Format Specification §5.7.1 (document file name, then `""`). |
| 12 | A stable identifier for the whole design | Required | Derive one deterministically (Section 5.3) and disclose how. |
| 13 | Documented length units and rotation convention | Required | Determine them empirically, document them, and hold them constant (Format Specification §5.7.5). |

Any row marked "Resolved" that you fill with a substitute value must appear in the disclosure document (Section 12).

## 5. Identity in practice (Rule A)

**5.1 The ladder.** Take the highest rung the tool supports:

1. a persistent id / stable GUID / occurrence token that the tool guarantees survives save, reload, rename and reorder;
2. a stable occurrence path — the chain of parent references from root to instance, built from per-instance stable names;
3. the fallback of Format Specification §6.3: component file name plus position in the tree.

Hash the chosen input with SHA-256 and emit the hex digest as `id`.

**5.2 What must never enter the hash.** Absolute or temporary paths, `sourcePath`, the machine or user name, the session, the save timestamp, the tool version, a raw array index, or a display-order number. Each of these changes without the design changing, which turns every save into a false "everything changed".

**5.3 The assembly id.** `meta.assemblyId` must survive ordinary saves *and* the design being moved or renamed on disk, and must be filename-safe (Format Specification §4.2.1). If the tool exposes a document GUID, use it. If not, generate one once, store it inside the document as a custom document-level property if the tool permits, and only otherwise fall back to a hash of a stable document identifier — disclosing that a move or rename will then start a new identity.

**5.4 Prove it before shipping.** Rung 1 and rung 2 both look stable until tested. Run Section 11 tests 1, 6 and 7 before you believe either.

## 6. Noise control in practice (Rule B)

Rule B failures are the most common reason a producer passes the validator and still makes T2DPLM report a change on every save. The usual causes, in order of frequency:

1. **Dumping every property the tool exposes.** Tool-internal bookkeeping — element-map or schema version stamps, touched/dirty flags, link and attachment state, recompute markers, cache keys — belongs nowhere inside `components` (Format Specification §7.5). Start with an allow-list of the properties the customer actually maintains; widen it on request.
2. **A version stamp that tracks the CAD tool.** If a property's value encodes the tool's own internal format or version, it will change on the day the user upgrades and make the entire design look modified. Exclude it.
3. **Paths inside components.** Any absolute path, temp path or machine name inside a component entry is a violation even if it looks stable on one workstation.
4. **Non-deterministic serialization.** Unstable component ordering, unstable key ordering, or locale-dependent number formatting all break Test 1 while every value is technically "correct". Fix ordering once, sort property keys, and format numbers with an invariant culture (Format Specification §7.6).
5. **Floating-point churn.** If the tool returns placement values that jitter in the last digits between saves of an untouched design, round to a fixed, documented precision — the same precision every time — rather than emitting raw jitter.

## 7. Traversal and occurrence semantics

- Walk the full tree, every level, no depth cap, no node-count cap (Format Specification §8.2).
- One entry per **occurrence**, not per unique part: three instances of the same bracket are three entries with three distinct `id` values and one shared `partNumber`. Quantity rollup is the consumer's job.
- Include suppressed and virtual components, flagged rather than omitted (§5.5). An entry disappearing means "deleted" to the consumer, and nothing else.
- More than one root is fine if the tool exposes several top-level items (§5.4.3). Do not fabricate a synthetic root to force a single tree.
- Never modify the design while walking it (§8.5). If reading a property forces a recompute or marks the document dirty, find another way or exclude that property.

## 8. Fault isolation and logging

- Wrap every operation. Any failure is logged and swallowed; the user's save completes normally either way (Format Specification §8.1).
- The log lives next to the producer, never in the watched folder (§4.6).
- Log enough to diagnose: timestamp, design identifier, what failed, exception detail. Do not log design geometry or property values beyond what is needed to identify the failure.
- Decide, implement and document one partial-failure behavior (§8.7): emit the component with empty values for what could not be read, or abandon the whole file. Never drop a component silently.
- Write atomically — temp file, then rename into place (§4.5).

## 9. Configuration

Read from an external plain file next to the binary or in the platform's standard config location. At minimum:

- watched folder path;
- the property name used as the source for `partNumber`;
- the property inclusion rule (allow-list, deny-list, or both).

Useful additions: rounding precision for placement values, log path, log verbosity.

None of these may be hard-coded (§9.2). Missing or partly invalid configuration means documented defaults plus a log line — never a crash of the host application (§9.3).

## 10. Packaging and installation

Tool-generic guidance, since mechanisms differ:

- Ship whatever the tool's supported add-in mechanism is, installed the way the vendor documents. Do not patch, inject into, or modify the tool's own files.
- Keep the producer's version string in `meta.toolVersion` and bump it on every release — it is the first thing anyone debugging an ingestion problem looks at.
- Changing identity scheme, units, rotation convention, rounding precision or property inclusion is a **breaking** change: it re-baselines every component in T2DPLM. Treat it as a coordinated release, note it in the disclosure document, and tell the consumer's owner before shipping it.

## 11. Acceptance test procedures

These are the Format Specification §10 tests, as a procedure. Record the result of each. A producer is not conformant until all eight pass.

**Test 1 — Stable ID.**
Open a real design. Save. Copy the output file aside. Save again with no edits. Diff the two files. They must differ only in `meta.savedAt`. Then repeat the pair after closing and reopening the tool, and again after a tool upgrade if one is available — both are where identity schemes and version stamps usually fail.

**Test 2 — Completeness.**
Against a design that includes nesting at least three levels deep, a repeated part, a suppressed component, a virtual/in-context component (if the tool has one), and components both with and without user properties: check every entry's position, rotation, properties, `parentId` and boolean flags against what the tool itself shows. Confirm the component count matches the occurrence count in the tool's tree.

**Test 3 — Encoding.**
Inspect the raw bytes. The file must be UTF-8 and must not begin with a BOM (`EF BB BF`), nor with any UTF-16/UTF-32 BOM.

**Test 4 — Noise.**
Search the `components` array for timestamps, absolute paths, temp paths, machine or user names, and tool-internal property keys. There must be none. Then confirm behaviorally: the unchanged-save diff from Test 1 is the real proof.

**Test 5 — Fault isolation.**
Make the watched folder unwritable (or delete it) and save. The host tool's save must complete normally, the user must not see a crash or a modal error from the producer, and the failure must appear in the log.

**Test 6 — Move.**
Move exactly one component and save. Diff against the previous file: only that component's `transform` may change. Every other component's `id` and every other value must be byte-identical.

**Test 7 — Delete.**
Delete exactly one component and save. Diff: that entry disappears; nothing else changes. If the deleted component had children, confirm the resulting file has no `parentId` pointing at a missing id.

**Test 8 — Structural validation.**
Run the reference validator over the output:

```bash
python3 ocf_validator.py path/to/asm_<assemblyId>.json
```

Exit code `0` is required. Use `--no-filename-check` only when validating content that has already been renamed in transit. Run it over the Test 2 design, not a trivial one, so nesting, repeated occurrences, empty-valued fields and both booleans are exercised.

**What the validator does not prove.** It checks one file's shape. Tests 1, 4, 6 and 7 are about behavior across saves and cannot be automated away — a producer that stamps a fresh timestamp into every component passes the validator every time.

## 12. The disclosure document you must ship

One page alongside the producer, stating:

- source tool and version range tested against;
- how the export is triggered: the save event, or a custom key combination (state which key combination);
- producer version;
- which rung of the identity ladder (Section 5.1) is used, and — if it is the §6.3 fallback — an explicit statement that identity may break when a component is renamed or reordered;
- how `meta.assemblyId` is derived and what breaks it;
- length units and rotation convention and order (Format Specification §5.7.5);
- rounding precision, if any;
- which capability-map rows (Section 4) were filled with substitute values, and what the substitute is;
- the property inclusion rule as shipped;
- the partial-failure behavior chosen (§8.7);
- the date and result of each Section 11 test.

The consumer cannot interpret the data correctly without this, and it is the first thing to check when a diff looks wrong.

## 13. Licensing and vendor API terms

This is a technical specification, not legal advice. Anyone building and running a producer against their own CAD tool's API should confirm that this use is consistent with that vendor's license and API terms of use. Different vendors have different terms; neither this guide nor the Format Specification resolves that question for any specific vendor, and neither should be treated as doing so.

---

*End of T2DPLM OCF v1.0 — Implementation Guide, Revision 2.*

---

## License and disclaimer

Copyright (c) 2026 Thought2Design Systems. This document is released under the **MIT License**; the full text is in the `LICENSE` file distributed with it and at <https://www.thought2design.com/ocf/LICENSE>.

- **No warranty.** This document is provided "AS IS", without warranty of any kind. Thought2Design Systems is not liable for any claim, damages or other liability arising from its use, or from any software built with its help.
- **Not legal advice.** Nothing here is legal advice. You are solely responsible for confirming that you legally own or are licensed to use your CAD tool, and that writing and running a producer against its API is permitted by that vendor's license and API terms of use.
- **No vendor code, no affiliation.** Thought2Design Systems supplies no CAD-vendor SDK, API binding or code that calls a vendor API, and does not receive or distribute producers you build. Names of CAD tools and vendors are trademarks of their respective owners; mentioning them implies no affiliation, endorsement or sponsorship.
- **Your producer is yours.** Thought2Design Systems claims no ownership of, and takes no responsibility for, a producer you create. Its licensing, and your compliance with the vendor's terms, are your responsibility.
