diff --git a/docs/superpowers/NEXT-SESSION.md b/docs/superpowers/NEXT-SESSION.md index f91f9ae..cdef269 100644 --- a/docs/superpowers/NEXT-SESSION.md +++ b/docs/superpowers/NEXT-SESSION.md @@ -4,173 +4,113 @@ --- -Продолжаем разработку MCP-сервера КОМПАС-3D (kompas3d-mcp). Работай автономно, -с коммитами и пушами в `main`; используй Codex для ревью каждой реализованной фичи. +Продолжаем разработку MCP-сервера КОМПАС-3D (kompas3d-mcp). Работай автономно, с коммитами и +пушами в `main`; используй Codex для ревью КАЖДОЙ реализованной фичи (спека и реализации). КОМПАС-3D должен быть запущен (нужен для интеграционных тестов). -**Фокус этой сессии — два новых крупных класса: СБОРКИ и 2D-ЧЕРТЁЖ.** До сих пор сделана -только геометрия ДЕТАЛИ (она близка к насыщению). Сборки и чертёж — самый ценный -нереализованный функционал. Начни со СБОРОК (тестируются объёмом/габаритом/числом компонентов), -затем ЧЕРТЁЖ. +**Фокус — продолжать ВЕХУ 2D-ЧЕРТЁЖ** (самый ценный развивающийся класс). Деталь и сборки близки +к насыщению. Следующий инкремент — **радиальный/угловой размер** ИЛИ **рамка/формат листа** (см. +«Следующий инкремент»). -## Текущее состояние (main, синхронизирован с origin) -- 76 MCP-инструментов, 218 тестов зелёных (141 unit + 77 integration). -- **ВЕХА 2D-ЧЕРТЁЖ: 4 инкремента готовы.** (1) `drawing_create_standard_views` (возвращает - `ViewNumbers`). (2) `drawing_fill_title_block` — основная надпись. (3) `drawing_add_linear_dimension` - — линейный размер. (4) `drawing_add_diametral_dimension(xc,yc,radius,angle°,viewNumber)` — - диаметральный размер (Ø) через `(ISymbols2DContainer)view.DiametralDimensions.Add` → `Xc/Yc/Radius/ - Angle(рад)` → `Update` → `NominalValue`=2R. Общий хелпер `RequireSymbols2DContainer(viewNumber)` для - всех размеров. Размеры — в `ISymbols2DContainer` (QI от вида), НЕ в `IView.ObjectCount`. Координаты — - локальная СК вида. Память: `kompas-drawing-api7`. **СЛЕДУЮЩЕЕ — инкремент 5: радиальный - (`RadialDimensions`, есть ветви) / угловой (`AngleDimensions`) размер** (те же `ISymbols2DContainer`; - спайк) ИЛИ рамка/формат листа (`ILayoutSheet.Format`/`SheetFormat` — проще, без спайка). -- **ВЕХА 2 (2D-ЧЕРТЁЖ) НАЧАТА:** `drawing_create_standard_views(partFilePath, scale, x, y)` СДЕЛАН - (инкремент 1) — стандартные ассоциативные виды (спереди/сверху/слева) детали/сборки на активном - чертеже (API7, `DrawingService`, namespace `Kompas.Mcp.Core.Drawings`). Workflow: - `doc2d.ViewsAndLayersManager.Views.AddStandartViews(path, "#Спереди", object[]{1,3,5}, x, y, scale, - 20, 20)`. Эмпирика: `object[]`→SAFEARRAY VT_I4 ОК; новый чертёж стартует с Count=1 (системный вид), - 3 проекции → Count=4; ObjectCount>0 сразу (rebuild не нужен); проверка `created==3` + непустота по - новым видам (разница `IView.Number`) + откат `IView.Delete`. Спек: - `2026-05-27-drawing-standard-views-design.md`. **СЛЕДУЮЩЕЕ — инкремент 2 чертежа: оформление - (размеры/обозначения на видах, рамка, основная надпись).** -- **СБОРКИ: инкременты 1 и 2 СДЕЛАНЫ** (API7, `AssemblyService`, namespace `Kompas.Mcp.Core.Assemblies`): - - `assembly_add_component(filePath, x, y, z)` — вставка детали/подсборки из `.m3d`/`.a3d` с позицией. - Workflow: `IParts7.AddFromFile(path,true,true)` → `part.Placement.SetOrigin(x,y,z)` → - `UpdatePlacement(true)` → `top.RebuildModel(true)`. Эмпирика: `UpdatePlacement`=FALSE для вручную - позиционируемого компонента — НЕ ошибка; позицию применяет SetOrigin+RebuildModel; разфиксация - первого компонента НЕ нужна. - - `assembly_add_mate(mateType, x1,y1,z1, x2,y2,z2, value)` — сопряжение граней двух компонентов. - Workflow: `(IMateConstraints3D)top.MateConstraints` → `Add(MateConstraintType)` → `BaseObject1/2` - (грани через `top.FindObjectsByPoint(x,y,z,FirstLevel=false)`) → `ParamValue` (distance) → - `Update()` → `RebuildModel(true)` → проверка `mate.Valid` (false→ошибка+откат). Типы: `coincidence`, - `distance` (value>0). Решатель может двигать любой компонент → тест по ширине габарита. - - Спеки: `2026-05-27-assembly-add-component-design.md`, `2026-05-27-assembly-add-mate-design.md`. - - **Тест-инфра:** `IntegrationTestBase` (per-test `DocumentService.CloseAllAsync`) — все интеграционные - классы наследуют его. -- **СЛЕДУЮЩЕЕ — инкремент 3 (по желанию) или ВЕХА 2 (2D-ЧЕРТЁЖ).** См. ниже. -- Деталь: эскизы (пакет A), формообразующие (extrude/revolve/fillet/chamfer/shell/rib/sweep/loft), - массивы и зеркало (пакет C), уклон (`draft`), все типы отверстий (`hole`/`_counterbore`/ - `_countersink`/`_conic`, API7), переменные (`create/set/delete_variable`), STEP import/export, - прямое редактирование B-rep (`move_face`/`split_solid_by_plane`/`move_body`/`boolean_union`), - структурный осмотр (`describe_model`/`list_*`/`measure`). -- **`list_components` УЖЕ ЕСТЬ** (читает сборку: `IKompasDocument3D.TopPart → IPart7.Parts (IParts7)`). -- Документы: `DocumentService` уже умеет создавать `Assembly` и `Drawing` - (`KompasDocumentType.Assembly/Drawing` → `DocumentTypeEnum.ksDocumentAssembly/ksDocumentDrawing`). - Есть `document_save_as` (сохранить деталь в файл — нужно, чтобы вставить её в сборку/на чертёж). -- API7-сервисы существуют как образец: `HoleService`, `FaceEditService` (паттерн: `(IXxx)part` - через COM-QI, операции на STA-потоке `KompasDispatcher`). -- Прочитай память: `kompas-step-and-assembly-api` (обход сборки, извлечение компонента, STEP), - `kompas-hole-api7` (паттерн API7-сервиса), `kompas-parametric-sketch-findings` (тупик — не повторять). +## Текущее состояние (main = origin) + +**76 MCP-инструментов, 218 тестов зелёных (141 unit + 77 integration).** Сборка Release чистая. + +Три класса функционала: +- **ДЕТАЛЬ** (насыщена): эскизы (полный набор 2D-примитивов), формообразующие (extrude/revolve/ + fillet/chamfer/shell/rib/sweep/loft), массивы и зеркало, уклон (`draft`), все типы отверстий + (`hole`/`_counterbore`/`_countersink`/`_conic`), переменные (`create/set/delete_variable`), + STEP import/export, прямое редактирование B-rep (`move_face`/`split_solid_by_plane`/`move_body`/ + `boolean_union`), структурный осмотр (`describe_model`/`list_*`/`measure`). +- **СБОРКИ — завершены** (`AssemblyService`, namespace `Kompas.Mcp.Core.Assemblies`, API7): + - `assembly_add_component(filePath, x, y, z)` — вставка детали/подсборки `.m3d`/`.a3d` с позицией. + `IParts7.AddFromFile(path,true,true)` → `part.Placement.SetOrigin` → `UpdatePlacement(true)` → + `top.RebuildModel(true)`. + - `assembly_add_mate(mateType, x1,y1,z1, x2,y2,z2, value)` — сопряжение граней двух компонентов + (`coincidence`/`distance`). `(IMateConstraints3D)top.MateConstraints.Add(...)` → `BaseObject1/2` + (грани через `top.FindObjectsByPoint(x,y,z,FirstLevel=false)`) → `Update` → проверка `mate.Valid`. + - `list_components` (чтение сборки) был и раньше. +- **2D-ЧЕРТЁЖ — 4 инкремента готовы** (`DrawingService`, namespace `Kompas.Mcp.Core.Drawings`, API7): + 1. `drawing_create_standard_views(partFilePath, scale, x, y)` — стандартные виды (спереди/сверху/ + слева) сохранённой модели; возвращает `ViewNumbers` (для адресации видов при простановке размеров). + 2. `drawing_fill_title_block(designation?, name?, material?)` — основная надпись (графы 2/1/3). + 3. `drawing_add_linear_dimension(x1,y1,x2,y2,x3,y3, orientation, viewNumber)` — линейный размер + (horizontal/vertical/parallel). + 4. `drawing_add_diametral_dimension(xc,yc,radius,angle°, viewNumber)` — диаметральный размер (Ø=2R). + +Спеки всех фич — в `docs/superpowers/specs/2026-05-27-*.md`. Память (читать перед работой): +`kompas-drawing-api7` (чертёж: виды, штамп, размеры — все приёмы), `kompas-assembly-insert-api7` +(сборки: вставка + сопряжения), `kompas-step-and-assembly-api`, `kompas-hole-api7` (паттерн API7- +сервиса), `kompas-parametric-sketch-findings` (тупик — не повторять). + +## Следующий инкремент (на выбор; оба расписаны) + +### Вариант A — радиальный / угловой размер (продолжает размеры, ценнее) +Тот же контейнер, что у линейного/диаметрального — `ISymbols2DContainer` (QI от вида); есть готовый +хелпер `RequireSymbols2DContainer(viewNumber)` в `DrawingService`. Точки входа (рефлексия подтвердила): +- Радиальный: `symbols.RadialDimensions` (`IRadialDimensions.Add()` → `IRadialDimension`): + `Xc,Yc,Radius,Angle` + `DimensionType` + ветви (`AddBranch`/`AddBranchByArcParam`/`ShelfX,Y`). +- Угловой: `symbols.AngleDimensions` (`IAngleDimension`) — задание через две прямые/точки. +**Сделай спайк ДО спека** (у радиального — `DimensionType`/ветви; у углового — что измеряет и как +задаются стороны угла; что в `NominalValue`). Значение читается `((IDimensionText)dim).NominalValue`. +Тест — `*Dimensions.Count` целевого вида вырос + значение (как у диаметрального). + +### Вариант B — рамка / формат листа (проще, без спайка) +`ILayoutSheet.Format` (`SheetFormat`) — задать формат листа (A4/A3) и ориентацию. Детерминированно +тестируется (задать формат → прочитать). `doc2d.LayoutSheets.ItemByNumber[1]` → `.Format`. +Менее ценно, чем размеры, но низкий риск. ## ОТРИЦАТЕЛЬНЫЙ результат (не повторять) -- **Параметрические эскизы (переменная двигает геометрию) — НЕДОСТИЖИМЫ через COM-API.** - `ksCDimWithVariable` (`IDrawingObject1.NewConstraint`) `Create()`=FALSE из внешней автоматизации; - `ksCFixedLenght` игнорирует `Expression`-ссылку на переменную. См. - `docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md`. НЕ трогать повторно. +**Параметрические эскизы (переменная двигает геометрию) — НЕДОСТИЖИМЫ через COM-API.** +`ksCDimWithVariable` (`IDrawingObject1.NewConstraint`) `Create()`=FALSE из внешней автоматизации; +`ksCFixedLenght` игнорирует `Expression`-ссылку. См. +`docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md`. НЕ трогать. -## Веха 1 — СБОРКИ (начать отсюда; новый `AssemblyService` на API7) - -Точки входа (проверено рефлексией interop, всё есть): -- Создать сборку: `DocumentService.CreateAsync(KompasDocumentType.Assembly)`. -- `IKompasDocument3D.TopPart → IPart7` → `IPart7.Parts` (это `IParts7`). -- **Вставка компонента из файла:** `IParts7.AddFromFile(string fileName, bool, bool)` или - `AddFromFileWithParam(string fileName, IPlacement3D placement, IInsertPartParameters prm, bool)`. - Позиция/ориентация — `IPlacement3D` (есть `IPlacement3DManipulator`). -- **Сопряжения (mates):** `IMateConstraints3D`/`IMateConstraint3D` + типы `IMate3DByAngle`, - `IMate3DByTangent`, `IMate3DSymmetry`, и др. (совпадение/параллельность/расстояние/угол). - -Рекомендуемые инкременты (по одному, до зелёного → merge): -1. ✅ **СДЕЛАНО:** `assembly_add_component(filePath, x, y, z)` — вставка детали из файла в сборку. -2. ✅ **СДЕЛАНО:** `assembly_add_mate` — сопряжения coincidence/distance (см. «Текущее состояние»). - Расширения (будущее): прочие типы (parallel/perpendicular/concentric/angle/tangency — добавить с - геометрической проверкой, concentric требует цилиндрических граней), параметр `Alignment` - (`ksMCAlignmentCooriented`/`Opposite`/`Closest`). Для concentric/angle проверять тип грани. -3. **(по желанию)** Перемещение/массив/фиксация компонентов. ИЛИ сразу переходить к ВЕХЕ 2 (чертёж) — - она самый ценный нереализованный класс после сборок. - -Проверенный API сопряжений (для расширений): `(IMateConstraints3D)top.MateConstraints` → -`Add(MateConstraintType)` → `IMateConstraint3D` (`BaseObject1`/`BaseObject2` = IModelObject граней; -`ParamValue` для distance/angle; `Alignment`) → `Update()` → `RebuildModel(true)`. Типы: -`mc_Coincidence=0`, `mc_Parallel=1`, `mc_Perpendicular=2`, `mc_Tangency=3`, `mc_Concentric=4`, -`mc_Distance=5`, `mc_Angle=6`, `mc_Symmetric=11`. Грани компонентов — `top.FindObjectsByPoint(x,y,z, -FirstLevel=false)` (мировые координаты с учётом placement). Память: `kompas-assembly-insert-api7`. - -Тонкости: компоненту нужен сохранённый файл-источник (сначала сохрани деталь). Уточни через -`kompas-sdk-research` точные сигнатуры `AddFromFile`/`AddFromFileWithParam`, что такое -`IInsertPartParameters` и как задать `IPlacement3D` (СК вставки). - -## Веха 2 — 2D-ЧЕРТЁЖ (после сборок; новый `DrawingService` на API7) - -Точки входа (проверено): -- Создать чертёж: `DocumentService.CreateAsync(KompasDocumentType.Drawing)`. -- `IKompasDocument2D.ViewsAndLayersManager.Views` (это `IViews`). -- **Стандартные ассоциативные виды детали из файла:** - `IViews.AddStandartViews(string FileName, string ProjectionName, object ProjectionsTypes, - double X, double Y, double Scale, double DX, double DY)` — создаёт виды (спереди/сверху/слева) - по сохранённой модели. -- Отдельный вид: `IViews.Add(LtViewType)`; геометрия/размеры вида — через `IDrawingContainer` - вида (`LineSegments`/`Circles`/… — как в разведке параметрики). - -Рекомендуемые инкременты: -1. ✅ **СДЕЛАНО:** `drawing_create_standard_views(partFilePath, scale, x, y)` — стандартные виды - (спереди/сверху/слева) детали/сборки на чертеже. `AddStandartViews(path, "#Спереди", - object[]{1,3,5}, x, y, scale, 20, 20)`; проверено `created==3` + непустота. Память: - `kompas-drawing-api7`. -2. ✅ **СДЕЛАНО:** `drawing_fill_title_block(designation?, name?, material?)` — основная надпись. -3. ✅ **СДЕЛАНО:** `drawing_add_linear_dimension` — линейный размер на виде (`ISymbols2DContainer. - LineDimensions`). Размеры — в `ISymbols2DContainer` (QI от `IView`), НЕ в `IDrawingContainer`/ - `IView.ObjectCount`. Координаты — локальная СК вида. Память `kompas-drawing-api7`. -4. ✅ **СДЕЛАНО:** `drawing_add_diametral_dimension(xc,yc,radius,angle°,viewNumber)` — диаметральный - размер (Ø). `(ISymbols2DContainer)view.DiametralDimensions.Add` → `Xc/Yc/Radius/Angle(рад)`; - `NominalValue`=2R. Общий хелпер `RequireSymbols2DContainer(viewNumber)`. Память `kompas-drawing-api7`. -5. **СЛЕДУЮЩЕЕ:** радиальный (`RadialDimensions`, `IRadialDimension` — Xc/Yc/Radius/Angle + ветви - `AddBranch`/`AddBranchByArcParam`) / угловой (`AngleDimensions`, `IAngleDimension`) размер. Тот же - `ISymbols2DContainer` (переиспользуй `RequireSymbols2DContainer`). **Спайк ДО спека** (у радиального - — `DimensionType`/ветви; у углового — задание двух прямых/точек). Тест — `*Dimensions.Count` вырос, - значение. Альтернатива (проще, без спайка): рамка/формат листа (`ILayoutSheet.Format`→`SheetFormat`). - -Тонкости: чертёж проверяется не объёмом, а числом видов/объектов; ассоциативные виды требуют -сохранённого `.m3d`/`.a3d`-файла. Коды видов `ksRelativeProjectionTypeEnum`: `ksPtFront=1`, -`ksPtUp=3`, `ksPtLeft=5`, `ksPtIsoXYZ=7` и т.д. - -## Процесс на каждую операцию (отлажен в прошлых сессиях) -Сборки/чертёж — это НЕ `PartModeler` (он API5-деталь). Заводи НОВЫЕ сервисы (`AssemblyService`, -`DrawingService`) и НОВЫЕ классы инструментов (`AssemblyTools`, `DrawingTools`); регистрируй -сервисы в DI (`Program.cs`, `AddSingleton`). Образец API7-сервиса — `HoleService`. - -1. Рефлексия interop — подтверди сигнатуры (`AddFromFile`, `AddStandartViews`, mate-типы): +## Процесс на каждый инкремент (отлажен — 6 фич за прошлую сессию) +1. **Рефлексия interop** — подтверди сигнатуры (имена/типы могут отличаться от справки): ```powershell - $a7=[Reflection.Assembly]::LoadFrom((Resolve-Path 'libs/kompas-interop/KompasAPI7.dll')) - # члены IParts7 / IMateConstraints3D / IViews — имена методов, типы параметров + $a7=[Reflection.Assembly]::LoadFrom((Resolve-Path 'libs/kompas-interop/KompasAPI7.dll').Path) + ($a7.GetTypes()|?{$_.Name -eq 'IRadialDimension'}).GetProperties()|%{ "$($_.PropertyType.Name) $($_.Name)" } ``` - Если высокая неопределённость (как было с параметрикой) — сделай spike ДО спека. -2. Семантику API уточняй через навык `kompas-sdk-research` (субагент Sonnet), не рой справку сам. -3. Краткий спек в `docs/superpowers/specs/` → коммит → ОТДАЙ НА РЕВЬЮ Codex (`codex:rescue`, - `--fresh` для новой темы) → внеси обоснованные правки (оценивай технически, не слепо). -4. Реализация TDD: метод в новом сервисе (паттерн API7 как в `HoleService`), инструмент в новом - классе `*Tools.cs`, интеграционный тест в новом `*Tests.cs` (Collection `KompasCollection`). -5. Codex-ревью реализации (`--resume` того же треда) → правки. -6. Документация через навык `docs-delegate` (Sonnet обновит README/CLAUDE/ARCHITECTURE/ - presentation.html). **ВАЖНО:** число тестов задавай субагенту ТОЧНО (по `dotnet test` раннеру, - НЕ по числу `[Fact]`/`[Theory]` — теории разворачиваются в несколько кейсов). -7. `merge --no-ff` в main, удали ветку, `push origin main`. Обнови этот handoff. + Enum'ы — в `Kompas6Constants`/`Kompas6Constants3D`. **Тестовый проект НЕ ссылается на эти + constants-сборки** → COM-enum в публичном API сервиса оборачивай СВОИМ enum (как `MateType`/ + `DimensionOrientation`), unit-тесть по `(int)`-коду нельзя — проверяй только свой enum/Parse. +2. **Семантику API** уточняй навыком `kompas-sdk-research` (субагент Sonnet), не рой справку сам. +3. **При неопределённости (привязка к геометрии, координаты, единицы) — СПАЙК ДО СПЕКА**: черновой + метод сервиса + временный `*SpikeTests.cs`, прогнать, зафиксировать находку. (Так делалось для + сопряжений, видов, штампа, линейного и диаметрального размеров — всегда окупалось.) +4. **Краткий спек** в `docs/superpowers/specs/` → коммит → **ревью Codex** (`codex:rescue --fresh` для + новой темы) → внеси обоснованные правки (оценивай технически, отклоняй неуместное с обоснованием — + напр. точечный release RCW отклоняется по конвенции v2-2). +5. **TDD**: метод в `DrawingService` (или новом сервисе), инструмент в `*Tools.cs`, чистые валидаторы + в static (unit), интеграционный тест в `*Tests.cs` (наследует `IntegrationTestBase`, Collection + `KompasCollection`). Спайк-методы/тесты УДАЛИ, промотировав в финальный код. +6. **Ревью Codex реализации** (`--resume` того же треда) → правки. +7. **Документация** навыком `docs-delegate` (Sonnet: README/CLAUDE/ARCHITECTURE/OPEN_QUESTIONS/ + presentation.html). **Число тестов задавай ТОЧНО по `dotnet test` раннеру** (НЕ по числу + `[Fact]`/`[Theory]` — теории разворачиваются в несколько кейсов). +8. `merge --no-ff` в main → удали ветку → `push origin main` → обнови этот handoff + память. ## Паттерн интеграционного теста -`CreateAsync(...)` → построить/вставить → операция → `RebuildAsync`/`Update` → -проверить результат; `finally CloseAsync`. Для СБОРКИ — объём/габарит сборки или `list_components` -(число компонентов). Для ЧЕРТЕЖА — число видов (`Views.Count`)/объектов (объёмом не проверить). -Артефакты (сохранённые `.m3d`) — в gitignored `.scratch/`. +`CreateAsync(...)` → построить/вставить → операция → проверить → `finally CloseAsync`. +- ДЕТАЛЬ — объём/габарит/МЦХ. СБОРКА — габарит/`list_components`. +- ЧЕРТЁЖ — числом, не объёмом: **виды** — `Views.Count`/`ObjectCount`; **размеры** — НЕ в + `IView.ObjectCount` (они в `ISymbols2DContainer`) → считать `ISymbols2DContainer.*Dimensions.Count` + целевого вида; **значение размера** — `((IDimensionText)dim).NominalValue`. +- Артефакты (`.m3d` детали для видов/сборок) — в gitignored `.scratch/` (`TestPaths.NewFile`). +- Возможен ТРАНЗИЕНТНЫЙ сбой пакета сразу после большого прогона (нестабильность КОМПАС) — перезапусти. ## Ключевые ловушки (проверено) -- Все COM-вызовы — на STA-потоке (`KompasDispatcher.InvokeAsync`). Контейнеры API7 берём - COM-QI: `(IModelContainer)part`, `(IParts7)part.Parts` и т.п. -- Выбор грани/ребра — по стабильному индексу из `list_faces`/`list_edges`; для сопряжений - объекты компонентов искать через их `IPart7`/`FindObjectsByPoint`. -- Углы — в градусах. Валидацию — в чистые static (unit-тестируемо), проверяй `double.IsFinite`. +- Все COM-вызовы — на STA-потоке (`KompasDispatcher.InvokeAsync`). Контейнеры берём COM-QI: + `(IModelContainer)part`, `(ISymbols2DContainer)view`, `(IMateConstraints3D)top.MateConstraints`. +- **Размеры чертежа** — в `ISymbols2DContainer` (QI ОТ КОНКРЕТНОГО `IView`), координаты — в ЛОКАЛЬНОЙ + СК вида (= координаты модели на плоскости вида при 1:1). `AutoNominalValue=true` авто-измеряет. +- Углы 2D-размеров — в РАДИАНАХ в API (инструмент экспонирует градусы → `DimensionAngles.ToRadians`). +- Валидацию — в чистые static (unit-тестируемо), проверяй `double.IsFinite`. Проверяй результат + `Update()`/`RebuildModel()`; при неуспехе после `Add()` — откат `.Delete()`. - НЕ освобождай транзитные RCW точечно — общий отложенный долг (OPEN_QUESTIONS v2-2). - Команды: `dotnet build -c Release`; `dotnet test --filter "Category=Unit"`; `dotnet test --filter "Category=Integration"` (нужен запущенный КОМПАС). -Начни с рефлексии interop `IParts7` (вставка компонента) + `kompas-sdk-research` по -`AddFromFile`/`AddFromFileWithParam`/`IPlacement3D`, затем первый инкремент — -`assembly_add_component` (вставка детали из файла в сборку). +Начни с выбора варианта (A — радиальный/угловой размер, рекомендуется; B — рамка/формат листа), +затем рефлексия interop соответствующих интерфейсов + (для A) спайк до спека.