refactor(#193): tool-host drift-guard + staged plan (shared spec registry already merged) #249
Reference in New Issue
Block a user
Delete Branch "refactor/193-tool-spec-registry"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Долг #193 (tool-half) — drift-guard + staged plan
Ключевая находка: бóльшая часть tool-half #193 УЖЕ влита в develop (коммит
f3fa15e7): zod-agnostic общий реестрpackages/mcp/src/tool-specs.ts(SHARED_TOOL_SPECS, 14 инструментов: name + model-facing описание + schema-builder), потребляется ОБОИМИ слоями —index.tsчерезregisterShared(...)иai-chat-tools.service.tsчерезsharedTool(...), у каждого остаётся только тонкий execute/auth-адаптер. Boundary-трюк ровно как в issue: каждый потребитель передаёт свой zod (v3 mcp / v4 server) вbuildShape. Текст issue просто не обновили.Что НЕ объединяемо безопасно (оставлено): ~17 оставшихся инструментов осознанно расходятся И по схеме, И по описанию (in-app: «Reversible»-формулировки, guardrails — deletePage soft-only, transformPage без deleteComments, разные лимиты search 20 vs 100, modelFriendlyInput, in-app-only getCurrentPage/listSidebarPages/getComment/getPageHistory; схемы намеренно без
.min(1)). Свести = изменить валидацию/поведение → нарушает zero-behavior.DocmostClientLike(слой 3) — деривация типа подтверждённо рискованна, отложена: (1)@docmost/mcpне эмитит.d.ts(нет declaration/types-export, нет path-mapping) — импортировать нечего; (2) реальные методы возвращают конкретные типы, а in-app адаптер читает черезRecord<string,unknown>+as→ точная деривация ломает касты/билд; (3) рантайм-guard на сервере блокирован (ESM-loader падает под jest без--experimental-vm-modules, поэтому тесты его и мокают).Что отгружено (минимальный безопасный инкремент, zero behavior change):
packages/mcp/test/unit/client-host-contract.test.mjs— drift-guard для hand-mirror слоя-3, гоняется с ESM-стороны где реальный класс импортируем: проверяет, что каждый метод, объявленный в in-appDocmostClientLike, существует функцией на реальномDocmostClient. Переименование/удаление в client.ts теперь валит тест, а не уезжает «x is not a function» в тул-вызов агента.docmost-client.loader.ts— мутный комментарий заменён на указатель на guard-тест + конкретный 4-шаговый staged plan полной деривации типа.PM↔Markdown конвертер (вторая половина issue) — вне скоупа.
Тесты: mcp tsc + server tsc чисто; mcp 369 pass (+2 новых), ai-chat tools 51 pass; build/ в синхроне.
🤖 Generated with Claude Code
Ревью
4c7b67195— переревью ПОЛНЫМИ 8 аспектами (отдельный субагент на каждый: security, stability, regressions, test-coverage, conventions, documentation, simplification, architecture). Вердикт: CHANGES.Раскладка: security / stability / regressions / test-coverage / conventions / architecture — LGTM. documentation — F3 (см. ниже) остаётся открытой.
Открыто: F3 (warning, docs) — в комментарии теста (строки 30-32) uploadImage ошибочно указан как вызываемый MCP-транспортом index.ts; он внутренний в client.ts (вызывается insertImage/replaceImage). Подтверждено grep'ом (index.ts его не зовёт). Фикс: убрать uploadImage из перечня (оставить insertImage/replaceImage/deleteComment/updateComment/insertFootnote).
⛔ DROP (кодеру НЕ делать · калибровка):
F3: fixed — убрал
uploadImageиз списка методов, якобы вызываемых MCP-транспортом, в комментарииclient-host-contract.test.mjs(строки 30-32). Проверил грепом:index.tsне ссылается наuploadImageвовсе; метод внутренний вclient.tsи вызывается изinsertImage/replaceImage(client.ts:2657,2842). В перечне оставлены реально вызываемые транспортомinsertImage/replaceImage/deleteComment/updateComment/insertFootnote.DROP-пункт (вывести HOST_CONTRACT_METHODS из парсера) не трогаю — согласен с калибровкой: явный список это стабильный якорь, loud-failure при баге парсера.
Изменение — только комментарий, логика теста не затронута. Коммит
888deba8. Вернулreview/needs.Ревью
888deba8— раунд 2 (ПОЛНЫЕ 8 аспектов, отдельный субагент на каждый).Вердикт: PASS. F3 закрыта:
uploadImageубран из перечня методов, вызываемых MCP-транспортом, в комментарииclient-host-contract.test.mjs. Проверено независимо —index.tsзовёт ровноinsertImage/replaceImage/deleteComment/updateComment/insertFootnote(диф всех 39 вызововdocmostClient.*противHOST_CONTRACT_METHODSдаёт ровно этот набор), аuploadImageдействительно внутренний вclient.ts. Все 8 аспектов — LGTM. Готово к мержу.Маркер
reviewed_headобновлён на888deba8.