Веха 2D-ЧЕРТЁЖ, инкремент 2 (оформление). DrawingService.FillTitleBlockAsync: LayoutSheets.ItemByNumber[1].Stamp.Text[id].Str = text → Update(). Enum StampField → номер графы ГОСТ (designation=2, name=1, material=3). Заполнение нескольких граф за вызов; перезапись (Str замещает, Clear не нужен — подтверждено спайком). Новый инструмент drawing_fill_title_block; ReadStampCellAsync для проверки. Ревью Codex спека учтено: Update() результат проверяется; null-checks (LayoutSheets/sheet/Stamp); RequireActiveDrawing выделен (сохраняет cast-проверку); ColumnId switch с дефолтным throw; счётчик = непустые поля; name=графа 1 однозначно. Валидация — чистый StampFields (ColumnId + Collect). Тесты: +7 unit (StampFields), +4 integration (DrawingStampTests: заполнение+reread 3 граф, перезапись, пустой ввод, не-чертёж). Итого 123 unit + 65 integration = 188. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.7 KiB
Дизайн: основная надпись чертежа (drawing_fill_title_block) через API7
Дата: 2026-05-27 Статус: реализовано и проверено (4 интеграционных + 7 unit, всего 188); ревью Codex спека учтено
Находка спайка: Str ПЕРЕЗАПИСЫВАЕТ (Clear не нужен)
Двойная запись в графу 2 («ДЕТАЛЬ.001» → «ИЗДЕЛИЕ.002») → чтение даёт «ИЗДЕЛИЕ.002» (не
дописано). Значит stamp.Text[id].Str = value замещает содержимое — IText.Clear() перед
записью НЕ нужен.
Правки по ревью Codex
- Update() результат проверять:
if (!stamp.Update()) throw. - null-checks:
LayoutSheets,sheet,sheet.Stamp(ранняя диагностируемая ошибка). RequireActiveDrawing()сохраняет проверкуdoc is not IKompasDocument2D(не толькоDocumentType);RequireActiveDrawingViewsстановится надстройкой над ним.ColumnIdswitch — дефолтArgumentOutOfRangeException; unit-тест на(StampField)999.- Тест: писать и перечитывать ВСЕ три графы (вкл.
name=графа 1); явный rereadText[id].Str; тест overwrite (запись дважды → читается второе) — уже подтверждён спайком, перенесём в регрессию. name= «Наименование изделия» (графа 1,ksStPartNumber) — однозначно в описании (не путать сksStDocumentName=51).- Счётчик результата = число непустых (trimmed) полей, записанных до успешного
Update(). - Сигнатура:
FillTitleBlockAsync(string? designation = null, string? name = null, string? material = null, ct). - Scale (графа 6) и прочие — ЯВНО вне scope инкремента 2. Spike-метод и spike-тест удаляются.
- RCW точечно не освобождаем (v2-2).
Цель
Веха 2D-ЧЕРТЁЖ, инкремент 2 (оформление). После стандартных видов (drawing_create_standard_views)
— заполнить основную надпись (штамп, title block) чертежа: обозначение, наименование, материал.
Чертёж с видами + заполненным штампом = презентабельный конструкторский документ. Размеры на видах
— отдельный инкремент 3 (нужен спайк по размерным интерфейсам).
Спайк: механизм подтверждён вживую (НЕ разучивать)
Спайк (DrawingStampSpikeTests, зелёный) подтвердил путь API7 — round-trip графы:
IKompasDocument2D doc2d = (IKompasDocument2D)app.ActiveDocument; // активный чертёж
ILayoutSheet sheet = (ILayoutSheet)doc2d.LayoutSheets.ItemByNumber[1]; // лист 1 (1-based)
IStamp stamp = (IStamp)sheet.Stamp;
stamp.Text[columnId].Str = text; // Text[Int32 Id] — индексированное свойство; Id = номер графы
stamp.Update(); // фиксирует
string readBack = stamp.Text[columnId].Str; // чтение для проверки
Проверено: запись в графу 2 (обозначение) «ДЕТАЛЬ.001» → чтение возвращает «ДЕТАЛЬ.001».
IText.Str — read/write; IStamp.Text[Id] — индексированное свойство (рефлексия: get_Text(Int32 Id)).
Update() фиксирует; перестроение документа не нужно.
Номера граф ГОСТ (форма 1), ksStampEnum: ksStPartNumber=1 (наименование изделия),
ksStDescription=2 (обозначение документа), ksStMaterial=3 (материал), ksStScale=6 (масштаб),
ksStAuthor=110 (разработал) и т.д.
Архитектура
Метод в существующем DrawingService. Свой enum StampField (паттерн BasePlane/MateType)
маппится на номера граф — COM-числа не текут в Host/тесты.
src/Kompas.Mcp.Core/Drawings/StampField.cs— enumStampField+ staticStampFields(ColumnId(field)→ номер графы).DrawingService.FillTitleBlockAsync(designation?, name?, material?, ct)— реализация.- Инструмент
drawing_fill_title_blockвDrawingTools.
MCP-инструмент
| Инструмент | Параметры | Поведение |
|---|---|---|
drawing_fill_title_block |
designation?, name?, material? (все опц.) |
Заполнить графы основной надписи активного чертежа: обозначение (графа 2), наименование (1), материал (3). Передаются только нужные поля (null/пусто — пропускается). Возвращает число заполненных граф. |
Контракт: активный документ — чертёж; хотя бы одно поле задано (иначе ошибка). Набор полей — 3 ключевые графы ГОСТ (расширяемо). За один вызов заполняются все переданные (меньше round-trip'ов для LLM-агента, чем у «одна графа за вызов»).
Валидация (чистые static, unit-тест)
StampFields.ColumnId(StampField)—Designation→2,Name→1,Material→3(unit-тест маппинга).- В сервисе: собрать непустые (после
Trim) поля; если ни одного —ArgumentException«укажите хотя бы одно поле». (Чистый помощникStampFields.Collect(...)→ список (columnId,text) — unit-тестируемо без COM.)
Проверка активного документа
RequireActiveDrawing() → IKompasDocument2D (тип ksDocumentDrawing, иначе раздельная ошибка) —
выделить из существующего RequireActiveDrawingViews общий шаг (тот станет надстройкой: вернуть
.ViewsAndLayersManager.Views).
Реализация
FillTitleBlockCore: собрать поля (StampFields.Collect) → если пусто, ошибка → RequireActiveDrawing
→ sheet = LayoutSheets.ItemByNumber[1] → stamp = (IStamp)sheet.Stamp → для каждого поля
stamp.Text[columnId].Str = text → stamp.Update() (результат проверить) → вернуть число граф.
Транзитные RCW не освобождаем точечно (долг v2-2, как везде).
Тестирование
Unit (StampFieldsTests)
StampFields.ColumnId— каждое поле → ожидаемый номер графы (2/1/3).StampFields.Collect— пропускает null/пусто/пробелы; при всех пустых даёт пустой список; собирает заданные с обрезкой пробелов.
Integration (DrawingStampTests)
Паттерн: создать чертёж → FillTitleBlockAsync(...) → перечитать графы напрямую (helper в сервисе
ReadStampCellAsync(columnId) для теста ИЛИ проверка через возврат) → finally CloseAsync (база
IntegrationTestBase).
- Заполнение и чтение:
designation="ДЕТАЛЬ.001", material="Сталь 45"→ 2 графы; чтение графы 2 == «ДЕТАЛЬ.001», графы 3 == «Сталь 45». - Пустой ввод: все поля null →
ArgumentException(ни одной графы не тронуто). - Не-чертёж: активный документ — деталь → ошибка.
(Для чтения в тесте — добавить DrawingService.ReadStampCellAsync(columnId) — он же подтверждает
round-trip; спайк-файл удаляется.)
Дальнейшее (вне спека)
- Прочие графы (масштаб, разработал, даты, литера), размеры/обозначения на видах (инкремент 3), рамка/формат листа.