# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project goal

An **MCP (Model Context Protocol) server** that lets an LLM drive the CAD system **КОМПАС-3D** (ASCON).
The server is a COM client of an installed КОМПАС: it exposes CAD operations (documents, 2D sketches,
3D parts, assemblies, drawings, STEP round-trip, model inspection) as MCP tools over stdio.

**There is no `docs/` directory** — it was deleted deliberately (commit `b022a91`). Do not re-create
`docs/ARCHITECTURE.md`, `docs/TODO.md`, `docs/OPEN_QUESTIONS.md`. Prose documentation lives in exactly
three places: this file (always loaded — architecture, principles, backlog, traps), the skill
`kompas-mcp-dev` with `reference/*.md` (loaded on demand — verified COM call-chains, release and CI),
and [`README.md`](README.md) (the tool catalog). Plus the memory files (`kompas-*-api*.md`).

Authoritative API references:
- **SDK knowledge base in RAG: MCP server `kompas-sdk`** — 2465 articles (one per COM interface/topic),
  served from the separate `kompas-sdk-docs` repo, indexed on CT 127 (rag-node). **Not in this repo** —
  Grep/Read won't find it. For any lookup dispatch the **`kompas-sdk-research`** subagent (Haiku), which
  owns the MCP tools.
- Online SDK docs: https://help.ascon.ru/KOMPAS_SDK/22/ru-RU/index.html
- Local SDK install: `C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK` (headers `Include\ksConstants*.h`
  are the last word on numeric constant values)
- `libs/kompas-interop/*.dll` — reflect over these to verify any signature a research answer gives you.

The base covers the **COM API7/API5** reference this project uses; the cross-platform Qt/C++ **KsAPI**
flavour (`ksapi_*`, non-COM) is intentionally **excluded** — ignore unless explicitly working with KsAPI.
How to search it is in the subagent's own definition (`.claude/agents/kompas-sdk-research.md`) — those
tools are scoped to the subagent, this session cannot call them. How to regenerate the base when a new
КОМПАС ships — skill `kompas-mcp-dev`, `reference/plugin-and-release.md`.

## Current state

**Status:** working end-to-end. Parts (sketch → feature → inspect), forming ops, patterns/mirror, holes,
direct B-rep edit, STEP import/export, assemblies, 2D drawings, structural inspection — implemented and
validated live. Also packaged as the Claude Code plugin `kompas` (no release published yet).

The full tool catalog (by group) lives in [`README.md`](README.md) §«Инструменты» — the single
source of truth; do not duplicate it here.

**The catalog is shaped for the agent, not for the SDK** (56 tools, down from 84): a tool names the
*operation*, the variant is a parameter (`extrude(mode=boss|cut)`, `hole(type=…)`, `pattern(kind=…)`);
an object is picked by index **or** point through one tool (no `*_index` twins); list parameters
(`entities[]`, `edgeIndices[]`) run in a single STA hop; and every mutating op appends its own build-check
result (`AutoValidation`, switched by `set_auto_validate` / `KOMPAS_MCP_AUTOVALIDATE`) so the agent doesn't
call `validate_part` after each step. Keep that shape when adding tools — rules and rationale in skill
`kompas-mcp-dev` §«Правила формы инструмента».

```powershell
dotnet build -c Release                          # build
dotnet test  --filter "Category=Unit"            # no COM needed
dotnet test  --filter "Category=Integration"     # needs a running КОМПАС
dotnet run --project src/Kompas.Mcp.Host         # start the MCP server (stdio)
pwsh -NoProfile -File tools/tests/run-ps-tests.ps1   # Pester tests for the plugin's PowerShell
```

Principle: **MCP = translating SDK capabilities into general tools**, never task-specific ones. If a
technique is missing, don't hardcode a workaround for the case at hand — prove the mechanism, then add
a *general* tool with tests, and describe the method in the `kompas-3d` skill.

### Backlog (canonical since `docs/TODO.md` is gone)

- **2D drawing** (top priority): bases (`drawing_add_base`), tolerances, associative binding for
  arc/angular/rough dimensions (needs its own spike — `ILineDimension` has no `BaseObject`).
- **Assembly**: mate types beyond `coincidence`/`distance` — `parallel`, `perpendicular`, `concentric`,
  `angle`, `tangency` (enum values exist in `MateType.cs`, not verified live).
- **Editing the tree** (raised by the `cad-engineer` regression run): there is no `feature_delete` /
  `sketch_update`, so any fit-up of a sketch means `document_close(all)` + rebuilding from scratch —
  four full rounds in that run. `IFeature7.Delete()` exists and `ksDocument3D.DeleteObject` is the API5
  counterpart; neither is verified live yet.
- **Addressing a subset of edges/faces**: on a body with hundreds of edges `list_edges` is unusable by
  answer size and there is no filter (by operation, by bounding window). Points now work in a batch
  (`fillet_edge(points=[…])`), but discovery still has no cheap path.
- **Known caveat:** boss/cut direction on a *selected face* depends on the face-normal orientation —
  `forward` may need flipping. Pick the direction from the `list_faces(index=…)` normal or a snapshot
  before building.

## Working mode: CAD tasks are the proving ground

The user solves small CAD tasks through the MCP tools (or uses the server as an assistant), but **the point
of those tasks is improving the server and its skills**, not the part being modelled. A task that goes badly
is a bug report, not a reason to work around it by hand. Three feedback channels, not one:

| Symptom | Where the fix goes |
|---|---|
| A tool crashes or returns the wrong result | `src/` → patch + test |
| No tool exposes the mechanism at all | `src/` → a new **general** tool (never case-specific) |
| Tools worked, but the route taken was wrong / a trap was unknown | `plugin/skills/kompas-3d/SKILL.md` |
| Geometry built fine but isn't printable on FDM | `plugin/skills/kompas-fdm-design/` (+ `references/`) |

Reading the sources, proposing patches, editing and rebuilding are all explicitly sanctioned — including
asking for a session restart when a rebuilt server has to be picked up.

- **A spike proves a theory; the deliverable is built with MCP tools.** A throwaway dotnet project under
  `usecases/<case>/` (referencing `Kompas.Mcp.Core`) is a legitimate way to measure something or falsify a
  claim — but the final part/drawing must be produced by MCP tool calls. A runner bypasses the very layer
  under test (tool schemas, input parsing, answer shape, auto-validation), so "built by the runner" proves
  nothing about the server. Missing tools are the finding, not a reason to finish by hand; delete the
  probe project afterwards and carry its numbers into the case's `plan.md` and the skill.
- **Skills are debugged like code.** `kompas-3d` and `kompas-fdm-design` are objects of revision, not fixed
  inputs. Edit them **only** in `plugin/skills/<name>/` (the source of truth — the other trees are junctions);
  a skill edit needs no rebuild but is only picked up by a *new* session.
- **Nothing internal leaks into a published skill** — no local SDK paths, no `usecases/`, no RAG-base
  references. Internal findings belong in `kompas-mcp-dev`; only reproducible methodology ships.
### The rebuild cycle

A running server holds its own binary: with `.mcp.json` pointing straight at
`src/Kompas.Mcp.Host/bin/…/kompas-mcp.exe`, `dotnet build -c Release` dies on `MSB3027` («file in use»),
and *every* open session counts — the error names each holding PID. `tools/dev/` removes that coupling.

- **`tools/dev/launch-dev-mcp.ps1`** — what `.mcp.json` now points at. It copies the build (~10 MB) into
  `%LOCALAPPDATA%\kompas-mcp\dev\<fingerprint>` and runs the server from there, so `bin` is never locked and
  a build never waits for a session to close. Logic lives in `tools/dev/KompasMcpDev.psm1`; overrides:
  `KOMPAS_MCP_EXE` (bypass the shadow copy entirely), `KOMPAS_MCP_DEV_BUILD_DIR`, `KOMPAS_MCP_DEV_ROOT`.
- **`tools/dev/rebuild-mcp.ps1`** — `-Check` compiles past `bin` (redirect `BaseOutputPath` only — moving
  `BaseIntermediateOutputPath` too makes the stale `obj/` visible to the glob and yields `CS0579`) so a
  syntax/type check costs ~2 s with the server live. Without flags: full build + `Category=Unit`, refusing
  early with the blocking PIDs instead of burning 15 s on retries.
- **A new binary still needs the stdio process restarted** — `/mcp` reconnect if the client supports it,
  otherwise a new session. Restarting is safe for КОМПАС: `KompasSession.Dispose` releases the COM objects
  but deliberately never calls `Quit`, so the document survives. What does not survive: the connection
  (`kompas_connect` again) and the in-memory build state — sketches by `id`. Save before restarting.
- **Two traps in the launcher's PowerShell**, both invisible under `pwsh` 7 and fatal under the 5.1 that
  `.mcp.json` actually uses: `Get-ChildItem` returning a *single* file is a scalar, so `.Count` throws under
  `Set-StrictMode`; and `Sort-Object` orders punctuation differently in 5.1 (NLS) vs 7 (ICU), which made the
  same build hash to two different fingerprints. Sort ordinal (`List.Sort([StringComparer]::Ordinal)`).

## Skills and their layout

- **`kompas-3d`** — methodology for *building* things through the MCP tools (playbooks, heuristics).
- **`kompas-fdm-design`** — DFM layer for FDM/FFF printing (overhang rules, wall thickness, teardrop
  holes, fits/clearances, orientation for strength, elephant foot, bosses/inserts/snap-fits) plus a
  light geometry audit via the inspection tools. Builds through `kompas-3d`, exports via `export_step`,
  no slicer integration.
- **`kompas-mcp-dev`** — internal: developing the server itself (the two layers, the `usecases/` proving
  ground, the checklist for productizing a technique into a general tool, delegation). Lives at
  `.claude/skills/kompas-mcp-dev/SKILL.md` as a real directory (not a junction) because the published
  skills must not reference things a plugin user doesn't have.

**Sync** (`tools/sync-agent-assets.ps1`, module `tools/AgentAssets.psm1`): the source of truth is
`plugin/skills/{kompas-3d,kompas-fdm-design}`; `.claude/skills/<name>` and `.agents/skills/<name>` are
**junctions** onto it created by the script (their paths are pinpointed in `.gitignore` — git sees a
junction as a plain directory). Its modes are mutually exclusive parameter sets, so `-Remove -Check`
together is a parameter-binding error.

**Gotcha:** switching to a branch/commit predating `plugin/skills` leaves the junctions dangling and
`git checkout` fails mid-way (`unable to create file .claude/skills/kompas-fdm-design/SKILL.md: No such
file or directory`) — part of the worktree is already deleted while HEAD stays on the old branch.
Recover with `git ls-files --deleted -z | xargs -0 git restore --`. Correct order:

1. `pwsh -NoProfile -File tools/sync-agent-assets.ps1 -Remove`
2. `git checkout <ref>`
3. `pwsh -NoProfile -File tools/sync-agent-assets.ps1` (re-link, if `plugin/skills` exists on that ref)

`-Remove` is safe: it deletes the reparse point itself via `[System.IO.Directory]::Delete` (no `-Recurse`),
never walks into the target, and leaves a real (non-junction) directory alone (`Skipped`); it detects a
junction by the `ReparsePoint` attribute rather than by resolving the target, which is exactly why it
still works once the target is gone. No `post-checkout` hook on purpose — it fires after checkout already
broke, too late to help.

## Delegation subagents

**`cad-engineer`** (`.claude/agents/`, model inherit — Skill/Read/Glob/Grep + the `kompas` MCP server,
no write access): runs a whole CAD task end-to-end from a clean context, building **only** through MCP
tools. It is a **debugging harness**, not a shortcut: this session fixes the skills and the server, then
re-runs the same task through the subagent and reads its protocol — calls made, dead ends, complaints
against the skill (quoted), complaints against the catalog. It can't patch anything, so a missing tool
comes back as a finding instead of a hand-made workaround. Project-local, never shipped in the plugin.

**`kompas-sdk-research`** (`.claude/agents/`, model **Haiku**, read-only — MCP `kompas-sdk` tools only):
finds an interface/method/enum/constant signature in the SDK knowledge base and returns a compressed
summary. Dispatch it for **any** SDK lookup — it holds the only access to the base, which no longer lives
in this repo. Its system prompt is in the agent definition, so pass only the question as the prompt.
A wrong answer is cheap: re-verify against `libs/kompas-interop/*.dll` by reflection.

(The former `docs-maintainer` subagent was removed together with `docs/` — edit `README.md`/`CLAUDE.md`
directly.)

## Claude Code plugin (`plugin/`)

The server and both published skills ship as the plugin **`kompas`** — `plugin/` is a self-contained tree,
distributed independently of the rest of the repo, released from the **`dist`** branch (never `main`).

Manifest/lock layout, the delivery bootstrap, the launcher's stdout invariant, the release workflow and the
CI gotchas — skill **`kompas-mcp-dev`**, `reference/plugin-and-release.md`. Two rules that must not wait
for a skill load:

- **Every release must bump `plugin/.claude-plugin/plugin.json`** — the version is Claude Code's cache key,
  and `/plugin update` silently skips a plugin whose version already matches what's installed.
- **Plugin PowerShell files must be UTF-8 *with BOM*.** The launcher runs under Windows PowerShell 5.1,
  which reads BOM-less files in the system ANSI codepage — Cyrillic string literals then corrupt parsing of
  the whole script. `pwsh` 7 doesn't reproduce this, so it passes locally and breaks for the user.

## Key implementation facts (don't relearn)

Verified COM call-chains — interop loading, the STA dispatcher, API5 `ksPart` building, face/edge selection,
МЦХ, snapshots, the feature tree, variables, STEP round-trip, direct B-rep edit, forming ops, patterns and
mirror, holes, assemblies, 2D drawings, sketch primitives — live in skill **`kompas-mcp-dev`**,
`reference/com-implementation-facts.md`. Load that skill before touching the COM layer; append to it when a
new chain is verified live. Cross-checked duplicates also sit in memory (`kompas-*-api*.md`).

## КОМПАС-3D API architecture (the critical context)

КОМПАС-3D is automated via a **COM Automation API**, Windows-only. КОМПАС **must be installed and
running/launchable on the same machine** — the MCP server is a COM client, not a standalone CAD engine.
Two API generations coexist:

| | Entry point | Namespace (C#) | Style | Use when |
|---|---|---|---|---|
| **API5** (legacy) | `KompasObject` | `Kompas6API5` | procedural, flat | 3D `ksPart` building, 2D primitives, bootstrapping |
| **API7** (modern, preferred) | `IApplication` / `_Application` | `KompasAPI7` | OOP, interface-based | documents, holes, assemblies, drawings, B-rep edit |

Constants live in separate libraries: `Kompas6Constants`, `Kompas6Constants3D` (C#), or `ksConstants.h` /
`ksConstants3D.h` (C++).

### Connection pattern (verified from `Samples/CSharp.zip`)

1. Get the КОМПАС root object by COM ProgID. **Verified on this machine (v24 Home):**
   `KOMPAS.Application.7` and `KOMPAS.Application.5` are registered; `KOMPASLT.*` is **absent** — the Home
   edition uses the regular (non-LT) ProgIDs. Resolution order:
   - `KOMPAS.Application.7` — direct API7 `IApplication` (preferred)
   - `KOMPAS.Application.5` — API5 `KompasObject`, then `ksGetApplication7()`
   - `KOMPASLT.Application.5` — fallback for other installations
   - New instance: `Activator.CreateInstance(Type.GetTypeFromProgID(progId))`
   - Attach to a running instance: `Marshal.GetActiveObject(progId)`
2. If you entered via API5, obtain the modern application:
   `IApplication appl = (IApplication)kompas.ksGetApplication7();`
3. Set `appl.Visible = true` to show the КОМПАС window; drive documents via API7 interfaces
   (`IKompasDocument2D`, `IKompasDocument3D`, …).

> The SDK C# samples are mostly **КОМПАС plugin libraries** (DLLs loaded *into* КОМПАС as ActiveX, entry
> methods like `ExternalRunCommand`/`ExternalMenuItem`, registered via `[ComRegisterFunction]`). This server
> is the **opposite direction**: a standalone *external automation client* connecting out-of-process via the
> ProgID pattern above. Read the samples for API usage, not for the plugin packaging/registration boilerplate.

## SDK layout (read-only reference, not part of this repo)

The SDK tree under `C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK` (`lib\*.tlb`, `lib64\`, `Include\`,
`KsAPI\`, `Samples\*.zip`, `Help\KOMPAS_SDK_ru-RU.zip`) is one `ls` away — browse it rather than trusting
a copy here. Two things that are **not** visible from a listing:

To inspect a sample without unpacking the whole archive:
`unzip -p "<path>\Samples\CSharp.zip" "Automation/Step2_API7_3D/Step2_API7_3D.cs"`. The `.cs` sample sources
are **Windows-1251 encoded** (Cyrillic comments appear garbled in UTF-8 tools).

## Conventions / gotchas

- **Windows-only & 64-bit**: target x64 to match the installed КОМПАС; mixing bitness breaks COM activation.
  v24 Home is the installed edition — some full-edition API features may be unavailable.
- **Encoding**: SDK sources are CP1251; project files are UTF-8; plugin PowerShell is UTF-8 **with BOM**.
- **COM lifetime**: release COM objects (`Marshal.ReleaseComObject`) or scope them; a leaked reference keeps
  the КОМПАС process alive.
- **API choice**: prefer API7 for new tools; drop to API5 only for what API7 doesn't expose.
- **Sequential tool calls**: the build session keeps sketches by `id` and the server serves requests
  concurrently — dependent tool calls must be awaited one at a time.
