From 71cafb2270dbe4dd87c32c252273f8d5f7f730e9 Mon Sep 17 00:00:00 2001 From: Shahovalov MIkhail Date: Wed, 27 May 2026 18:07:01 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20drawing=5Fadd=5Flinear=5Fdimension=20?= =?UTF-8?q?=E2=80=94=20=D1=83=D0=BF=D1=80=D0=BE=D1=87=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20?= =?UTF-8?q?Codex=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #4: отклонение нулевого NominalValue после Update (ориентация несовместима с точками, напр. horizontal на вертикали |X2-X1|=0) — откат dim.Delete + ошибка. #3: Parallel протестирован — работает БЕЗ явного Angle (КОМПАС авто-вычисляет угол по точкам; (0,0)-(30,40)→50). #7: rollback-ветка покрыта тестом нулевой проекции. #8: контракт «первый несистемный вид» — осознанный (задокументирован). Тесты: DrawingDimensionTests 5→7 (+parallel, +нулевая проекция/откат). Итого 131 unit + 72 integration = 203. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...6-05-27-drawing-linear-dimension-design.md | 14 ++++++- .../Drawings/DrawingService.cs | 6 +++ .../Integration/DrawingDimensionTests.cs | 37 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/docs/superpowers/specs/2026-05-27-drawing-linear-dimension-design.md b/docs/superpowers/specs/2026-05-27-drawing-linear-dimension-design.md index 29171eb..7097db6 100644 --- a/docs/superpowers/specs/2026-05-27-drawing-linear-dimension-design.md +++ b/docs/superpowers/specs/2026-05-27-drawing-linear-dimension-design.md @@ -1,7 +1,19 @@ # Дизайн: линейный размер на виде чертежа (drawing_add_linear_dimension) через API7 **Дата:** 2026-05-27 -**Статус:** реализовано и проверено (5 интеграционных + unit, всего 201); ревью Codex спека учтено +**Статус:** реализовано и проверено (7 интеграционных + unit, всего 203); ревью Codex спека и реализации учтено + +## Правки по ревью реализации Codex + +- **#4 нулевое значение** (важно): после `Update`+`Valid` проверяем `|NominalValue| > 1e-6` — ловит + несовместимость ориентации с точками (horizontal для точек на одной вертикали: `|X2-X1|=0`), которую + `RequireDistinctPoints` не видит. При нуле — откат (`dim.Delete`) + ошибка. Тест добавлен. +- **#3 Parallel** (важно): добавлен интеграционный тест — параллельный (0,0)-(30,40) → 50 (3-4-5). + **Работает БЕЗ явного `Angle`** (КОМПАС авто-вычисляет угол по точкам) — Parallel оставлен. +- **#7 rollback** (важно): тест нулевой проекции проходит через ветку `dim.Delete()` (откат) — + проверяет, что число размеров вида не изменилось. (Update==false/Valid==false без fault injection.) +- **#8 ассоциативность вида** (минор): осознанный контракт «первый НЕсистемный вид» (задокументирован + в описании инструмента и ошибке FindView). ## Находка реализации: размеры НЕ в IView.ObjectCount diff --git a/src/Kompas.Mcp.Core/Drawings/DrawingService.cs b/src/Kompas.Mcp.Core/Drawings/DrawingService.cs index 2e39f68..ee0023f 100644 --- a/src/Kompas.Mcp.Core/Drawings/DrawingService.cs +++ b/src/Kompas.Mcp.Core/Drawings/DrawingService.cs @@ -118,6 +118,12 @@ public sealed class DrawingService // NominalValue читаем ТОЛЬКО после успешного Update и Valid. var value = ((IDimensionText)dim).NominalValue; + // Нулевое значение — ориентация несовместима с точками (напр. horizontal для точек на одной + // вертикали: |X2-X1|=0). RequireDistinctPoints это не ловит — точки различны по Y. + if (Math.Abs(value) < 1e-6) + throw new InvalidOperationException( + "Размер измерил нулевое значение — выбранная ориентация несовместима с точками " + + "(например, horizontal для точек на одной вертикали; используйте vertical/parallel)."); return new DrawingDimensionResult { Value = value, ViewNumber = view.Number }; } catch diff --git a/tests/Kompas.Mcp.Tests/Integration/DrawingDimensionTests.cs b/tests/Kompas.Mcp.Tests/Integration/DrawingDimensionTests.cs index 4e4cbdb..3ee34dc 100644 --- a/tests/Kompas.Mcp.Tests/Integration/DrawingDimensionTests.cs +++ b/tests/Kompas.Mcp.Tests/Integration/DrawingDimensionTests.cs @@ -93,6 +93,43 @@ public sealed class DrawingDimensionTests : IntegrationTestBase finally { await _docs.CloseAsync(save: false); } } + [Fact] + public async Task Parallel_dimension_measures_true_length() + { + var partFile = await BuildAndSaveBoxAsync(); + await _docs.CreateAsync(KompasDocumentType.Drawing); + try + { + await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150); + // Параллельный размер (0,0)-(30,40): реальная длина = 50 (3-4-5). + var r = await _drawing.AddLinearDimensionAsync( + viewNumber: 0, x1: 0, y1: 0, x2: 30, y2: 40, x3: 25, y3: 5, DimensionOrientation.Parallel); + Assert.InRange(r.Value, 49.5, 50.5); + } + finally { await _docs.CloseAsync(save: false); } + } + + [Fact] + public async Task Zero_projection_orientation_throws_and_rolls_back() + { + var partFile = await BuildAndSaveBoxAsync(); + await _docs.CreateAsync(KompasDocumentType.Drawing); + try + { + await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150); + var before = await _drawing.GetViewLineDimensionCountAsync(0); + + // Горизонтальный размер для точек на одной вертикали → |X2-X1|=0 → ошибка + откат. + await Assert.ThrowsAsync(() => _drawing.AddLinearDimensionAsync( + viewNumber: 0, x1: 10, y1: 0, x2: 10, y2: 30, x3: 0, y3: 15, DimensionOrientation.Horizontal)); + + // Откат: число размеров не изменилось (вырожденный размер удалён). + var after = await _drawing.GetViewLineDimensionCountAsync(0); + Assert.Equal(before, after); + } + finally { await _docs.CloseAsync(save: false); } + } + [Fact] public async Task Coincident_points_throw() {