Session 3 of the four-session plan. Two more engineering planning
docs that lock in the most contentious architectural decisions
before V1 implementation begins.
docs/architecture/tool-handoff-boundaries.md
--------------------------------------------
Locks in the V1 read/write relationship with external tools:
- AtoCore is a one-way mirror in V1. External tools push,
AtoCore reads, AtoCore never writes back.
- Per-tool stance table covering KB-CAD, KB-FEM, NX, PKM, Gitea
repos, OpenClaw, AtoDrive, PLM/vendor systems
- Two new ingest endpoints proposed for V1:
POST /ingest/kb-cad/export and POST /ingest/kb-fem/export
- Sketch JSON shapes for both exports (intentionally minimal,
to be refined in dedicated schema docs during implementation)
- Drift handling: KB-CAD changes a value -> creates an entity
candidate -> existing active becomes a conflict member ->
human resolves via the conflict model
- Hard-line invariants V1 will not cross: no write to external
tools, no live polling, no silent merging, no schema fan-out,
no external-tool-specific logic in entity types
- Why not bidirectional: schema drift, conflict semantics, trust
hierarchy, velocity, reversibility
- V2+ deferred items: selective write-back annotations, light
polling, direct NX integration, cost/vendor/PLM connections
- Open questions for the implementation sprint: schema location,
who runs the exporter, full-vs-incremental, exporter auth
docs/architecture/representation-authority.md
---------------------------------------------
The canonical-home matrix that says where each kind of fact
actually lives:
- Six representation layers identified: PKM, KB project,
Gitea repos, AtoCore memories, AtoCore entities, AtoCore
project_state
- The hard rule: every fact kind has exactly one canonical
home; other layers may hold derived copies but never disagree
- Comprehensive matrix covering 22 fact kinds (CAD geometry,
CAD-side structure, FEM mesh, FEM results, code, repo docs,
PKM prose, identity, preference, episodic, decision,
requirement, constraint, validation claim, material,
parameter, project status, ADRs, runbooks, backup metadata,
interactions)
- Cross-layer supremacy rule: project_state > tool-of-origin >
entities > active memories > source chunks
- Three worked examples showing how the rules apply:
* "what material does the lateral support pad use?" (KB-CAD
canonical, project_state override possible)
* "did we decide to merge the bind mounts?" (Gitea + memory
both canonical for different aspects)
* "what's p05's current next focus?" (project_state always
wins for current state queries)
- Concrete consequences for V1 implementation: Material and
Parameter are mostly KB-CAD shadows; Decisions / Requirements /
Constraints / ValidationClaims are AtoCore-canonical; PKM is
never authoritative; project_state is the override layer;
the conflict model is the enforcement mechanism
- Out of scope for V1: facts about other people, vendor/cost
facts, time-bounded facts, cross-project shared facts
- Open questions for V1: how the reviewer sees canonical home
in the UI, whether entities need an explicit canonical_home
field, how project_state overrides surface in query results
This is pure doc work. No code, no schema, no behavior changes.
After this commit the engineering planning sprint is 6 of 8 docs
done — only human-mirror-rules and engineering-v1-acceptance
remain.
14 KiB
Tool Hand-off Boundaries (KB-CAD / KB-FEM and friends)
Why this document exists
The engineering layer V1 will accumulate typed entities about projects, subsystems, components, materials, requirements, constraints, decisions, parameters, analysis models, results, and validation claims. Many of those concepts also live in real external tools — CAD systems, FEM solvers, BOM managers, PLM databases, vendor portals.
The first big design decision before writing any entity-layer code is: what is AtoCore's read/write relationship with each of those external tools?
The wrong answer in either direction is expensive:
- Too read-only: AtoCore becomes a stale shadow of the tools and loses the trust battle the moment a value drifts.
- Too bidirectional: AtoCore takes on responsibilities it can't reliably honor (live sync, conflict resolution against external schemas, write-back validation), and the project never ships.
This document picks a position for V1.
The position
AtoCore is a one-way mirror in V1. External tools push structured exports into AtoCore. AtoCore never pushes back.
That position has three corollaries:
- External tools remain the source of truth for everything they already manage. A CAD model is canonical for geometry; a FEM project is canonical for meshes and solver settings; KB-CAD is canonical for whatever KB-CAD already calls canonical.
- AtoCore is the source of truth for the AtoCore-shaped record of those facts: the Decision that selected the geometry, the Requirement the geometry satisfies, the ValidationClaim the FEM result supports. AtoCore does not duplicate the external tool's primary representation; it stores the structured facts about it.
- The boundary is enforced by absence. No write endpoint in
AtoCore ever generates a
.prt, a.fem, an export to a PLM schema, or a vendor purchase order. If we find ourselves wanting to add such an endpoint in V1, we should stop and reconsider the V1 scope.
Why one-way and not bidirectional
Bidirectional sync between independent systems is one of the hardest problems in engineering software. The honest reasons we are not attempting it in V1:
- Schema drift. External tools evolve their schemas independently. A bidirectional sync would have to track every schema version of every external tool we touch. That is a permanent maintenance tax.
- Conflict semantics. When AtoCore and an external tool disagree on the same field, "who wins" is a per-tool, per-field decision. There is no general rule. Bidirectional sync would require us to specify that decision exhaustively.
- Trust hierarchy. AtoCore's whole point is the trust hierarchy: trusted project state > entities > memories. If we let entities push values back into the external tools, we silently elevate AtoCore's confidence to "high enough to write to a CAD model", which it almost never deserves.
- Velocity. A bidirectional engineering layer is a multi-year project. A one-way mirror is a months project. The value-to-effort ratio favors one-way for V1 by an enormous margin.
- Reversibility. We can always add bidirectional sync later on a per-tool basis once V1 has shown itself to be useful. We cannot easily walk back a half-finished bidirectional sync that has already corrupted data in someone's CAD model.
Per-tool stance for V1
| External tool | V1 stance | What AtoCore reads in | What AtoCore writes back |
|---|---|---|---|
| KB-CAD (Antoine's CAD knowledge base) | one-way mirror | structured exports of subsystems, components, materials, parameters via a documented JSON or CSV shape | nothing |
| KB-FEM (Antoine's FEM knowledge base) | one-way mirror | structured exports of analysis models, results, validation claims | nothing |
| NX / Siemens NX (the CAD tool itself) | not connected in V1 | nothing direct — only what KB-CAD exports about NX projects | nothing |
| PKM (Obsidian / markdown vault) | already connected via the ingestion pipeline (Phase 1) | full markdown/text corpus per the ingestion-waves doc | nothing |
| Gitea repos | already connected via the ingestion pipeline | repo markdown/text per project | nothing |
| OpenClaw (the LLM agent) | already connected via the read-only helper skill on the T420 | nothing — OpenClaw reads from AtoCore | nothing — OpenClaw does not write into AtoCore |
| AtoDrive (operational truth layer, future) | future: bidirectional with AtoDrive itself, but AtoDrive is internal to AtoCore so this isn't an external tool boundary | n/a in V1 | n/a in V1 |
| PLM / vendor portals / cost systems | not in V1 scope | nothing | nothing |
What "one-way mirror" actually looks like in code
AtoCore exposes an ingestion endpoint per external tool that accepts a structured export and turns it into entity candidates. The endpoint is read-side from AtoCore's perspective (it reads from a file or HTTP body), even though the external tool is the one initiating the call.
Proposed V1 ingestion endpoints:
POST /ingest/kb-cad/export body: KB-CAD export JSON
POST /ingest/kb-fem/export body: KB-FEM export JSON
Each endpoint:
- Validates the export against the documented schema
- Maps each export record to an entity candidate (status="candidate")
- Carries the export's source identifier into the candidate's provenance fields (source_artifact_id, exporter_version, etc.)
- Returns a summary: how many candidates were created, how many were dropped as duplicates, how many failed schema validation
- Does NOT auto-promote anything
The KB-CAD and KB-FEM teams (which is to say, future-you) own the exporter scripts that produce these JSON bodies. Those scripts live in the KB-CAD / KB-FEM repos respectively, not in AtoCore.
The export schemas (sketch, not final)
These are starting shapes, intentionally minimal. The schemas
will be refined in kb-cad-export-schema.md and
kb-fem-export-schema.md once the V1 ontology lands.
KB-CAD export shape (starting sketch)
{
"exporter": "kb-cad",
"exporter_version": "1.0.0",
"exported_at": "2026-04-07T12:00:00Z",
"project": "p05-interferometer",
"subsystems": [
{
"id": "subsystem.optical-frame",
"name": "Optical frame",
"parent": null,
"components": [
{
"id": "component.lateral-support-pad",
"name": "Lateral support pad",
"material": "GF-PTFE",
"parameters": {
"thickness_mm": 3.0,
"preload_n": 12.0
},
"source_artifact": "kb-cad://p05/subsystems/optical-frame#lateral-support"
}
]
}
]
}
KB-FEM export shape (starting sketch)
{
"exporter": "kb-fem",
"exporter_version": "1.0.0",
"exported_at": "2026-04-07T12:00:00Z",
"project": "p05-interferometer",
"analysis_models": [
{
"id": "model.optical-frame-modal",
"name": "Optical frame modal analysis v3",
"subsystem": "subsystem.optical-frame",
"results": [
{
"id": "result.first-mode-frequency",
"name": "First-mode frequency",
"value": 187.4,
"unit": "Hz",
"supports_validation_claim": "claim.frame-rigidity-min-150hz",
"source_artifact": "kb-fem://p05/models/optical-frame-modal#first-mode"
}
]
}
]
}
These shapes will evolve. The point of including them now is to make the one-way mirror concrete: it is a small, well-defined JSON shape, not "AtoCore reaches into KB-CAD's database".
What AtoCore is allowed to do with the imported records
After ingestion, the imported records become entity candidates in AtoCore's own table. From that point forward they follow the exact same lifecycle as any other candidate:
- they sit at status="candidate" until a human reviews them
- the reviewer promotes them to status="active" or rejects them
- the active entities are queryable via the engineering query catalog (Q-001 through Q-020)
- the active entities can be referenced from Decisions, Requirements, ValidationClaims, etc. via the V1 relationship types
The imported records are never automatically pushed into trusted project state, never modified in place after import (they are superseded by re-imports, not edited), and never written back to the external tool.
What happens when KB-CAD changes a value AtoCore already has
This is the canonical "drift" scenario. The flow:
- KB-CAD exports a fresh JSON. Component
component.lateral-support-padnow hasmaterial: "PEEK"instead ofmaterial: "GF-PTFE". - AtoCore's ingestion endpoint sees the same
idand a different value. - The ingestion endpoint creates a new entity candidate with the
new value, does NOT delete or modify the existing active
entity, and creates a
conflictsrow linking the two members (per the conflict model doc). - The reviewer sees an open conflict on the next visit to
/conflicts. - The reviewer either:
- promotes the new value (the active is superseded, the candidate becomes the new active, the audit trail keeps both)
- rejects the new value (the candidate is invalidated, the active stays — useful when the export was wrong)
- dismisses the conflict (declares them not actually about the same thing, both stay active)
The reviewer never touches KB-CAD from AtoCore. If the resolution implies a change in KB-CAD itself, the reviewer makes that change in KB-CAD, then re-exports.
What about NX directly?
NX (Siemens NX) is the underlying CAD tool that KB-CAD wraps. NX is not connected to AtoCore in V1. Any facts about NX projects flow through KB-CAD as the structured intermediate. This gives us:
- One schema to maintain. AtoCore only has to understand the KB-CAD export shape, not the NX API.
- One ownership boundary. KB-CAD owns the question of "what's in NX". AtoCore owns the question of "what's in the typed knowledge base".
- Future flexibility. When NX is replaced or upgraded, only KB-CAD has to adapt; AtoCore doesn't notice.
The same logic applies to FEM solvers (Nastran, Abaqus, ANSYS): KB-FEM is the structured intermediate, AtoCore never talks to the solver directly.
The hard-line invariants
These are the things V1 will not do, regardless of how convenient they might seem:
- No write to external tools. No POST/PUT/PATCH to any external API, no file generation that gets written into a CAD/FEM project tree, no email/chat sends.
- No live polling. AtoCore does not poll KB-CAD or KB-FEM on a schedule. Imports are explicit pushes from the external tool into AtoCore's ingestion endpoint.
- No silent merging. Every value drift surfaces as a conflict for the reviewer (per the conflict model doc).
- No schema fan-out. AtoCore does not store every field that KB-CAD knows about. Only fields that map to one of the V1 entity types make it into AtoCore. Everything else is dropped at the import boundary.
- No external-tool-specific logic in entity types. A
Componentin AtoCore is the same shape regardless of whether it came from KB-CAD, KB-FEM, the PKM, or a hand-curated project state entry. The source is recorded in provenance, not in the entity shape.
What this enables
With the one-way mirror locked in, V1 implementation can focus on:
- The entity table and its lifecycle
- The two
/ingest/kb-cad/exportand/ingest/kb-fem/exportendpoints with their JSON validators - The candidate review queue extension (already designed in
promotion-rules.md) - The conflict model (already designed in
conflict-model.md) - The query catalog implementation (already designed in
engineering-query-catalog.md)
None of those are unbounded. Each is a finite, well-defined implementation task. The one-way mirror is the choice that makes V1 finishable.
What V2 might consider (deferred)
After V1 has been live and demonstrably useful for a quarter or two, the questions that become reasonable to revisit:
- Selective write-back to KB-CAD for low-risk fields. For example, AtoCore could push back a "Decision id linked to this component" annotation that KB-CAD then displays without it being canonical there. Read-only annotations from AtoCore's perspective, advisory metadata from KB-CAD's perspective.
- Live polling for very small payloads. A daily poll of "what subsystem ids exist in KB-CAD now" so AtoCore can flag subsystems that disappeared from KB-CAD without an explicit AtoCore invalidation.
- Direct NX integration if the KB-CAD layer becomes a bottleneck — but only if the friction is real, not theoretical.
- Cost / vendor / PLM connections for projects where the procurement cycle is part of the active engineering work.
None of these are V1 work and they are listed only so the V1 design intentionally leaves room for them later.
Open questions for the V1 implementation sprint
- Where do the export schemas live? Probably in
docs/architecture/kb-cad-export-schema.mdanddocs/architecture/kb-fem-export-schema.md, drafted during the implementation sprint. - Who runs the exporter? A scheduled job on the KB-CAD / KB-FEM hosts, triggered by the human after a meaningful change, or both?
- Is the export incremental or full? Full is simpler but more expensive. Incremental needs delta semantics. V1 starts with full and revisits when full becomes too slow.
- How is the exporter authenticated to AtoCore? Probably
the existing PAT model (one PAT per exporter, scoped to
write:engineering-importonce that scope exists). Worth a quick auth design pass before the endpoints exist.
TL;DR
- AtoCore is a one-way mirror in V1: external tools push, AtoCore reads, AtoCore never writes back
- Two import endpoints for V1: KB-CAD and KB-FEM, each with a documented JSON export shape
- Drift surfaces as conflicts in the existing conflict model
- No NX, no FEM solvers, no PLM, no vendor portals, no cost/BOM systems in V1
- Bidirectional sync is reserved for V2+ on a per-tool basis, only after V1 demonstrates value