# .kc File Format Specification **Version:** 1.0-draft **Date:** February 2026 **Status:** Specification — Not Started The `.kc` format is Kindred Create's native file format. It is a strict superset of FreeCAD's `.fcstd` format — every `.kc` file is a valid `.fcstd` file with an additional `silo/` directory containing platform metadata. This design preserves full interoperability with vanilla FreeCAD while enabling Silo integration, version control, compute job attachment, and engineering workflow features. --- ## 1. Design Principles **Superset, not fork.** A `.kc` file can be renamed to `.fcstd` and opened in unmodified FreeCAD. FreeCAD ignores unknown entries in the ZIP archive, so the `silo/` directory is invisible to the base document loader. This means upstream FreeCAD merges never break the format. **Silo metadata is a snapshot.** The `silo/` directory carries a point-in-time copy of server-side state. The Silo server is authoritative. When a `.kc` file is opened while connected to Silo, the client checks for newer revisions. Offline edits are reconciled on reconnect by comparing revision hashes in `silo/manifest.json`. **Incremental adoption.** Not every `silo/` file needs to be populated. The format grows as Silo modules ship. A minimal `.kc` file only requires `silo/manifest.json`. All other entries are optional and introduced by their respective modules. **Round-trip safety.** FreeCAD's save routine writes only the entries it knows about (`Document.xml`, `GuiDocument.xml`, `.brp` files, `thumbnails/`). It does not delete unknown entries from the ZIP. The `silo/` directory survives FreeCAD save cycles without corruption. --- ## 2. Archive Structure A `.kc` file is a ZIP archive. Its contents are organized into two zones: the standard FreeCAD zone (inherited as-is) and the Kindred zone (`silo/`). ``` part.kc (ZIP archive) │ │ ── FreeCAD Standard Zone ────────────────────────── │ ├── Document.xml # Feature tree, parameters, object definitions ├── GuiDocument.xml # Visual state (colors, visibility, camera) ├── *.brp # BREP geometry cache (one per shape) ├── thumbnails/ │ └── Thumbnail.png # FreeCAD-generated preview │ │ ── Kindred Zone ─────────────────────────────────── │ └── silo/ ├── manifest.json # Identity, origin, revision, schema version ├── metadata.json # Custom schema fields, tags, lifecycle state ├── history.json # Local revision log (lightweight) ├── approvals.json # ECO / approval state snapshot ├── dependencies.json # Assembly link references by Silo UUID ├── macros/ # Embedded macro references or inline scripts ├── inspection/ # GD&T annotations, tolerance data, CMM linkage ├── jobs/ # Compute job YAML definitions │ └── default.yaml └── thumbnails/ # Silo-generated renderings (separate from FreeCAD's) ``` --- ## 3. FreeCAD Standard Zone These entries are identical to a standard `.fcstd` file. Kindred Create does not modify their structure or semantics. | Entry | Description | |-------|-------------| | `Document.xml` | Serialized feature tree. Contains all object definitions, parametric properties, sketch geometry, constraints, and inter-object references. This is the canonical representation of the model. | | `GuiDocument.xml` | View provider state: object colors, visibility flags, camera position, display modes. Not required for geometry reconstruction. | | `*.brp` | OpenCASCADE BREP files. One per shape object. These are a derived cache — they can be regenerated from `Document.xml` by recomputing the feature tree. | | `thumbnails/Thumbnail.png` | FreeCAD's built-in thumbnail, generated on save. 128×128 PNG by default. | The BREP files are binary and not diffable. `Document.xml` is XML and structurally diffable (see Silo's Intelligent FCStd Diffing module). `GuiDocument.xml` is XML but rarely relevant to version control. --- ## 4. Kindred Zone (`silo/`) All Kindred-specific data lives under `silo/`. Each entry is described below with its schema, lifecycle, and owning module. ### 4.1 `silo/manifest.json` — Required The only mandatory `silo/` entry. Identifies this file within the Silo ecosystem. ```json { "kc_version": "1.0", "silo_instance": "https://silo.example.com", "part_uuid": "550e8400-e29b-41d4-a716-446655440000", "revision_hash": "a1b2c3d4e5f6", "created_at": "2026-02-13T19:00:00Z", "modified_at": "2026-02-13T20:30:00Z", "created_by": "joseph" } ``` | Field | Type | Description | |-------|------|-------------| | `kc_version` | string | `.kc` schema version. Used for forward-compatible migrations. | | `silo_instance` | string | URL of the originating Silo server. Null for offline-created files. | | `part_uuid` | UUID | Globally unique identifier assigned by Silo. Survives renames and moves. | | `revision_hash` | string | Hash of the last committed revision. Used for offline reconciliation. | | `created_at` | ISO 8601 | Timestamp of initial `.kc` creation. | | `modified_at` | ISO 8601 | Timestamp of last save. | | `created_by` | string | Username of the creating user. | ### 4.2 `silo/metadata.json` — Optional Custom schema field values, lifecycle state, and tags. Driven by Silo's user-customizable schema engine. ```json { "schema": "mechanical-part-v2", "lifecycle": "released", "tags": ["structural", "aluminum"], "fields": { "category": "bracket", "material": "6061-T6", "finish": "anodized", "weight_kg": 0.34, "project": "PRJ-042" } } ``` The `schema` field references a schema definition stored on the Silo server. Field names, types, and validation rules are defined by that schema. The client renders form fields dynamically based on the schema descriptor fetched from `GET /api/schemas/{schema_name}/form`. ### 4.3 `silo/history.json` — Optional Lightweight local revision log. The full history lives server-side; this is a portable subset for offline reference. ```json { "revisions": [ { "revision": 3, "hash": "a1b2c3d4e5f6", "author": "joseph", "timestamp": "2026-02-13T20:30:00Z", "comment": "Added fillet to mounting holes", "status": "released" }, { "revision": 2, "hash": "f6e5d4c3b2a1", "author": "joseph", "timestamp": "2026-02-12T14:00:00Z", "comment": "Initial geometry", "status": "draft" } ] } ``` Revisions are listed newest-first. This file is append-only during local editing and reconciled with the server on commit. ### 4.4 `silo/approvals.json` — Optional Snapshot of engineering change order (ECO) and approval workflow state. Server-authoritative — this is a read cache for offline display. ```json { "eco": "ECO-2026-047", "state": "pending_review", "approvers": [ { "user": "jane.smith", "role": "design_lead", "status": "approved", "timestamp": "2026-02-13T16:00:00Z" }, { "user": "bob.jones", "role": "quality", "status": "pending", "timestamp": null } ] } ``` ### 4.5 `silo/dependencies.json` — Optional Assembly link references stored by Silo UUID rather than filesystem path. This decouples assembly structure from local file layout. ```json { "links": [ { "uuid": "660e8400-e29b-41d4-a716-446655440001", "label": "Base Plate", "part_number": "KC-BRK-0042", "revision": 2, "quantity": 1, "relationship": "component" }, { "uuid": "770e8400-e29b-41d4-a716-446655440002", "label": "M6 Socket Head Cap Screw", "part_number": "KC-HDW-0108", "revision": 1, "quantity": 4, "relationship": "component" } ] } ``` When opening an assembly `.kc`, the Silo workbench resolves UUIDs to local file paths. Missing dependencies trigger a download prompt if the Silo connection is active. ### 4.6 `silo/macros/` — Optional Embedded macro references or inline Python scripts bound to this part. Files in this directory are registered with Create's macro system on document open. ``` silo/macros/ ├── on_save.py # Hook: runs before save ├── generate_drawing.py # Utility: creates a drawing from this part └── manifest.json # Macro metadata and execution triggers ``` Macro manifest: ```json { "macros": [ { "file": "on_save.py", "trigger": "pre_save", "description": "Validates wall thickness before save" }, { "file": "generate_drawing.py", "trigger": "manual", "description": "Generate 3-view drawing with BOM table" } ] } ``` ### 4.7 `silo/inspection/` — Optional GD&T annotations, tolerance data, and CMM device linkage metadata. Structure TBD pending Tier 5 Quality module specification. Provisional layout: ``` silo/inspection/ ├── gdt_annotations.json # GD&T callouts linked to face/edge references ├── tolerance_stack.json # Statistical tolerance analysis results └── cmm_program.json # CMM program reference and measurement linkage ``` ### 4.8 `silo/jobs/` — Optional Compute job YAML definitions attached to this part. These feed into Silo's job queue infrastructure (Tier 3). A part can carry multiple job definitions for different compute workloads. ```yaml # silo/jobs/default.yaml kind: silo/job version: 1 metadata: part: bracket-assembly-v3 trigger: on-commit spec: tasks: - name: constraint-check runner: labels: [cpu, ondsel-solver] image: kindred/solver-runner:latest timeout: 300s - name: appearance-render runner: labels: [gpu, render] image: kindred/render-runner:latest depends_on: [constraint-check] resources: vram: 8Gi ``` Job YAMLs use the runner label system described in the Silo Job Queue specification. The `trigger` field determines when the job executes: `on-commit` (every Silo commit), `on-release` (lifecycle transition to released), or `manual` (user-initiated). ### 4.9 `silo/thumbnails/` — Optional Silo-generated renderings, separate from FreeCAD's built-in `thumbnails/Thumbnail.png`. These are produced by the Headless Create module (Tier 1) and may include multiple views or higher-resolution images. ``` silo/thumbnails/ ├── isometric.png # Default isometric view ├── front.png # Front orthographic ├── top.png # Top orthographic └── exploded.png # Exploded assembly view (assemblies only) ``` Thumbnail generation policy (single canonical vs. multi-view) is configurable at the Silo instance level. --- ## 5. Interoperability ### 5.1 FCStd → .kc (Import / Promotion) When a user opens an `.fcstd` file in Kindred Create, it loads normally through FreeCAD's standard document loader. The file can be "promoted" to `.kc` through either of two paths: **Manual promotion:** User selects File → Save As → `.kc`. Create generates `silo/manifest.json` with a new UUID and prompts for schema field selection if connected to Silo. **Silo-triggered promotion:** User commits an `.fcstd` to Silo via the Silo workbench. Silo assigns a UUID, generates the `silo/` directory with defaults, and returns a `.kc` to the client. Subsequent saves default to `.kc`. In both cases, no data in the FreeCAD standard zone is modified. The promotion is purely additive. ### 5.2 .kc → FCStd (Export / Demotion) File → Export As → `.fcstd` strips the entire `silo/` directory. The resulting file is a valid `.fcstd` with no Kindred-specific content. This is the recommended path for sharing files with vanilla FreeCAD users. ### 5.3 Vanilla FreeCAD Behavior If a `.kc` file is renamed to `.fcstd` and opened in vanilla FreeCAD: - The document loads normally. `Document.xml`, `GuiDocument.xml`, and BREP files are read as expected. - The `silo/` directory is ignored (unknown ZIP entries are silently skipped). - On save, FreeCAD writes its standard entries. The `silo/` directory survives the save because FreeCAD does not delete unknown ZIP entries. - **Caveat:** If FreeCAD rewrites the ZIP from scratch (rather than updating in-place), the `silo/` directory may be lost. Testing confirms that FreeCAD 1.0+ preserves unknown entries, but this behavior should be monitored across upstream releases. --- ## 6. Client Implementation Layers Implementation in the Create client is organized into four layers, each independently deliverable. ### Layer 1: Format Registration (C++) Register `.kc` as a recognized file type in FreeCAD's application framework. **Scope:** - `src/App/Application.cpp` — register `.kc` extension alongside `.fcstd` in the file type map. Both extensions route to the same `openDocument()` path since the ZIP internals are structurally identical. - `src/Gui/FileDialog.cpp` — add `.kc` to open/save/export dialogs. New documents default to `.kc`. "Save As" offers both `.kc` and `.fcstd`. - `src/App/Document.cpp` — on save-as-`.fcstd`, strip the `silo/` directory from the ZIP. On save-as-`.kc`, ensure the `silo/` directory exists (create `manifest.json` with defaults if missing). - Platform integration — `.kc` MIME type registration, file association on Linux (`.desktop` file / XDG), macOS (`Info.plist`), and Windows (registry / NSIS installer). **Risk:** Low. FreeCAD already ignores unknown ZIP entries. This layer is purely file dialog and post-save ZIP manipulation. **Acceptance criteria:** - `.kc` files open in Create without errors. - "Save As .fcstd" produces a valid `.fcstd` with no `silo/` directory. - "Save As .kc" produces a ZIP with at minimum `silo/manifest.json`. - Double-clicking a `.kc` file on all platforms opens Create. ### Layer 2: Silo Metadata Layer (Python) A `KindredDocument` class in `src/Mod/Create/` that wraps the loaded `App::Document` and manages the `silo/` directory contents. **Scope:** - `src/Mod/Create/KindredDocument.py` (new) — load/save logic for all `silo/` entries. - `src/Mod/Create/InitGui.py` — connect to `App::Document` signals (`signalSaveDocument`, `signalRestoreDocument`) to trigger metadata load/save. **Behavior by operation:** | Operation | Action | |-----------|--------| | Open `.kc` | Parse all `silo/` entries. Expose metadata as properties on the document. | | Open `.fcstd` | No-op — no `silo/` directory present. `KindredDocument` is inactive. | | Save `.kc` | Serialize current metadata into `silo/` before FreeCAD writes the ZIP. | | Save `.fcstd` | Skip metadata serialization. Strip `silo/` if present. | | Promote `.fcstd` → `.kc` | Generate `silo/manifest.json` with new UUID. Prompt for schema fields. | **Behavior by `silo/` entry:** | Entry | On open | On save | On promote | |-------|---------|---------|------------| | `manifest.json` | Read instance origin, UUID, revision, schema version | Update `modified_at` and `revision_hash` | Generate with new UUID | | `metadata.json` | Load schema fields, tags, lifecycle | Serialize current state | Generate with defaults from selected schema | | `history.json` | Load local revision log | Append entry if dirty | Initialize empty | | `approvals.json` | Load ECO/approval snapshot | Pass-through (server authoritative) | Initialize empty | | `dependencies.json` | Resolve assembly links by UUID | Update from current assembly link objects | Generate from assembly link scan | | `macros/` | Register embedded macros | Serialize bound macros | Empty directory | | `inspection/` | Load GD&T / tolerance data | Serialize annotations | Empty directory | | `jobs/` | Load job definitions for display | Serialize job YAML edits | Empty directory | | `thumbnails/` | Load Silo-rendered previews | No-op (server generates these) | Empty directory | **Risk:** Medium. Signal timing relative to FreeCAD's ZIP write must be tested carefully to ensure `silo/` entries are written before the archive is finalized. **Acceptance criteria:** - Opening a `.kc` with populated `silo/metadata.json` surfaces schema fields in the Create UI. - Saving a `.kc` persists metadata changes across close/reopen cycles. - Promoting an `.fcstd` to `.kc` assigns a UUID and creates `silo/manifest.json`. ### Layer 3: Silo Workbench Integration (Python) The Silo workbench (`mods/silo/`) connects `.kc` files to the live Silo server. **Scope:** - **Commit to Silo** — reads `silo/manifest.json` for the part UUID, uploads the `.kc` via REST. Silo extracts and indexes the `silo/` metadata server-side. - **Checkout from Silo** — downloads a `.kc` with fully populated `silo/` directory. `KindredDocument` hydrates metadata on open. - **Dependency resolution** — `silo/dependencies.json` stores assembly references by UUID. On opening an assembly, the workbench resolves UUIDs to local paths or triggers downloads for missing components. - **Offline reconciliation** — on reconnect, compare `manifest.json` revision hashes. Server wins on conflict unless the user explicitly forces a local override. Display a diff summary before reconciliation. **Risk:** Medium. Depends on Silo server API endpoints existing for each metadata type. Can be built incrementally — start with commit/checkout of the full `.kc` blob, then add granular metadata sync per module. **Acceptance criteria:** - Commit/checkout round-trips a `.kc` without metadata loss. - Assembly checkout resolves all `dependencies.json` UUIDs to local files. - Offline edits reconcile cleanly when connection is restored. ### Layer 4: Compute Job Attachment (Python) UI for managing `silo/jobs/` YAML definitions. Ties into Silo's Tier 3 compute modules. **Scope:** - Task panel in the Silo workbench for viewing, editing, and attaching job YAMLs. - Job trigger configuration (on-commit, on-release, manual). - Status display for running/completed jobs (fetched from Silo server). **Risk:** Low (UI-only on the client side). Depends on Silo job queue infrastructure being operational. **Acceptance criteria:** - Users can attach a job YAML to a `.kc` file via the UI. - Job status is visible in the Silo workbench panel. --- ## 7. Implementation Sequence Layers are ordered by dependency and risk: 1. **Layer 1** (Format Registration) — Small C++ diff. Low risk. Immediately lets users open/save `.kc` files even without Silo running. No functional behavior beyond file association. 2. **Layer 2** (Metadata Layer) — Bulk of the work. Develop incrementally: start with `manifest.json` only, add other `silo/` entries as their respective Silo modules come online. 3. **Layer 3** (Silo Integration) — Requires Silo server API endpoints. Build commit/checkout first, add granular metadata sync as modules mature. 4. **Layer 4** (Job Attachment) — Deferred until Silo Tier 3 (Job Queue + Compute modules) is operational. The `silo/jobs/` directory sits empty until then. This sequence ensures Create is backwards-compatible with `.fcstd` at every step. The `.kc` format grows incrementally as Silo modules ship, matching the tiered dependency structure in the platform roadmap. --- ## 8. Version Migration The `kc_version` field in `silo/manifest.json` tracks the schema version. When the `.kc` spec evolves: - **Additive changes** (new optional `silo/` entries): No migration needed. Older files simply lack the new entries. - **Breaking changes** (renamed fields, restructured entries): A migration function in `KindredDocument` upgrades `silo/` contents on open. The original file is preserved until the user explicitly saves. - **Version floor:** Create refuses to open `.kc` files with a `kc_version` newer than it supports, displaying an "update Create" message. --- ## 9. Security Considerations **Macro execution:** `silo/macros/` scripts execute with full FreeCAD Python API access. Files from untrusted sources should prompt the user before macro registration. A configurable trust policy (always trust from this Silo instance / never auto-execute / prompt each time) is exposed in Create preferences. **Job YAML injection:** `silo/jobs/` YAMLs specify container images and resource requests. The Silo server validates job definitions against an allowlist of approved images and resource limits before dispatching. The client does not execute jobs directly. **Metadata tampering:** `silo/manifest.json` contains the revision hash. On commit, Silo validates the hash against its own records. Tampered manifests are rejected with a conflict error requiring re-checkout. --- ## 10. Open Questions 1. **FreeCAD ZIP rewrite behavior** — Confirm that FreeCAD 1.0+ preserves unknown ZIP entries on save across all platforms. If not, the `silo/` directory must be re-injected post-save via a signal hook. 2. **Thumbnail policy** — Single canonical isometric thumbnail vs. configurable multi-view renders. Impacts `silo/thumbnails/` size and Headless Create compute cost. 3. **Offline metadata authority** — How much of `silo/metadata.json` (particularly lifecycle state) can be modified offline? Current proposal: lifecycle transitions require server confirmation; field edits are permitted offline and reconciled on commit. 4. **Assembly dependency depth** — Should `silo/dependencies.json` be recursive (full assembly tree) or single-level (direct children only)? Single-level is simpler; recursive enables full offline assembly loading. 5. **Macro sandboxing** — Is a restricted execution environment for `silo/macros/` feasible within FreeCAD's Python runtime, or is trust-based policy the only practical option? --- ## Appendix A: MIME Type and File Association | Property | Value | |----------|-------| | Extension | `.kc` | | MIME type | `application/x-kindred-create` | | UTI (macOS) | `com.kindred-systems.create.document` | | Magic bytes | `PK` (ZIP header, offset 0) + `silo/manifest.json` entry present | | Icon | Kindred Create document icon (from `icons/kindred/` asset set) | --- ## Appendix B: Glossary | Term | Definition | |------|------------| | `.fcstd` | FreeCAD Standard file format. ZIP containing `Document.xml`, `GuiDocument.xml`, BREP cache, and thumbnails. | | `.kc` | Kindred Create file format. Superset of `.fcstd` with a `silo/` directory. | | BREP | Boundary Representation. OpenCASCADE geometry format stored as `.brp` files. Derived cache, regenerable from `Document.xml`. | | Promotion | Converting an `.fcstd` to `.kc` by adding a `silo/` directory with at minimum `manifest.json`. | | Demotion | Converting a `.kc` to `.fcstd` by stripping the `silo/` directory. | | Reconciliation | Process of merging offline `.kc` edits with server-side state on reconnect. | | Schema | A Silo-defined template specifying which metadata fields exist for a given part category. | --- ## Appendix C: References - [FreeCAD FCStd File Format](https://wiki.freecad.org/Fcstd_file_format) - [Silo Platform Roadmap](ROADMAP.md) - [Silo Gap Analysis](GAP_ANALYSIS.md) - [Silo Specification](SPECIFICATION.md)