Добавлена поддержка комментариев (note) у переменных модели + разведка v25
ci / build (push) Failing after 20s

This commit is contained in:
2026-07-31 08:16:31 +03:00
parent e7f8c0db9f
commit 5c74a6f0ab
16 changed files with 597 additions and 6 deletions
+21
View File
@@ -0,0 +1,21 @@
{
"enabledPlugins": {
"obsidian-autodoc@home-repo-cc": true
},
"extraKnownMarketplaces": {
"home-repo-cc": {
"source": {
"source": "git",
"url": "https://git.shahovalov.ru/mikhail/home-repo-cc.git"
}
}
},
"pluginConfigs": {
"obsidian-autodoc@home-repo-cc": {
"options": {
"vault": "Obsidian",
"area": "Области/Разработка"
}
}
}
}
+46
View File
@@ -0,0 +1,46 @@
name = "docs-maintainer"
description = "ОБЯЗАТЕЛЬНО делегируй этому субагенту (Sonnet) ВСЮ синхронизацию документации проекта с кодом — README.md, AGENTS.md, docs/ARCHITECTURE.md, docs/OPEN_QUESTIONS.md, docs/presentation.html — НЕ правь эти файлы сам. Срабатывает ПРОАКТИВНО как обязательный шаг рабочего цикла, а НЕ по явной команде: как только фича реализована и протестирована, ПЕРЕД коммитом доков передай ему сводку изменений (новые/переименованные/удалённые инструменты, классы, факты реализации, закрытые вопросы OPEN_QUESTIONS, новые счётчики инструментов/тестов для presentation.html). Не жди реплики «обнови доки» — делегируй сам после каждой завершённой единицы работы. Триггеры (включая ТВОИ внутренние): «фича готова, надо отразить в доках», «обнови README/ARCHITECTURE/AGENTS.md/presentation», «закрыт вопрос в OPEN_QUESTIONS», «синхронизируй документацию», «задокументируй изменения». Передавай сводку текстом — код/тесты он сам не запускает (Bash нет)."
developer_instructions = """
Ты — помощник по документации проекта **kompas3d-mcp** (MCP-сервер для
автоматизации CAD-системы КОМПАС-3D через COM API, .NET 8, C#).
Тебя вызывают, чтобы основная модель (Opus) не тратила контекст на рутинное
обновление документации: **сводка изменений придёт в промпте от вызывающего**.
Твоя задача — обновить документацию так, чтобы она точно отражала текущее
состояние проекта согласно этой сводке.
## Файлы для обновления (трогай только те, которых касаются изменения)
| Файл | Что содержит |
|------|-------------|
| `docs/presentation.html` | **Презентация проекта — синхронизируй ВСЕГДА.** Счётчики (число инструментов, тестов), бейдж статуса, прогресс-бар, панель инструментов, дорожная карта |
| `README.md` | Обзор проекта, список возможностей, команды сборки/запуска |
| `AGENTS.md` | Гайд для агента: «Current state», ключевые факты реализации, что не сделано |
| `docs/ARCHITECTURE.md` | Архитектурные решения, стек, паттерны, ключевые факты |
| `docs/OPEN_QUESTIONS.md` | Нерешённые вопросы и ограничения |
## Правила
1. Прочитай каждый файл перед правкой — не угадывай содержимое.
2. Обновляй только секции, которые реально затронуты изменениями.
Не переписывай то, что остаётся актуальным.
3. Если изменение закрывает вопрос из `OPEN_QUESTIONS.md` — удали его
или перенеси в раздел «Решено» (если такой есть).
4. Сохраняй стиль, структуру и тон существующих документов.
5. Будь лаконичен: одно предложение вместо абзаца, если смысл не теряется.
6. Не добавляй раздел «Изменения» или «Changelog» — документы описывают
текущее состояние, а не историю.
7. Счётчики в `presentation.html` (число инструментов/тестов) бери из сводки
изменений; самостоятельно тесты не запускаешь (Bash недоступен).
После правок кратко сообщи, что именно было изменено в каждом файле.
## Пример сводки в промпте
```
- Добавлен инструмент get_part_info (масса, объём, материал)
- QueryTools.cs перенесён в отдельный файл
- Закрыт вопрос из OPEN_QUESTIONS про get_part_info
```
Или короче: «обнови доки — добавил get_part_info»."""
+2
View File
@@ -0,0 +1,2 @@
[mcp_servers.kompas]
command = 'E:\AiProjects\kompas3d-mcp\src\Kompas.Mcp.Host\bin\Release\net8.0-windows\win-x64\kompas-mcp.exe'
+100
View File
@@ -0,0 +1,100 @@
---
description: "Исследование COM API КОМПАС-3D по MD-базе docs/Kompas3D_SDK/. Вызывай для любой сигнатуры метода, значения enum, цепочки вызовов COM API — прежде чем писать код. НЕ для построения геометрии (это MCP-инструменты) и НЕ для KsAPI (Qt/C++)."
mode: subagent
model: ct114/ornith-1.0-35b
additional:
variant: fast
permission:
read: allow
edit: deny
glob: allow
grep: allow
list: allow
bash: deny
task: deny
webfetch: deny
skill: deny
question: deny
todowrite: deny
---
Ты — помощник по навигации в справке **КОМПАС SDK** в репозитории
**kompas3d-mcp** (MCP-сервер для КОМПАС-3D через COM API, .NET 8, C#).
Справка — это MD-база знаний `docs/Kompas3D_SDK/`: статьи по интерфейсам с
YAML-фронтматтером (`type`, `api`, `domain`, `tags`, `sources`); методы и
свойства — заголовки `## ` внутри статьи интерфейса.
Тебя вызывают, чтобы основная модель не тратила контекст на поиск:
**вопрос для исследования придёт в промпте от вызывающего**. Прогони Grep/Read
по базе, прочитай нужную статью и верни сжатый ответ (интерфейс, сигнатура,
параметры, значения констант, источник).
## Когда это про тебя
- Нужна сигнатура метода (`SetSideParam`, `GetGabarit`, …) — Automation/COM, параметры, возврат.
- Нужны значения перечисления/констант (`Obj3dType`, `ksHoleTypeEnum`, `ST_MIX_*`, стили линий).
- Нужно найти интерфейс под задачу («чем/каким интерфейсом построить X»).
- Нужен паттерн «как через API сделать X» с цепочкой вызовов.
## Структура MD-базы `docs/Kompas3D_SDK/`
```
index.md — оглавление по 4 категориям со ссылками на статьи
interfaces/*.md — одна статья на интерфейс/тему; все методы и свойства как ## секции
enums/*.md — перечисления (пары «имя | значение | смысл»)
structures/*.md — структуры и параметрические интерфейсы
guides/*.md — концепции и руководства
resources/ — изображения (ссылки в статьях вида ../resources/имя.png)
```
Каждая статья начинается с YAML-фронтматтера: `type` (interface/enum/struct/guide),
`api` (api7/api5), `domain` (3d/2d/sketch/assembly/…), `tags`, `sources` (исходные `*.html`).
Имя файла статьи — имя интерфейса (`iapplication.md`, `ksbossextrusiondefinition.md`)
или читаемый слаг темы (`приложение.md`). Методы/свойства внутри — заголовки `## Имя - Описание`.
> База **хранится в репозитории** (канонический источник справки) — отдельная
> генерация не нужна.
## Инструменты (используй именно их, не веб)
- **Grep** по `docs/Kompas3D_SDK/` — ищи имя интерфейса/метода/свойства, русское
ключевое слово или тег. Имена методов — это заголовки `## SetSideParam - …`,
поэтому поиск по имени метода сразу ведёт в нужную статью.
- **Read** найденного `*.md` — статья интерфейса содержит все его методы/свойства,
блоки `Синтаксис Automation:`/`Синтаксис COM:` (в code-fence), параметры, примечания.
- `docs/Kompas3D_SDK/index.md` — оглавление по категориям, когда нужно осмотреть тему.
Полезные приёмы поиска:
- по перечислению: `Grep "ksMassUnitsEnum"` или загляни в `enums/`;
- фильтр по тегам в фронтматтере: `Grep "domain: \[.*3d"` , `Grep "type: enum"`;
- веер по многим интерфейсам сразу: `Grep "IPart7|IDocument3D|IPart"` по `interfaces/`.
Точные числовые значения констант при необходимости сверяй в заголовках SDK:
`C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK\Include\*.h` (например `ksConstants*.h`, `ldefin2d.h`).
## Важно — что в базе и чего нет
- База содержит **COM API7/API5** — то, что использует проект (файлы `iapplication*`,
`kspart*`, `ksmassinertiaparam*` и т.п.). Это твой основной источник.
- Кроссплатформенный Qt/C++ **KsAPI** (`ksapi_*`) в базу **не включён** — если задача
явно про KsAPI, скажи об этом (нужен отдельный источник).
## Правила
1. Не угадывай — находи через Grep/Read по `docs/Kompas3D_SDK/` и читай первоисточник.
2. Верни **сжатую выжимку**, а не дамп статьи:
- имя интерфейса и метода/свойства;
- синтаксис Automation (и COM, если важен порядок out-параметров);
- параметры (имя, тип, смысл) и возвращаемое значение;
- для enum/констант — пары «имя = значение» и их смысл;
- важные примечания (единицы измерения, побочные эффекты, версия КОМПАС);
- имя статьи / `sources` из фронтматтера как ссылку на источник.
3. Если у метода несколько перегрузок или связанных интерфейсов — перечисли релевантные.
4. Если в COM-interop имя отличается от справки (частый случай в этом проекте), отметь это
как вероятную тонкость и предложи свериться рефлексией по `libs/kompas-interop/*.dll`.
5. Только исследование и ответ — правок в код или документацию не делаешь.
## Пример задачи в промпте
«Нужна сигнатура и единицы измерения у метода расчёта МЦХ детали через API5 — что
возвращает, как задать мм/кг.» Или короче: «как построить массив по сетке (pattern)».
+138
View File
@@ -0,0 +1,138 @@
# AGENTS.md
This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
## Project goal
Build an **MCP (Model Context Protocol) server** that lets an LLM drive the CAD system **КОМПАС-3D** (ASCON). The server exposes КОМПАС operations (create/open documents, build 2D geometry, 3D parts and assemblies, read/write parameters, run macros) as MCP tools.
Authoritative references:
- **SDK knowledge base in this repo: `docs/Kompas3D_SDK/`** — clean Markdown, one article per COM interface, with YAML tags; search it with Grep/Read (see below). Committed to the repo (canonical), distilled from the КОМПАС SDK help. Prefer this over the web. For non-trivial lookups, dispatch the **`kompas-sdk-research`** subagent (Haiku) to save context.
- 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`
## Navigating the SDK docs (`docs/Kompas3D_SDK/`)
`docs/Kompas3D_SDK/` is a structured MD knowledge base distilled from the 26 000-page Help&Manual WebHelp export. One article per COM interface/topic, split into `interfaces/`, `enums/`, `structures/`, `guides/` (+ `resources/` images), each with YAML frontmatter (`type`, `api`, `domain`, `tags`, `sources`); methods/properties are `## ` headings inside the interface article. **Search it directly — do not browse the raw HTML:**
- **Grep** over `docs/Kompas3D_SDK/` for an interface/method/property name or Russian keyword (method names are `## SetSideParam - …` headings, so the name lands you in the right article).
- **Read** the matching `*.md` — the interface article holds all its members, `Синтаксис Automation:`/`Синтаксис COM:` blocks (in code fences), parameters, notes.
- `docs/Kompas3D_SDK/index.md` — table of contents by category. Filter by frontmatter tags, e.g. `Grep "type: enum"` or `Grep "domain: \[.*3d"`.
The base is committed to the repo (canonical) — no regeneration step. It covers the **COM API7/API5** reference this project uses (interfaces named `iapplication_*`, `idocuments_*`, …). The cross-platform Qt/C++ **KsAPI** flavour (`ksapi_*`, non-COM binding) is intentionally **excluded** from the base — ignore unless explicitly working with KsAPI.
## Current state
**Status:** v1 + v2 + STEP/assembly + direct B-rep edit + structural inspection + 2D drawings — implemented and working (full sketch→feature→inspect→STEP round-trip + `move_face` + `describe_model` validated end-to-end).
Stack: **.NET 8 (`net8.0-windows`, x64), C#**, MCP via the official `ModelContextProtocol` SDK over **stdio**. **83 MCP tools, 331 tests green (201 unit + 130 integration).**
Where to look (single source of truth — do **not** duplicate these lists here):
- **Full tool catalog** (by group, all 83) → [`README.md`](README.md) §«Инструменты».
- **Roadmap / what's already done** → [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §10.
- **Backlog / what's left** → [`docs/TODO.md`](docs/TODO.md) (canonical; top of «2D-ЧЕРТЁЖ» = next priority. Associative diametral/radial→circle binding (`associate` flag), sheet format (`drawing_set_sheet_format`), leaders (`drawing_add_leader`) done — next: bases, tolerances, arc/angular/rough binding; plus extra mate types, package E continuation).
- **Design decisions / caveats** → [`docs/OPEN_QUESTIONS.md`](docs/OPEN_QUESTIONS.md). Known caveat («Ревью v2»): boss/cut direction on a selected face depends on face-normal orientation — `forward` may need flipping; the agent picks via snapshot or `describe_face` normal.
- **Verified COM call-chains & gotchas** → «Key implementation facts» below + memory files (`kompas-*-api*.md`).
Principle: **MCP = translating SDK capabilities into general tools** (not task-specific). On top of MCP — skill **`.Codex/skills/kompas-3d/`** with a methodology (playbooks, heuristics, validated in `usecases/`). Layout: `usecases/` (in .gitignore) is the proving ground; proven techniques are promoted to the skill. A separate skill **`.Codex/skills/kompas-fdm-design/`** is a DFM methodology layer for FDM/FFF 3D-printing (overhang rules, wall thickness, teardrop holes, fits/clearances, orientation for strength, elephant foot, bosses/inserts/snap-fits) with a lightweight geometry audit using existing inspection tools; it works on top of `kompas-3d` (the build layer) and exports via `export_step` — no slicer integration.
**Delegation subagents** (`.Codex/agents/`, dispatched via the `Agent` tool to keep heavy work off Opus's context — system prompt lives in the agent definition, so pass only the variable part as the prompt):
- **`kompas-sdk-research`** (model: **Haiku**, read-only — `Glob`/`Grep`/`Read`): finds an interface/method/enum/constant signature in the `docs/Kompas3D_SDK/` MD knowledge base and returns a compressed summary. Dispatch it for any non-trivial SDK lookup instead of grepping the help yourself; a wrong answer is cheap — Opus re-verifies against `libs/kompas-interop/*.dll` by reflection.
- **`docs-maintainer`** (model: **Sonnet**, `Read`/`Edit`/`Write`/`Glob`/`Grep`): syncs `README.md`/`AGENTS.md`/`docs/ARCHITECTURE.md`/`docs/OPEN_QUESTIONS.md`/`docs/presentation.html` with code changes from a change summary you provide. Dispatch it for doc updates instead of editing docs by hand. (Both were skills before — converted to native subagents; the model split reflects task type: bounded retrieval → Haiku, judgement-heavy editing → Sonnet.)
Layout: `src/Kompas.Mcp.Core` (COM layer), `src/Kompas.Mcp.Host` (MCP stdio server + tools),
`tests/Kompas.Mcp.Tests` (unit + integration), `libs/kompas-interop/*.dll` (vendored КОМПАС interop
assemblies from SDK `Samples/Common`, referenced via `Directory.Build.props``KompasInteropDir`).
```powershell
dotnet build -c Release # build
dotnet test --filter "Category=Unit" # unit tests (no COM)
dotnet test --filter "Category=Integration" # integration (requires running КОМПАС)
dotnet run --project src/Kompas.Mcp.Host # start the MCP server (stdio)
```
## Key implementation facts (don't relearn)
- **All COM calls run on one dedicated STA thread** (`KompasDispatcher.InvokeAsync`); КОМПАС is single-instance STA. Services never touch COM off that thread.
- **Connection**: API5 (`KOMPAS.Application.5``KompasObject`) then `ksGetApplication7()``IApplication`; the API5 root is needed for `ksPart` 3D-building and `ksDocument3D` snapshots. API7 is used for app/documents, holes, assemblies, drawings, direct B-rep edit.
- **3D via API5 `ksPart`**: `NewEntity(o3d_*)` + matching definition; always check `entity.Create()` return. Entity codes: `o3d_sketch`/`o3d_bossExtrusion`/`o3d_cutExtrusion`/`o3d_bossRotated`/`o3d_fillet`/`o3d_chamfer`, `o3d_shellOperation=43`, `o3d_ribOperation=44`, `o3d_baseEvolution=45` (sweep), `o3d_baseLoft=30`, `o3d_planeOffset=14`, `o3d_meshCopy=35` (linear pattern), `o3d_circularCopy=36`, `o3d_mirrorOperation=48`, `o3d_mirrorAllOperation=49`, `o3d_incline=42` (draft), axes `o3d_axisOX/OY/OZ=71/72/73`. Definitions: `ksBossExtrusionDefinition`/`ksCutExtrusionDefinition`/`ksBossRotatedDefinition`/`ksFilletDefinition`/`ksChamferDefinition`/`ksShellDefinition`/`ksRibDefinition`/`ksBaseEvolutionDefinition`/`ksBaseLoftDefinition`/`ksPlaneOffsetDefinition`/`ksMeshCopyDefinition`/`ksCircularCopyDefinition`/`ksMirrorCopyDefinition`/`ksMirrorCopyAllDefinition`/`ksInclineDefinition`. Cut-through holes use `dtBoth` + `etThroughAll`.
- **Face/edge selection**: `ksPart.EntityCollection(o3d_face|o3d_edge)``SelectByPoint(x,y,z)` (world mm) → `GetByIndex(0)`; or by stable index from `list_faces`/`list_edges` (helpers `SelectFaceByIndex`/`SelectEdgeByIndex`, range-checked before mutation; by-index more reliable than by-point). Classify: `ksFaceDefinition.IsPlanar/IsCylinder/…` + `GetArea(ST_MIX_MM)`; `ksEdgeDefinition.IsLineSeg/IsCircle/IsArc/…` + `GetLength()`. Sketch axis = line with system style **3** (осевая).
- **МЦХ / mass props**: use **API5 `ksPart.CalcMassInertiaProperties(ST_MIX_MM|ST_MIX_KG)`**`ksMassInertiaParam` (`v`/`m`/`F`/`xc`/`yc`/`zc`), computed on demand. **Do NOT** use API7 `IMassInertiaParam7.Calculate()` — its `Actual` flag sticks after the first calc and won't refresh on API5 geometry changes (stale volume). Bounding box: `ksPart.GetGabarit(full:false, …)`.
- **Snapshot**: `ksDocument3D.SaveAsToRasterFormat(file, ksRasterFormatParam)` renders to a temp file (the in-memory `resultArrayBytes` stays empty when a filename is given); read bytes back. Return to MCP via `ImageContentBlock.FromBytes(bytes, mime)`**not** `Data = bytes` (Data holds base64 bytes). Use `model_snapshot` only for visually-spatial questions; **prefer `describe_model` first** (structural «passport» — bbox + МЦХ + bodies + topology + feature tree + variables, no image token cost).
- Logs go to **stderr** (stdout is the MCP channel). Integration tests reuse one КОМПАС via `KompasFixture`; artifacts land in gitignored `.scratch/`. All integration test classes inherit `IntegrationTestBase` (`IAsyncLifetime`) → `DocumentService.CloseAllAsync` after each test (prevents tab accumulation).
- **Feature tree API**: read via API5 `ksPart.GetFeature()``(ksFeature).SubFeatureCollection(true,false)``ksFeatureCollection`. Cast `(ksFeature)part` does NOT work (RCW QI returns null) — must use `GetFeature()`. `ksFeature.type` returns only coarse `o3d_entity` and does NOT distinguish operations; precise type and params come from `ksFeature.GetObject()``ksEntity.GetDefinition()` + the matching definition (`ksBossExtrusionDefinition.GetSideParam`, `ksFilletDefinition.radius`, `ksChamferDefinition.GetChamferParam`, …). Node names ("Элемент выдавливания:1") are localized by КОМПАС. Features registered by id in `_features` support patterns/mirror; helpers `RequireSketch`/`RequireFeature`.
- **Variables (API5)**: create/read via `ksPart.GetFeature().VariableCollection` (property on root ksFeature) — **NOT** `ksPart.VariableCollection()` (returns external-only). Expression is the leading field; value is derived. Apply via `ksPart.RebuildModel()` (check return); after rebuild the RCW variable is stale → re-read via a fresh collection (`ReadValueFresh`). Dependents recalculate automatically; deletion fails if dependents exist (`RemoveVariable` returns FALSE). **Geometry limitation:** variables drive geometry only in a parametric model (sketch dims linked to variable names); our sketches use literal coords → `set_variable` stores/computes the value but does NOT move geometry. Parametric sketches **unavailable via COM** (`ksCDimWithVariable` not constructible from external automation — see `docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md`; do not retry without new info).
- **Topology / measure API**: `ksFaceDefinition.EdgeCollection` / `GetCylinderParam` / `GetSurface().GetNormal` + `normalOrientation`; `ksEdgeDefinition.GetAdjacentFace(bool)` / `GetVertex(bool)``ksVertexDefinition.GetPoint`; bodies via `ksPart.BodyCollection()``ksBody` (`IsSolid` / `FaceCollection`); measurements via `ksPart.GetMeasurer()``ksMeasurer` (`SetObject1/2`, `unit=ST_MIX_MM`, `Calc`, `distance`/`MinDistance`/`angle` in degrees / `IsAngleValid`).
- **"STEP import without history"** detected structurally: `bodyCount > 0 && no formative features && features.Count <= bodyCount+1` (only origin + body). STEP with edits ("Смещённая плоскость" / "Разрезать" / "Переместить грани" / "Булева операция") already has history.
- **STEP import/export COM pattern** (verified): `IApplication.get_Converter((object)(int)ksConverterFromSTEP=-3)` (pass format code, not DLL path) → `IConverter.ConverterParameters(cmd)``IAdditionConvertParameters.Format=ksConverterFromSTEP``IKompasDocument3D1.ConvertFromAdditionFormat(path, prm)`. Export: `ConvertToAdditionFormat` (format codes AP203/AP214/AP242). Param co-classes (AdditionConvertParameters etc.) are NOT CoCreatable — only via converter factories. Assembly traversal (`list_components`): `IKompasDocument3D.TopPart → IPart7.Parts (IParts7)`. Extract component: `prm.NeedCreateComponentsFiles=true` (writes .m3d files next to STEP) + `IPart7.OpenSourceDocument`.
- **Direct B-rep face editing (`move_face`)** (verified): API7 face via `IPart7.FindObjectsByPoint(x,y,z,true)` → cast to `KompasAPI7.IFace`; containers via runtime COM-QI `(ISurfaceContainer)part`, `(IModelContainer)part`; `FaceMover` (SetFaces + Offset + Direction + Update) moves the face. distance>0 = outward (add material), <0 = inward. Works on parametric and imported B-rep. Full split-reposition workflow (SplitSolids/BodyRepositions) is driveable; only partly exposed as tools (`split_solid_by_plane`, `move_body`, `boolean_union`).
- **Forming ops (API5 definitions)**:
- `shell` (`ksShellDefinition`, o3d_shellOperation=43): `thickness` + `thinType` (bool, `= !outward`) + `FaceArray()` (open faces ≥1 by index). Transient RCWs intentionally not released (consistent with Fillet/Chamfer).
- `rib` (`ksRibDefinition`, =44): `SetSketch(sketch)``index=0`, `angle`, `side` (`left|right|up|down` → 0/1/2/3 via `SketchGeometry.RibSide()`); `SetThinParam(dtBoth, t/2, t/2)` if symmetric, else `(dtNormal, t, 0)`. Empirical: the rib contour must float in the gap (not touch the body) — КОМПАС extends the web automatically.
- `sweep` (`ksBaseEvolutionDefinition`, =45): `SetSketch(profile)``PathPartArray().Add(path)``sketchShiftType=0``SetThinParam(false)``Create()`. Profile & path on different (usually ⟂) planes; `profileSketchId != pathSketchId`.
- `loft` (`ksBaseLoftDefinition`, =30): `Sketchs().Add(each)``SetLoftParam(false,false,true)``SetThinParam(false)`. ≥2 closed sections on parallel planes — use `sketch_create_on_offset_plane` for non-base sections.
- offset plane (`sketch_create_on_offset_plane`, `ksPlaneOffsetDefinition`, o3d_planeOffset=14): `SetPlane(base)` + `offset` mm + `direction``Create()` → sketch on it (`OpenSketchOnOffsetPlaneAsync`).
- `draft` (`ksInclineDefinition`, o3d_incline=42 — API5 calls the op **Incline**, NOT Draft): `FaceArray()` (by index) + `SetPlane(neutral base plane)` + `angle` (degrees) + `direction`. **Empirical, opposite to SDK docs:** `direction=false`=expanding/outward (adds material), `true`=tapering/inward → code maps `def.direction = !outward`. Validate `0<angle<90`. (`o3d_DraftFromEdges=644` / `IDraftFromEdges` is a different op — not used.)
- **Patterns & mirror (API5)**: `linear_pattern` (`ksMeshCopyDefinition`, =35): `SetAxis1(axis)` + `SetCopyParamAlongAxis(true,0,count,step,false)` + `count2=1` (disables 2nd direction → 1D); features via `OperationArray()`. `circular_pattern` (`ksCircularCopyDefinition`, =36): `SetAxis(axis)`; `count1=1` (radial off), `count2=count` (ring), `step2=angle°` between neighbours, `factor2=false`, `inverce=reverse`; `GetOperationArray().Add(feature)`. `mirror_operation` (`ksMirrorCopyDefinition`, =48): `SetPlane(base)` + `GetOperationArray().Add(feature)`. `mirror_body` (`ksMirrorCopyAllDefinition`, =49): `SetPlane(base)`; `ChooseBodies()` casts to null in interop and is NOT needed — mirrors all bodies keeping the original (volume doubles). Empirical: `count` includes the original instance (count=3 → 3 instances). Axes: `CoordinateAxis{X,Y,Z}``o3d_axisOX/OY/OZ` (`Core/Modeling/CoordinateAxis.cs`, analogous to `BasePlane.cs`).
- **Hole ops (API7 only — `ksHoleDefinition` absent in API5 interop; `HoleService`)**: `HoleCore(ksHoleTypeEnum holeType, Action<IHole3D> configure)``configure` sets `HoleParameters` **after** `HoleType` is assigned (the type-specific sub-interface is inaccessible until the type is fixed). Placement shared: `IModelContainer`/`IHole3D`/`IHoleDisposal` + `Points3D`, direction chosen by volume delta, orphan rollback. None registered in `_features` → no id returned. `hole`=`ksHTBase`, configure=null. `hole_counterbore`=`ksHTCounterbore` + `(ISpotfacingHoleParameters)` (`SpotfacingDiameter`/`SpotfacingDepth`). `hole_countersink`=`ksHTCountersinking` + `(ICountersinkHoleParameters)` (`CountersinkType=ksCTDiameterAngle`, `CountersinkDiameter`/`Angle`). `hole_conic`=`ksHTConic` + `(IConicHoleParameters)` (`ConicType=ksCNAngle`, `ConicAngle`).
- **Assembly (API7, `AssemblyService`, namespace `Kompas.Mcp.Core.Assemblies`)**: `assembly_add_component``IParts7.AddFromFile(path, ExternalFile=true, Redraw=true)``IPart7.Placement` (`IPlacement3D`) → `SetOrigin(x,y,z)` (mm, assembly world CS) → `UpdatePlacement(true)``top.RebuildModel(true)`. **Empirical:** `UpdatePlacement` returns FALSE for a manually-positioned component (no mates) — NOT an error. Validate `DocumentType==ksDocumentAssembly` before touching `TopPart`; rollback via `IFeature7.Delete` + `RebuildModel`. `assembly_add_mate``top.MateConstraints` (`IMateConstraints3D`) → `Add(MateConstraintType)``BaseObject1/2` (faces via `top.FindObjectsByPoint(x,y,z,FirstLevel=false)`) → `ParamValue` (distance) → `Update()``RebuildModel(true)`; check `mate.Valid` (false → rollback `mate.Owner.Delete`). Types `coincidence`(mc_Coincidence=0) / `distance`(mc_Distance=5, value>0) verified live; `parallel`/`perpendicular`/`concentric`/`angle`/`tangency` — future.
- **Drawing (API7, `DrawingService`, namespace `Kompas.Mcp.Core.Drawings`)** — entry via `IKompasDocument2D`; requires an active drawing doc (`DocumentType==ksDocumentDrawing`). All coords are **view-local** (mm) unless noted. Model file must be saved before placing views.
- `drawing_create_standard_views`: `doc2d.ViewsAndLayersManager.Views.AddStandartViews(path, "#Спереди", projTypes, x, y, scale, dx=20, dy=20)` where `projTypes=object[]{1,3,5}` (Front/Up/Left as SAFEARRAY VT_I4). Success: `created==3`; content check: sum of new views' `IView.ObjectCount` > 0 else rollback `IView.Delete`. Returns `ViewNumbers` (the `IView.Number` values — address views by these when placing annotations).
- `drawing_fill_title_block`: `doc2d.LayoutSheets.ItemByNumber[1].Stamp` (`IStamp`) → `stamp.Text[columnId].Str = text` (indexed property; `IText.Str` overwrites, no Clear needed) → `stamp.Update()`. Fields→columns (`ksStampEnum`): Name=1, Designation=2, Material=3. Non-transactional (all cells → single `Update`).
- **Dimensions go into `(ISymbols2DContainer)view`, NOT the sheet, and are NOT counted in `IView.ObjectCount`** (that counts geometry in `IDrawingContainer`) — verify placement via the container's `*.Count`. Common flow: `Add()` → set coords → `AutoNominalValue=true``Update()` → check `Valid` → read `((IDimensionText)dim).NominalValue`; rollback `dim.Delete()` on FALSE/invalid/zero. Leader/angle in **radians** (`DimensionAngles.ToRadians`). Free placement = set coords directly; **associative** (diametral/radial only) = set `BaseObject` to a projected circle → value read from geometry (see below).
- linear (`ILineDimension`): `X1,Y1,X2,Y2` (extension pts) + `X3,Y3` (dim line) + `Orientation` (`DimensionOrientation{Horizontal,Vertical,Parallel}``ksLinDParallel=0`/`Horizontal=1`/`Vertical=2`; parallel needs no explicit Angle).
- diametral (`IDiametralDimension`): `Xc,Yc,Radius` + `Angle`; `NominalValue` = 2·Radius.
- radial (`IRadialDimension`): `Xc,Yc,Radius` + `Angle`, `DimensionType=true`; **`NominalValue` = Radius, NOT diameter** — contrary to SDK docs, confirmed by spike.
- **associative** diametral/radial (`associate=true` flag): instead of coords, find a projected circle in `(IDrawingContainer)view.Circles` by center+radius key (`CircularObjectMatch.SelectMatchIndex`, tol 1 mm; throws on none/ambiguous; concentric disambiguated by radius), set `dim.BaseObject = circle` (`_Circle` implements `IDrawingObject`) → `NominalValue` read from geometry. `RequireViewContainers` gives both QIs; free path stays on `RequireSymbols2DContainer`. Arc/angular/rough binding — not yet (own spike needed; `ILineDimension` has no `BaseObject`).
- angular (`IAngleDimension`, `AngleDimensions.Add(ksDrADimension=10)`): vertex `Xc,Yc` + side pts `X1,Y1`/`X2,Y2` + arc-position `X3,Y3` (positions the arc only, does NOT pick the angle); measured angle chosen by `DimensionType` = `AngleDimensionType{Min,Max,More}` (on rays 0°/45° → min=45°/max=135° supplement/more=315° reflex). `NominalValue` in degrees.
- `drawing_add_rough` (`Roughs.Add()`/`IRough`: `BranchX0/Y0`, `Angle`) + `(IRoughParams)rough` QI: `SignType` = `RoughSignType{NoProcessing,DeleteMaterial,WithoutDeleteMaterial}`, value (Ra/Rz) = `RoughParamText.Str`.
- `drawing_add_text`**text lives in `IDrawingContainer`, NOT `ISymbols2DContainer`, and NOT in `IView.ObjectCount`**: `(IDrawingContainer)view.DrawingTexts.Add()`/`IDrawingText` (`X/Y/Angle`) + `(IText)dt.Str` = text; count via `DrawingTexts.Count`. Do NOT set `Height` (that's block height, not font).
- `drawing_set_technical_requirements`**document-level**: `(IDrawingDocument)doc.TechnicalDemand`/`ITechnicalDemand`: `td.Text.Str = text``td.Update()` (`IsCreated` False→True on first set; overwrites; `\n` multiline).
- `DrawingAnnotationResult{Value(read-back), ViewNumber}` is the shared result for rough/text.
- `drawing_add_leader``ISymbols2DContainer.Leaders.Add(ksDrLeader)``IBaseLeader`. **КРИТИЧЕСКИЙ ПОРЯДОК (спайк):** новая выноска имеет 0 ответвлений → `(IBranchs)bl.AddBranchByPoint(0,x,y)` (остриё) ДО `SetBranchTextPosition(textX,textY)`/`Update`, иначе КОМПАС падает `RPC_E_SERVERFAULT`. Текст — `(ILeader)bl.TextOnShelf.Str`; `ShelfDirection` (enum `ShelfDirection{Auto,Right,Left,Up,Down}`, Auto = не задавать). `AddBranchByPoint`/`SetBranchTextPosition` возвращают bool — проверять. Результат — общий `DrawingAnnotationResult`.
- `drawing_set_sheet_format``RequireLayoutSheet(n).Format` (`ISheetFormat`): `Format`=`ksDocumentFormatEnum` (`PaperFormat{A0..A5,User}`+`PaperFormats.Parse/ToKompas/FromKompas`), standard → set `VerticalOrientation=!landscape` (W/H auto-computed from enum+orientation, e.g. A3 landscape→420×297); **User → set `FormatWidth/Height` only, КОМПАС auto-derives `VerticalOrientation` from W/H and ignores the flag, never swaps W/H (spike)**`sheet.Update()`. New drawing defaults A4 portrait. `ValidateFormatDimensions`: User needs W/H>0, standard forbids W/H (must be 0).
- **Richer sketch primitives (API5 `ksDocument2D` wrappers)**: `ksArcBy3Points`; `ksArcByAngle` (centre/radius/start-end angles in degrees + counterClockwise flag); `ksEllipse` via `ksEllipseParam` (`KompasObject.GetParamStruct(ko_EllipseParam=22)`; **property names are `A`/`B` UPPERCASE in the interop**); `ksRegularPolygon` via `ksRegularPolygonParam` (`ko_RegularPolygonParam=92`; `describe = !inscribed`); NURBS spline via `ksNurbs(order=4)` + `ksNurbsPoint` loop + `ksEndObj`; `ksPoint`. Param structs released after use. `PartModeler` is partial: `.cs` (registry/helpers/`NewParam<T>`/reset), `.Sketch.cs` (2D primitives), `.Features.cs` (extrude/revolve/fillet/chamfer). Static `SketchGeometry` (`Core/Modeling`) holds enum maps + validators (`RequirePositive`, `RequireVertexCount`, `RequirePoints`, `RequireMin`). Point lists use `record SketchPoint(X, Y)` (JSON names `x`/`y`).
## КОМПАС-3D API architecture (the critical context)
КОМПАС-3D is automated via a **COM Automation API**, Windows-only. КОМПАС-3D **must be installed and running/launchable** on the same machine — the MCP server is a COM client, not a standalone CAD engine. There are **two coexisting API generations**:
| | Entry point | Namespace (C#) | Style | Use when |
|---|---|---|---|---|
| **API5** (legacy) | `KompasObject` | `Kompas6API5` | procedural, flat | older features, 2D primitives, bootstrapping |
| **API7** (modern, preferred) | `IApplication` / `_Application` | `KompasAPI7` | OOP, interface-based | everything new — documents, 3D, parameters |
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();` (via `KOMPAS.Application.7` you already hold `IApplication`).
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]`). For an MCP server we want the **opposite direction**: a standalone *external automation client* that connects 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)
Under `C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK`:
- `lib\*.tlb` — COM type libraries to reference / generate interop from: `kAPI5.tlb`, `kAPI7.tlb`, `ksConstants.tlb`, `ksConstants3D.tlb`, `kAPI2D5COM.tlb`, `kAPI3D5COM.tlb`.
- `lib64\` — 64-bit import libs (`kAPI7.lib`, `kAPI5.lib`, …) and `.a` for C++/Builder.
- `Include\` — C++/Pascal headers (`Ks_TLB.h`, `kAPI2D5COM.h`, `LDefin2D.pas`, …).
- `KsAPI\` — the **KsAPI** (Qt/C++ cross-platform flavour): `Include\KsAPI.h`, `ksConstants*.h`, `Lib64\ksAPI.lib`, plus `Help\С чего начать.pdf` and a Linux/Debian 12 build guide.
- `Samples\` — zipped examples per language: `CSharp.zip`, `C++.zip`, `Pascal.zip`, `Basic.zip`. Inside `CSharp.zip`, the `Step1``Step12` and `Step2_API7_2D` / `Step2_API7_3D` projects are the progressive tutorial; `Gayka`, `SlideWrk`, `EventsAuto` are larger feature demos.
- `Help\KOMPAS_SDK_ru-RU.zip` and `KsAPI\Help\KsAPI_Help.zip` — offline copy of the docs.
To inspect a sample without unpacking the whole archive: `unzip -p "<path>\Samples\CSharp.zip" "Automation/Step2_API7_3D/Step2_API7_3D.cs"`. Note 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 source samples are CP1251. New project files should be UTF-8.
- **COM lifetime**: release COM objects (`Marshal.ReleaseComObject`) / scope them; a leaked reference keeps the КОМПАС process alive.
- **API choice**: prefer API7 for new tool implementations; drop to API5 only for things API7 doesn't expose.
+2 -2
View File
@@ -27,8 +27,8 @@ LLM набор инструментов для создания документ
dotnet build -c Release
# сервер (stdio):
dotnet run --project src/Kompas.Mcp.Host -c Release
# или собранный exe:
src/Kompas.Mcp.Host/bin/Release/net8.0-windows/kompas-mcp.exe
# или собранный exe (платформа x64 — из Directory.Build.props):
src/Kompas.Mcp.Host/bin/x64/Release/net8.0-windows/kompas-mcp.exe
```
### Подключение к MCP-клиенту (stdio)
+7 -2
View File
@@ -321,10 +321,15 @@ document_create(part)
## 8. Сборка и запуск
```powershell
dotnet build -c Release -r win-x64 # сборка
# → kompas-mcp.exe (self-contained, win-x64)
dotnet build -c Release # сборка
# → src/Kompas.Mcp.Host/bin/x64/Release/net8.0-windows/kompas-mcp.exe
```
Платформа `x64` задаётся в `Directory.Build.props` (`Platforms`/`PlatformTarget`) — она обязательна
для COM-активации 64-битного КОМПАС, отдельный `-r win-x64` указывать не нужно. Сборка
framework-dependent: рядом с `.exe` лежат зависимости и interop-сборки КОМПАС, требуется
установленный .NET 8 Runtime.
Регистрация stdio-сервера у клиента (пример для конфигурации Claude Desktop):
```json
+1 -1
View File
@@ -91,7 +91,7 @@ COM ↔ STA ↔ MCP работает. Затем наращиваем инстр
### Фаза 9 — Качество и поставка
- Unit-тесты (маппинг, валидация, форматирование); интеграционные (`[Trait("Category","Integration")]`, гейтятся).
- Трансляция ошибок COM (`ksGetLastError`/`IApplication.KompasError`) в структурированные MCP-ошибки.
- Сборка `kompas-mcp.exe` (`dotnet publish -c Release -r win-x64`), регистрация stdio-сервера в конфиге клиента.
- Сборка `kompas-mcp.exe` (`dotnet build -c Release`; платформа x64 — из `Directory.Build.props`), регистрация stdio-сервера в конфиге клиента.
- Escape-hatch `run_kompas_command` (опц.).
---
+24
View File
@@ -235,3 +235,27 @@ stateful-сессии? Пока полагаемся на последовате
**Решено.** Новый инструмент `drawing_add_leader(x,y, textX,textY, text, shelfDirection, viewNumber)` — ставит линию-выноску с надписью на полке на виде активного чертежа. Паттерн API7: `ISymbols2DContainer.Leaders.Add(ksDrLeader)``IBaseLeader``(IBranchs)bl.AddBranchByPoint(0,x,y)` (остриё, ответвление ответвлений — обязательно до `Update`, иначе `RPC_E_SERVERFAULT`) → `SetBranchTextPosition(textX,textY)``(ILeader)bl.TextOnShelf.Str = text` → опционально `ShelfDirection``Update()``Valid`. Новый enum `ShelfDirection {Auto,Right,Left,Up,Down}` + `ShelfDirections.Parse/ToKompas` в `src/Kompas.Mcp.Core/Drawings/ShelfDirection.cs`; переиспользует `DrawingAnnotationResult { Value, ViewNumber }`. +13 unit-тестов (`ShelfDirections.Parse`) + 10 интеграционных (`DrawingLeaderTests`, включая параметризацию направлений полки). Итог: **83 инструмента, 331 тест (201 unit + 130 integration).**
Нереализовано: обозначения баз (`Bases`), допуски формы (`Tolerances`); привязка к дуге (`Arcs`), ассоциативный угловой размер, ассоциативная шероховатость (`IRough.BaseObject`); рамка по ГОСТ-стилю; специальные выноски (позиция, клеймо, маркер).
### ⚠️ КОМПАС-3D v25 vs v24 — разведка для будущего апгрейда
**Контекст.** Проект таргетирует установленную локально КОМПАС-3D v24 Home (SDK в `C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK`). `docs/Kompas3D_SDK/` (MD-база в репо) дистиллирована из справки v22 — новых интерфейсов v25 там нет и не появится без отдельной работы. Разведка проведена по официальным веб-источникам ASCON (v25 локально не установлена).
**Что нового в v25 (кратко, https://kompas.ru/kompas-3d/v25/, https://habr.com/ru/companies/ascon/news/1056484/):**
- Нативная версия для Linux (Альт 11.0, РЕД ОС 8.0, Astra Linux SE 1.8).
- 3D: «Создать вариант детализации» (упрощённые заменители в больших сборках), «Глубина проецирования» на ассоциативных видах, команда «Рельеф» (надписи/логотипы как выступ/гравировка), групповой выбор кривых/граней, несколько отверстий одной операцией.
- Поверхностное моделирование: эквидистанта вдоль нескольких граней, команда «Средняя линия», расширена «Поверхность скругления», сегментация полигональных объектов (реверс-инжиниринг: авто-разбиение сканов на плоскости/цилиндры/сферы/конусы/торусы).
- Импорт/экспорт: собственные конвертеры прямого чтения UGS/NX, ProE/Creo, SolidWorks, Inventor, CATIA V5, Solid Edge (плюс DXF/DWG).
- Чертежи/сборки: «Симметрия объектов», линейные размеры с выносными линиями касательными к окружностям, новые способы имитации движения компонентов сборки с контролем соударений.
- Новое приложение «Эргономика: Манекены»; доработки в специализированных приложениях (Композиты, Валы и передачи, Раскрой, Разъёмные соединения, строительная конфигурация — P&ID и др.) — вне scope MCP-сервера.
**Что нового в SDK / COM Automation API7 v25 (https://help.ascon.ru/KOMPAS_SDK/25/ru-RU/new_intrfs_v25.html, new_methods_v25.html) — потенциально релевантно для kompas3d-mcp.** Новые интерфейсы-кандидаты для будущих MCP-инструментов:
- `ICheckGeometry`/`ICheckGeometries`/`ICheckGeometryResult` — программная проверка корректности геометрии (кандидат для расширения `validate_part`).
- `ICollision`/`ICollisions`/`ICalculateCollisionsResult` — обнаружение пересечений/соударений объектов (новый класс проверок для сборок — сейчас в проекте отсутствует).
- `IFaceReplacer`/`IFaceReplacers`, `IFaceResizer`/`IFaceResizers` — замена/изменение размера грани (дополняет текущий `move_face`).
- `IMiddleLine`/`IMiddleLines` — поверхностная операция «средняя линия».
- `IArrayConstraint`, `ILinearArrayConstraint`, `ICircularArrayConstraint` — ограничения параметрических массивов объектов (2D/3D).
- `IDeformationManager`/`IDeformationObject` — деформация 3D-объектов.
- `IPart7.SaveModifiedPartAs` — сохранение изменённой вставки компонента сборки отдельным файлом.
- `ISpecificationExportParameters` / `ISpecification*.Export` — программный экспорт спецификаций.
- Точечные добавки: `IDrawingDocument.GetZoneByPoint/GetSheetNumberByPoint/SetCurrentModel`, `IDocuments.GetDocumentTypeByName`, `IStamp.IsCellPresent`, `IThread.GetLimitPoints`, `ITolerance`/`ITolerance3D` (доп. знаки допусков), `IApplicationDialogs` (ChoiceDocument/ChoiceTolerance/ReadPassword).
**Вывод / на проработку:** решения о переходе на v25 нет. Если оно будет принято — нужно либо доснять `docs/Kompas3D_SDK/` под v25, либо верифицировать эти интерфейсы напрямую рефлексией по новым interop-сборкам (тот же принцип «Haiku предлагает → Opus перепроверяет по DLL», что и сейчас). Приоритетные кандидаты: `ICheckGeometry` (валидация геометрии), `ICollision(s)` (проверка столкновений в сборке), `IFaceReplacer`/`IFaceResizer` (расширение прямого редактирования B-rep).
@@ -0,0 +1,198 @@
# Agent CAD Tool Contract Catalog Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Создать полный агент-ориентированный каталог внешних MCP-методов КОМПАС-3D, включающий реализованные и необходимые нереализованные операции, оценку полноты сквозных сценариев и приоритизированные пробелы.
**Architecture:** Итоговый документ является нормативной картой внешнего контракта, а не описанием реализации. Текущий код Host служит источником истины для реализованных методов; желаемый контракт формируется по симметрии `create → inspect → update → delete`, сквозным CAD-сценариям и проверке технической реалистичности без публикации SDK-деталей.
**Tech Stack:** Markdown, PowerShell, ripgrep, C# attributes `[McpServerTool]`, локальная документация проекта.
## Global Constraints
- Итоговый файл: `docs/AGENT_CAD_TOOL_CATALOG.md`.
- В итоговом документе не должно быть COM-интерфейсов, API5/API7 и иных деталей SDK.
- Все существующие MCP-инструменты должны быть представлены ровно по одному разу.
- Нереализованные методы описываются как общий внешний CAD-контракт, а не как задача-специфичные workflow.
- Статусы: `✅ реализован`, `🟡 частично`, `⬜ не реализован`, `⛔ ограничен платформой`.
- Необходимость: `Core`, `Advanced`, `Optional`; приоритет пробелов: `P0`, `P1`, `P2`.
- Нельзя изменять существующие незакоммиченные пользовательские правки вне создаваемого каталога.
---
### Task 1: Инвентаризация реализованного внешнего контракта
**Files:**
- Read: `src/Kompas.Mcp.Host/Tools/*.cs`
- Read: `README.md`
- Read: `docs/ARCHITECTURE.md`
- Create: `docs/AGENT_CAD_TOOL_CATALOG.md`
**Interfaces:**
- Consumes: имена и описания методов из атрибутов `[McpServerTool(Name = "...")]` и `[Description("...")]`.
- Produces: доменные таблицы, в которых каждый реально зарегистрированный MCP-метод встречается ровно один раз.
- [ ] **Step 1: Получить машинный список имён методов**
Run:
```powershell
rg -o 'McpServerTool\(Name = "[^"]+"' src/Kompas.Mcp.Host/Tools | Sort-Object
```
Expected: список всех имён внешних MCP-методов из Host без зависимости от потенциально устаревшего счётчика README.
- [ ] **Step 2: Сверить количество и уникальность имён**
Run:
```powershell
$names = rg -o 'McpServerTool\(Name = "[^"]+"' src/Kompas.Mcp.Host/Tools | ForEach-Object { if ($_ -match 'Name = "([^"]+)"') { $Matches[1] } }
"total=$($names.Count) unique=$(@($names | Sort-Object -Unique).Count)"
```
Expected: `total` равно `unique`; текущее ожидаемое значение по README — 83, но источником истины остаётся фактический Host.
- [ ] **Step 3: Создать каркас каталога и внести реализованные методы**
Create `docs/AGENT_CAD_TOOL_CATALOG.md` with:
```markdown
# Каталог внешнего CAD-контракта для агента
## Назначение и критерий полноты
## Легенда
## Покрытие сквозных сценариев
## Методы внешнего контракта
### Сессия и документы
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
```
Repeat the same table header for every domain from the approved design. Add every extracted method once, using its public behavior rather than implementation details.
- [ ] **Step 4: Проверить, что все реализованные методы попали в каталог**
Run:
```powershell
$source = rg -o 'McpServerTool\(Name = "[^"]+"' src/Kompas.Mcp.Host/Tools | ForEach-Object { if ($_ -match 'Name = "([^"]+)"') { $Matches[1] } } | Sort-Object -Unique
$catalog = rg -o '`[a-z][a-z0-9_]+`' docs/AGENT_CAD_TOOL_CATALOG.md | ForEach-Object { $_.Trim('`') } | Sort-Object -Unique
Compare-Object $source $catalog | Where-Object SideIndicator -eq '<='
```
Expected: no output.
### Task 2: Спроектировать недостающий агентский контракт
**Files:**
- Modify: `docs/AGENT_CAD_TOOL_CATALOG.md`
- Read: `docs/TODO.md`
- Read: `docs/OPEN_QUESTIONS.md`
- Read: `docs/Kompas3D_SDK/` only for internal feasibility checks
**Interfaces:**
- Consumes: реализованный каталог Task 1 и критерии полноты из дизайн-спецификации.
- Produces: полный целевой контракт с отсутствующими, частичными и платформенно ограниченными методами.
- [ ] **Step 1: Проверить симметрию каждого мутирующего семейства**
For every domain, explicitly check whether an agent can:
```text
list/describe → create → update/transform → delete → validate
```
Add a row for every missing externally observable capability. Use `🟡 частично` when an existing method covers only part of the target behavior; do not invent a second row if an extension of the existing contract is clearer.
- [ ] **Step 2: Проверить адресуемость и устойчивость ссылок**
Add required contract methods for objects that are created but cannot later be found, inspected, changed or deleted. Cover at least documents, sketch entities, features, bodies, vertices, components, mates, drawing views and drawing annotations.
- [ ] **Step 3: Проверить замкнутость пяти сквозных сценариев**
For each scenario from the approved design, list stages in the matrix and mark:
```text
полный | частичный | неполный
```
A scenario is `полный` only if the agent can inspect initial state, perform the mutation, verify the result, save it and recover from an incorrect mutation.
- [ ] **Step 4: Проверить реалистичность спорных методов**
Search the local SDK knowledge base only when feasibility is unclear. If reliable external behavior cannot be confirmed, mark the catalog row `⛔ ограничен платформой` or state that a technical spike is required. Do not copy SDK symbols or call chains into the catalog.
- [ ] **Step 5: Добавить сводный приоритет пробелов**
Add three ordered subsections:
```markdown
### P0 — замыкание автономного цикла
### P1 — типовые профессиональные сценарии
### P2 — расширение охвата
```
Every item in these lists must reference a method already present in a domain table.
### Task 3: Проверка качества и передача результата
**Files:**
- Verify: `docs/AGENT_CAD_TOOL_CATALOG.md`
- Verify: `src/Kompas.Mcp.Host/Tools/*.cs`
**Interfaces:**
- Consumes: completed catalog from Tasks 12.
- Produces: internally consistent Markdown document with evidence-backed coverage claims.
- [ ] **Step 1: Повторить автоматическую сверку реализованных имён**
Run the `Compare-Object` command from Task 1 Step 4.
Expected: no missing source methods.
- [ ] **Step 2: Проверить дубликаты строк методов**
Run:
```powershell
$rows = Select-String -Path docs/AGENT_CAD_TOOL_CATALOG.md -Pattern '^\| `([a-z][a-z0-9_]+)` \|' | ForEach-Object { $_.Matches[0].Groups[1].Value }
$rows | Group-Object | Where-Object Count -gt 1 | Select-Object Name, Count
```
Expected: no output, except deliberate method-family extension rows must instead be consolidated into one row.
- [ ] **Step 3: Проверить отсутствие внутренних SDK-деталей**
Run:
```powershell
rg -n 'API5|API7|COM|I[A-Z][A-Za-z0-9]+|ks[A-Z][A-Za-z0-9]+' docs/AGENT_CAD_TOOL_CATALOG.md
```
Expected: no implementation references; ordinary Russian words that accidentally match the expression are reviewed manually.
- [ ] **Step 4: Проверить Markdown и пробельные ошибки**
Run:
```powershell
git diff --check -- docs/AGENT_CAD_TOOL_CATALOG.md
```
Expected: exit code 0 and no output.
- [ ] **Step 5: Проверить итоговую полноту вручную**
Confirm all acceptance criteria from `docs/superpowers/specs/2026-07-17-agent-cad-tool-contract-catalog-design.md`, then report:
```text
implemented methods / partial methods / missing methods / platform-limited methods
P0 / P1 / P2 gaps
scenario coverage: full / partial / incomplete
```
@@ -83,6 +83,16 @@ public sealed class VariableService
return RequireVariable(vc, name).value;
}, ct);
/// <summary>Заменить комментарий (note) существующей переменной.</summary>
public Task SetVariableNoteAsync(string name, string note, CancellationToken ct = default)
=> _dispatcher.InvokeAsync(() =>
{
RequireName(name);
var (_, vc) = RootVariables();
var v = RequireVariable(vc, name);
v.note = note;
}, ct);
/// <summary>Перечитать значение переменной из свежей коллекции (после RebuildModel оно пересчитано).</summary>
private double ReadValueFresh(string name)
{
@@ -277,6 +277,7 @@ public sealed class ModelInspectionService
Value = ComHelper.SafeNum(() => v.value),
External = ComHelper.SafeBool(() => v.external),
Information = ComHelper.SafeBool(() => v.Information),
Note = ComHelper.SafeStr(() => v.note),
});
}
return list;
@@ -16,4 +16,7 @@ public sealed record VariableInfo
/// <summary>Информационная переменная (вычисляется, не задаёт геометрию).</summary>
public required bool Information { get; init; }
/// <summary>Комментарий к переменной (описание назначения).</summary>
public string Note { get; init; } = "";
}
+2 -1
View File
@@ -58,7 +58,8 @@ public sealed class InspectionTools(KompasSession session, ModelInspectionServic
var lines = vs.Select(v =>
{
var flags = (v.External ? " [внешняя]" : "") + (v.Information ? " [инфо]" : "");
return Inv($" {v.Name} = {v.Expression} (= {v.Value:G}){flags}");
var notePart = string.IsNullOrWhiteSpace(v.Note) ? "" : $" — {v.Note}";
return Inv($" {v.Name} = {v.Expression} (= {v.Value:G}){flags}{notePart}");
});
return $"Переменных: {vs.Count}\n" + string.Join("\n", lines);
}
@@ -33,6 +33,17 @@ public sealed class VariableTools(KompasSession session, VariableService variabl
return $"Переменная '{name}' = «{expression}» → {v}.";
}
[McpServerTool(Name = "set_variable_note")]
[Description("Заменить комментарий (note) существующей переменной модели. name — имя переменной, note — новый текст комментария.")]
public async Task<string> SetVariableNote(
string name,
[Description("Новый текст комментария")] string note)
{
await session.ConnectAsync();
await variables.SetVariableNoteAsync(name, note);
return $"Комментарий переменной '{name}' обновлён.";
}
[McpServerTool(Name = "delete_variable")]
[Description("Удалить переменную модели по имени. Нельзя удалить переменную, на которую ссылаются другие (сначала удалите зависимые).")]
public async Task<string> DeleteVariable(string name)
@@ -71,4 +71,35 @@ public sealed class VariableTests : IntegrationTestBase
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Variable_set_note_and_list_shows_note()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
await _modeler.AddRectangleAsync(s, 0, 0, 20, 20);
await _modeler.CloseSketchAsync(s);
await _modeler.ExtrudeAsync(s, depth: 10);
// Create variable without note
await _vars.CreateVariableAsync("t", 5);
var list0 = await _inspect.ListVariablesAsync();
var v0 = list0.Single(v => v.Name == "t");
Assert.Equal("", v0.Note);
// Set note
await _vars.SetVariableNoteAsync("t", "wall thickness, mm");
var list1 = await _inspect.ListVariablesAsync();
var v1 = list1.Single(v => v.Name == "t");
Assert.Equal("wall thickness, mm", v1.Note);
// Overwrite note
await _vars.SetVariableNoteAsync("t", "thickness of base plate, mm");
var list2 = await _inspect.ListVariablesAsync();
Assert.Equal("thickness of base plate, mm", list2.Single(v => v.Name == "t").Note);
}
finally { await _docs.CloseAsync(save: false); }
}
}