20e425585e
Надстройка над стадией-1 (сырой mxGraph XML) — помогает агенту рисовать
корректные диаграммы без бэкенд-рендеринга:
- hard-rules в описаниях drawio_create/drawio_update (геометрия, parent-
relative координаты, стили);
- drawio_guide (5 секций: skeleton / layout / containers / icons-aws /
icons-azure, каждая ≤4KB) — по требованию, не раздувает контекст;
- drawio_shapes — реальный jgraph shape-index (10446 фигур, gzip 437KB,
ленивый node:zlib gunzip) + курируемый оверлей (service-level паттерны
AWS/Azure, note-подсказки на пустые resIcon, палитра категорий);
ранжирование aws4>aws3; escapeRe в score (не ReDoS);
- layout:"elk" через elkjs (чистый JS, dependencies:{}) — compound-nesting,
best-effort (на сбое ELK возвращает нормализованный вход), 73→0 warnings
на 12-узловом графе;
- 6 типов quality-warnings в линтере (overlap, out-of-bounds, edge-cross,
и т.п.), геометрия Liang-Barsky; warnings НИКОГДА не блокируют write.
Оба новых инструмента в SHARED_TOOL_SPECS (tier:deferred) + SERVER_
INSTRUCTIONS; drift-guards зелёные. elkjs ^0.11.1 — единственный новый
рантайм-деп; lockfile синхронизирован (--frozen-lockfile --offline EXIT 0).
data/ едет с воркспейсом (.gitignore-негация !packages/mcp/data/).
Внутренний цикл: 1 проход внутреннего ревью (APPROVE WITH SUGGESTIONS);
все 59 профильных тестов зелёные.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
52 lines
1.9 KiB
JavaScript
52 lines
1.9 KiB
JavaScript
// Unit tests for the drawio_guide progressive-disclosure reference (issue #424).
|
|
// Acceptance #2: every section is returned and each is <= ~4KB so pulling one
|
|
// does not bloat the model's context.
|
|
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import {
|
|
getGuideSection,
|
|
GUIDE_SECTIONS,
|
|
} from "../../build/lib/drawio-guide.js";
|
|
|
|
const MAX_BYTES = 4096; // "<= ~4KB" acceptance bound.
|
|
|
|
test("every section is returned and is under ~4KB", () => {
|
|
assert.deepEqual(GUIDE_SECTIONS, [
|
|
"skeleton",
|
|
"layout",
|
|
"containers",
|
|
"icons-aws",
|
|
"icons-azure",
|
|
]);
|
|
for (const s of GUIDE_SECTIONS) {
|
|
const { section, content } = getGuideSection(s);
|
|
assert.equal(section, s);
|
|
assert.ok(content.length > 200, `${s}: suspiciously short`);
|
|
const bytes = Buffer.byteLength(content, "utf8");
|
|
assert.ok(bytes <= MAX_BYTES, `${s}: ${bytes} bytes exceeds ${MAX_BYTES}`);
|
|
}
|
|
});
|
|
|
|
test("each section's content matches its topic", () => {
|
|
assert.match(getGuideSection("skeleton").content, /mxGraphModel/);
|
|
assert.match(getGuideSection("skeleton").content, /adaptiveColors="auto"/);
|
|
assert.match(getGuideSection("layout").content, /elk/i);
|
|
assert.match(getGuideSection("layout").content, /150px|<150/);
|
|
assert.match(getGuideSection("containers").content, /fillColor=none/);
|
|
assert.match(getGuideSection("icons-aws").content, /resourceIcon/);
|
|
assert.match(getGuideSection("icons-aws").content, /elasticsearch_service/);
|
|
assert.match(getGuideSection("icons-azure").content, /img\/lib\/azure2/);
|
|
});
|
|
|
|
test("omitting the section returns the index of sections", () => {
|
|
const idx = getGuideSection();
|
|
assert.equal(idx.section, "index");
|
|
for (const s of GUIDE_SECTIONS) assert.ok(idx.content.includes(s));
|
|
assert.ok(Buffer.byteLength(idx.content, "utf8") <= MAX_BYTES);
|
|
});
|
|
|
|
test("an unknown section falls back to the index", () => {
|
|
const idx = getGuideSection("nonsense");
|
|
assert.equal(idx.section, "index");
|
|
});
|