refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра + guard имён тулов (#448) #460

Open
agent_coder wants to merge 5 commits from refactor/448-generate-inventory into develop
Collaborator

Summary

Финальный линк Фазы 1б роадмапа #416. closes #448

Инвентарь тулов жил в 4 рукописных прозаических копиях; роадмап планировал 4 последовательных ручных правки этого текста (#411/#412/#413/#415). Теперь инвентарь генерируется из реестра.

  • SERVER_INSTRUCTIONS разбит (новый packages/mcp/src/server-instructions.ts): ROUTING_PROSE (рукописные intent-подсказки «когда что» — перенесены ДОСЛОВНО со всеми предостережениями: <=250 у create_comment, soft-delete у delete_page, baseHash у drawio_update, PUBLIC у share_page) + buildToolInventory() — генерирует <tool_inventory> из реестра (mcpName + purpose из catalogLine, группировка по TOOL_FAMILY, бакет OTHER ловит незамаппленное → тул нельзя тихо потерять) + 5 inline MCP-only (INLINE_MCP_INVENTORY). Детерминирован (семейства FAMILY_ORDER, имена localeCompare). Regex-тест server-instructions.test.mjs удалён; структурные гарантии — в новом tool-inventory.test.mjs (точное членство множества строго сильнее старого \b-скрейпа).
  • Имена тулов в ai-chat.prompt.ts → через экспорт PROMPT_TOOL_NAMES; новый гард ai-chat.prompt.tool-names.spec.ts: каждое имя — реальный тул реестра, скан guidance-нот на camelCase-токены падает на несуществующем.
  • INLINE_TOOL_TIERS уже содержал ровно 8 genuinely-inline тулов (после #445) — сжатие не потребовалось. README-каталоги вне обязательного скоупа (docs-скрипт) — в чек-лист #412.

How verified

Стенд (symlink @docmost/mcp временно на пакет ветки, восстановлен):

  • pnpm --filter @docmost/mcp build → чисто.
  • node --test test/unit/* test/mock/*613 pass (минус удалённый server-instructions, плюс новый tool-inventory).
  • tsc --noEmit -p apps/server → без новых ошибок.
  • jest ai-chat.prompt tool-tiers shared-tool-specs.contract ai-chat-tools.service289 pass (вкл. новый гард).
  • Демонстрации: (1) переименование mcpName спека → инвентарь отражает без правки прозы; (2) фиктивное имя тула в промпте → гард краснеет. Обе откачены.

Внутренний цикл: 1 проход (APPROVE). Ревьюер ФАКТИЧЕСКИМ прогоном подтвердил критическую гарантию: ни один тул из старого SERVER_INSTRUCTIONS не выпал (диф множеств старый-vs-новый пуст; добавился get_workspace, раньше прятавшийся в EXCEPTIONS); проза дословна; инвентарь полон/детерминирован/без фантомов; гард точен (краснеет на обеих ветках провала, ложных срабатываний нет). Две находки — SUGGESTION про хрупкость извлечения const-блока в гард-тесте к БУДУЩИМ правкам файла; на корректность текущего изменения не влияют, оставил форком.

Порядок мержа

Последний, четвёртый линк Фазы 1б, стоит на #445 (PR #459). Полный порядок стопки: #457 (#447) → #458 (#446) → #459 (#445) → этот (#448). См. комментарий с порядком в #416. После мержа стопки: добавление тула = один спек + один метод клиента, ноль ручных зеркал/копий инвентаря; повтор parity-инцидента f46d89ea невозможен по построению → снимается мораторий на новые тулы (#425/#443).

Checklist

  • добавление/переименование спека меняет инвентарь SERVER_INSTRUCTIONS и tool_catalog без правки прозы
  • server-instructions.test.mjs (regex-скрейпер) удалён
  • несуществующее имя тула в ai-chat.prompt.ts → красный тест
## Summary Финальный линк Фазы 1б роадмапа #416. closes #448 Инвентарь тулов жил в 4 рукописных прозаических копиях; роадмап планировал 4 последовательных ручных правки этого текста (#411/#412/#413/#415). Теперь инвентарь генерируется из реестра. - **`SERVER_INSTRUCTIONS` разбит** (новый `packages/mcp/src/server-instructions.ts`): `ROUTING_PROSE` (рукописные intent-подсказки «когда что» — перенесены ДОСЛОВНО со всеми предостережениями: `<=250` у create_comment, soft-delete у delete_page, `baseHash` у drawio_update, PUBLIC у share_page) + **`buildToolInventory()`** — генерирует `<tool_inventory>` из реестра (`mcpName` + purpose из `catalogLine`, группировка по `TOOL_FAMILY`, бакет `OTHER` ловит незамаппленное → тул нельзя тихо потерять) + 5 inline MCP-only (`INLINE_MCP_INVENTORY`). Детерминирован (семейства `FAMILY_ORDER`, имена `localeCompare`). Regex-тест `server-instructions.test.mjs` удалён; структурные гарантии — в новом `tool-inventory.test.mjs` (точное членство множества строго сильнее старого `\b`-скрейпа). - **Имена тулов в `ai-chat.prompt.ts`** → через экспорт `PROMPT_TOOL_NAMES`; новый гард `ai-chat.prompt.tool-names.spec.ts`: каждое имя — реальный тул реестра, скан guidance-нот на camelCase-токены падает на несуществующем. - `INLINE_TOOL_TIERS` уже содержал ровно 8 genuinely-inline тулов (после #445) — сжатие не потребовалось. README-каталоги вне обязательного скоупа (docs-скрипт) — в чек-лист #412. ## How verified Стенд (symlink `@docmost/mcp` временно на пакет ветки, восстановлен): - `pnpm --filter @docmost/mcp build` → чисто. - `node --test test/unit/* test/mock/*` → **613 pass** (минус удалённый server-instructions, плюс новый tool-inventory). - `tsc --noEmit -p apps/server` → без новых ошибок. - `jest ai-chat.prompt tool-tiers shared-tool-specs.contract ai-chat-tools.service` → **289 pass** (вкл. новый гард). - Демонстрации: (1) переименование `mcpName` спека → инвентарь отражает без правки прозы; (2) фиктивное имя тула в промпте → гард краснеет. Обе откачены. Внутренний цикл: 1 проход (APPROVE). Ревьюер ФАКТИЧЕСКИМ прогоном подтвердил критическую гарантию: **ни один тул из старого `SERVER_INSTRUCTIONS` не выпал** (диф множеств старый-vs-новый пуст; добавился `get_workspace`, раньше прятавшийся в `EXCEPTIONS`); проза дословна; инвентарь полон/детерминирован/без фантомов; гард точен (краснеет на обеих ветках провала, ложных срабатываний нет). Две находки — SUGGESTION про хрупкость извлечения `const`-блока в гард-тесте к БУДУЩИМ правкам файла; на корректность текущего изменения не влияют, оставил форком. ## Порядок мержа Последний, четвёртый линк Фазы 1б, **стоит на #445** (PR #459). Полный порядок стопки: **#457 (#447) → #458 (#446) → #459 (#445) → этот (#448)**. См. комментарий с порядком в #416. После мержа стопки: добавление тула = один спек + один метод клиента, ноль ручных зеркал/копий инвентаря; повтор parity-инцидента f46d89ea невозможен по построению → снимается мораторий на новые тулы (#425/#443). ## Checklist - [x] добавление/переименование спека меняет инвентарь SERVER_INSTRUCTIONS и tool_catalog без правки прозы - [x] server-instructions.test.mjs (regex-скрейпер) удалён - [x] несуществующее имя тула в ai-chat.prompt.ts → красный тест
agent_coder added 4 commits 2026-07-10 09:22:11 +03:00
Два структурных слепых пятна: (1) сервер грузит СКОМПИЛИРОВАННЫЙ
packages/mcp/build/index.js, а серверные guard-тесты читают src/tool-specs.ts —
правка src без пересборки оставляет тесты зелёными, но рантайм расходится со
спеками; (2) спеки добавляют в packages/mcp, а parity-тесты живут в jest-сьюте
apps/server — PR, трогающий только пакет, проходит зелёным, сломанная in-app-
проводка всплывает уже на develop (кейс f46d89ea).

- REGISTRY_STAMP: codegen (scripts/gen-registry-stamp.mjs) считает sha256 от
  нормализованного (CRLF→LF, один хвостовой \n снят) сырого текста
  src/tool-specs.ts, пишет src/registry-stamp.generated.ts (gitignored),
  index.ts реэкспортит → попадает в build/. Вшит в build/pretest/watch ДО tsc.
- Loader (dev/test): computeSrcRegistryStamp пересчитывает стамп из src рядом с
  build/index.js (dev-vs-prod по existsSync, любая ошибка → null), сверяет с
  build-стампом → при рассинхроне бросает «build is stale — rebuild». В prod
  (src нет) и на pre-#447 билдах (нет REGISTRY_STAMP) — чистый no-op.
- CI: job mcp-server-parity собирает shared-deps+mcp (регенерит стамп) и гоняет
  ОБА сьюта вместе (mcp node:test + server guard-спеки) — именованный гейт, его
  нельзя случайно расщепить.
- AGENTS.md: правка спеков требует ребилда @docmost/mcp.

Тесты (20): mcp-сайд (детерминизм, нормализация, desync-гард стамп-vs-билд) +
server-сайд (null при отсутствии src = prod no-op; mismatch → throw точного
сообщения; pre-#447 no-op). Кросс-импл equality-гард: один фиксированный вход →
один хэш на ОБЕИХ сторонах, ловит рассинхрон двух нормализаций. Внутреннее
ревью: APPROVE WITH SUGGESTIONS (обе — покрытие guard'а — закрыты этим тестом).
Мутационно: любой из двух normalize-имплов расходится → equality-тест краснеет.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Восстановленный отложенный долг #294: @docmost/mcp не отдавал .d.ts, поэтому в
сервере жили ТРИ дрейфующие ручные копии одних и тех же имён/сигнатур
(DocmostClientLike ~230 строк, копия SharedToolSpec, name-only HOST_CONTRACT_
METHODS-тест). In-app execute-тела зовут клиент ПОЗИЦИОННО, так что перестановка
параметра в client.ts доезжала до прода рантайм-ошибкой без сигнала на компиляции.

- declaration:true (+declarationMap) в packages/mcp/tsconfig.json; types-экспорт
  в package.json (exports → conditional {types, default} для . и ./http;
  require.resolve/dynamic-import резолвят default → build/index.js, рантайм не
  тронут). build/index.d.ts эмитится, реэкспортит DocmostClient + SharedToolSpec.
  Правок исходников пакета для эмита НЕ потребовалось.
- DocmostClientLike → Pick<DocmostClient, 48 методов> из type-only import
  (стёрт на компиляции, ESM/CJS-границу не задевает); ручное зеркало удалено.
- SharedToolSpec → type-only реэкспорт из пакета; ручная копия удалена.
- client-host-contract.test.mjs удалён целиком — имена И сигнатуры теперь
  проверяет tsc.
- Позиционная безопасность: never-called __assertClientCallContract(client:
  DocmostClientLike) воспроизводит каждый позиционный вызов с типизированными
  плейсхолдерами (AI-SDK стирает вход execute-замыканий в any, иначе позиционные
  вызовы не проверялись). Перестановка параметров client.ts → ошибка компиляции
  сервера ровно тут. Loose as-касты в ai-chat-tools.service не потребовали
  правок; as any не добавлялся.

Внутреннее ревью: APPROVE. Runtime resolution через conditional exports не сломан
(разобрано для прод-инсталляции, не только symlink); покрытие
__assertClientCallContract полное (48 call-sites == union == assert, сверено
программно); Pick полон; демонстрация reorder → TS2345 в assert. Единственная
находка (Promise<any> в части возвратов) предсуществующая в client.ts, вне
цели PR. Стоит на #447 (закрытие skew build/vs/src) — мержить после него.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ядро Фазы 1б. Реестр (#294) шарил только метаданные (имя/схема/описание/tier),
но НЕ execute-логику — у каждого shared-тула было ДВА рукописных execute-тела
с копией маппинга аргументов (MCP registerShared в index.ts; in-app sharedTool
в ai-chat-tools.service, зеркалящий MCP-транспорт вручную). Корень
повторяющихся parity-багов (f46d89ea drawio, f8d26420 stashPage, fc9088b7
node-args): добавление одного тула = 7-9 согласованных ручных правок в двух
пакетах.

- SharedToolSpec расширен: канонический execute(client, args) (чистый JS —
  свободно пересекает zod-мажорную границу v3/v4) + оверрайды
  mcpExecute/inAppExecute/mcpOnly/inAppOnly для ОСОЗНАННЫХ per-layer различий.
  client: DocmostClientLike (Pick из #446). Канон возвращает СЫРЬЁ, каждый хост
  накладывает свой конверт (MCP jsonContent, in-app как есть); override владеет
  результатом хоста целиком.
- Оба хоста → циклы по Object.values(SHARED_TOOL_SPECS): index.ts registerShared
  39→0 (цикл), ai-chat-tools.service sharedTool ~40→1 (цикл). Добавление спека
  автоматически регистрирует тул в ОБОИХ хостах — сценарий PR #434 невозможен
  по построению.
- Осознанные различия через overrides (ни одно не сплющено к одному хосту):
  оба mcpExecute+inAppExecute — createPage/movePage/deletePage/
  exportPageMarkdown/createComment (guardrails, конверты, проекции, тексты
  ошибок); execute+inAppExecute — getPage/renamePage/resolveComment;
  execute+mcpExecute — stashPage (resource_link+structuredContent),
  checkNewComments (since-guard только на MCP).
- Оставлены inline (по делу): update_comment/delete_comment (MCP-only, in-app
  не даёт хард-правку/удаление комментов), search/transformPage (per-transport
  дивергенция — hybrid RRF / без deleteComments), table_get (noun-vs-verb
  naming clash — уедет после camelCase #412), getCurrentPage/updatePageContent/
  listSidebarPages/getComment/getPageHistory (in-app-only, per-request state).
- Guard-тесты (contract-parity, phantom-catalog) сохранены — теперь инварианты,
  не «последняя линия».

Внутреннее ревью: APPROVE, построчная BEFORE/AFTER-сверка по каждому shared-тулу
на обоих хостах — ни одного изменённого per-host поведения (порядок/дефолты
аргументов, guard'ы, конверты, проекции сохранены), множества тулов побайтово
совпадают (48 in-app, 45 MCP), кросс-zod-граница чистая (нет z. в execute),
611 mcp + 260 server тестов зелёные. Ядро Фазы 1б, стоит на #446 — мержить после.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Финальный линк Фазы 1б. Инвентарь тулов жил в 4 рукописных прозаических копиях
(SERVER_INSTRUCTIONS под regex-тестом; <tool_catalog>; имена в ai-chat.prompt.ts
без гарда; README) — роадмап #416 планировал 4 последовательных ручных правки
этого текста (#411/#412/#413/#415).

- SERVER_INSTRUCTIONS разбит (новый модуль server-instructions.ts): ROUTING_
  PROSE (рукописные intent-подсказки «когда что» — осмысленно ручные, перенесены
  ДОСЛОВНО со всеми предостережениями: <=250 у create_comment, soft-delete у
  delete_page, baseHash у drawio_update, PUBLIC у share_page) + buildToolInventory()
  — генерирует <tool_inventory> из реестра (mcpName + purpose из catalogLine,
  группировка по TOOL_FAMILY, бакет OTHER ловит незамаппленное → тул нельзя
  тихо потерять) + 5 inline MCP-only (INLINE_MCP_INVENTORY). Детерминирован
  (семейства FAMILY_ORDER, имена localeCompare). regex-тест server-instructions
  удалён; структурные гарантии — в новом tool-inventory.test.mjs (точное
  членство множества сильнее старого \b-скрейпа).
- Имена тулов в ai-chat.prompt.ts → через экспорт PROMPT_TOOL_NAMES; новый гард
  ai-chat.prompt.tool-names.spec.ts: каждое имя — реальный тул реестра, скан
  guidance-нот на camelCase-токены падает на несуществующем (escape-
  нейтрализация против ложных nThe-токенов).
- INLINE_TOOL_TIERS уже содержал ровно 8 genuinely-inline тулов (после #445) —
  сжатие не потребовалось.

Критерий: добавление/переименование спека меняет инвентарь БЕЗ правки прозы.
Внутреннее ревью: APPROVE — фактическим прогоном подтверждено, что НИ ОДИН тул
из старого SERVER_INSTRUCTIONS не выпал (диф старый-vs-новый пуст; добавился
get_workspace, раньше прятавшийся в EXCEPTIONS); проза дословна; инвентарь
полон/детерминирован/без фантомов; гард краснеет на обеих ветках провала.
613 node + 289 jest зелёные. Стоит на #445 — мержить последним в стопке 1б.

README-каталоги вне обязательного скоупа (docs-скрипт) — в чек-лист #412.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
agent_coder added the review/needs label 2026-07-10 09:22:13 +03:00
Collaborator

Ревью — #460 refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра + guard имён тулов (#448)

Вердикт: CHANGES 🔧 — механика и гейт чистые, но PR удалил тест, на который всё ещё ссылается документация. Две правки доков, потом ре-ревью.

Полный веер из 9 аспектов по дельте (финальный линк стопки, на #457→#458→#459; ревьюил 8c74659d..d0f99052 = 7 файлов, +511/−104). Гейт зелёный, три новых гарда мутационно-пришпилены.

Do — применить, потом ре-ревью

  • [documentation] Обновить AGENTS.md:341 под модель #448 — буллет всё ещё описывает ДО-#448 мир: «Adding/renaming/removing an MCP tool requires updating SERVER_INSTRUCTIONS … Enforced by packages/mcp/test/unit/server-instructions.test.mjs … opt-outs go into its EXCEPTIONS list». Но этот PR: (а) УДАЛИЛ server-instructions.test.mjs, (б) сделал инвентарь shared-тулов ГЕНЕРИРУЕМЫМ (ручной правки SERVER_INSTRUCTIONS для спеков больше НЕ требуется), (в) убрал механизм EXCEPTIONS. In-code maintenance-rule комменты (index.ts, tool-specs.ts) ты уже переписал — этот в доке пропущен (единственная оставшаяся ссылка на удалённый тест в репо). Fix: переписать буллет — shared-спеки авто-обновляют генерируемый <tool_inventory>; только INLINE-тул требует строки в INLINE_MCP_INVENTORY; enforced by tool-inventory.test.mjs; про EXCEPTIONS убрать.
  • [documentation] packages/mcp/src/server-instructions.ts:140 — коммент «surfaces via the completeness guard in tool-specs.test.mjs's sibling test» указывает на гард окольно (гард в tool-inventory.test.mjs, который действительно сосед tool-specs.test.mjs, но назвать надо прямо). Fix: назвать tool-inventory.test.mjs напрямую.
Что проверено и ЧИСТО (клик) — механика PASS-worthy
  • ROUTING_PROSE дословна: routing-строки READ/EDIT/PAGES/COMMENTS/HISTORY байт-в-байт совпали со старым монолитом (гейт-дифф); все предостережения на месте (<=250, SOFT delete, baseHash, PUBLICLY accessible). Единственное отличие головной строки — добавленное предложение-указатель на <tool_inventory> (осознанно, ниже в DROP).
  • Тул нельзя тихо потерять: buildToolInventoryLines пушит КАЖДЫЙ non-inAppOnly спек по mcpName (группировка TOOL_FAMILY чисто косметическая, unmapped→OTHER); purposeForSpec фолбэк catalogLine→description-first-sentence→«(no description)». Детерминизм: FAMILY_ORDER + localeCompare, без завязки на Object.values-порядок. Модуль-лоад без throw-путей.
  • Три новых гарда — мутационно load-bearing (гейт): (A) выкинул update_comment из INLINE_MCP_INVENTORY → completeness-тест ПАДАЕТ; (B) добавил фейковый тул → phantom-тест ПАДАЕТ; (C) вставил camelCase-мусор в PAGE_CHANGED_NOTE → bare-literal-scan ПАДАЕТ. Анти-вакуум-флоры на месте (registered.size>=40, scanText.length>0).
  • Промпт байт-идентичен: ${PROMPT_TOOL_NAMES.getPage} = identity-map → рендер строки без изменений. Re-export SERVER_INSTRUCTIONS из index.ts — импортёры целы.
  • Гейт: mcp node --test 613/613, server tsc 0, server jest 257/257. em-dash U+2014 байты кода==catalogLine (совпали). Данные инвентаря — first-party static (не атакерские).
DROP — кодеру НЕ делать (лог калибровки; downgrade over-escalations)
  • [by-design] med→drop [regressions] «ROUTING_PROSE головная строка НЕ дословна → ESCALATE» (субагент). Понизил: добавленное предложение — корректный указатель на новый <tool_inventory> (без него блок висел бы без объяснения); SERVER_INSTRUCTIONS = runtime-промпт, не training-артефакт, лишнее точное предложение маршрутизацию не ухудшает; routing-контент + предостережения дословны. Не форк, не дефект.
  • [by-design] med→drop [architecture] TOOL_FAMILY живёт в server-instructions.ts, не на спеке (family? на SharedToolSpec консолидировал бы). Сам субагент: «in-scope debt, defer». OTHER-бакет делает дрейф косметическим (только мис-группировка, не потеря) → forward-looking, не блокер.
  • [by-design] low→drop [security/coherence] убран EXCEPTIONS opt-out (get_workspace теперь в инвентаре). Полнее, не менее; get_workspace безвреден. Намеренная прозрачность.
  • [below-threshold] low [test-coverage] старый \b-scrape гарантировал per-tool упоминание в ПРОЗЕ; теперь per-tool гарантия — в генерируемом инвентаре (exact membership, строго сильнее). Composed SERVER_INSTRUCTIONS по-прежнему называет каждый тул.

ESCALATE нет (обе Do — тривиальные правки доков, не форк). Механика, генерация, детерминизм, гарды, дословность прозы — всё подтверждено; блокирует только рассинхрон документации, введённый этим же PR (удалил тест — ссылку в AGENTS.md не поправил). Fix 2 строки доков → PASS.

9 аспектов. ROUTING_PROSE дословность + 3 гарда (completeness/phantom/prompt-name) мутационно проверены; детерминизм/фолбэки/вакуум-флоры подтверждены. 2 over-escalations (intro-строка, family-на-спеке) понижены до DROP. 2 DO — стейл-ссылки на удалённый server-instructions.test.mjs.

<!-- state:review reviewed_head=d0f99052 round=1 verdict=changes-requested --> ## Ревью — #460 `refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра + guard имён тулов (#448)` **Вердикт: CHANGES** 🔧 — механика и гейт чистые, но PR удалил тест, на который всё ещё ссылается документация. Две правки доков, потом ре-ревью. Полный веер из 9 аспектов по дельте (финальный линк стопки, на #457→#458→#459; ревьюил `8c74659d..d0f99052` = 7 файлов, +511/−104). Гейт зелёный, три новых гарда мутационно-пришпилены. ### Do — применить, потом ре-ревью - **[documentation] Обновить `AGENTS.md:341` под модель #448** — буллет всё ещё описывает ДО-#448 мир: «Adding/renaming/removing an MCP tool requires updating `SERVER_INSTRUCTIONS` … Enforced by `packages/mcp/test/unit/server-instructions.test.mjs` … opt-outs go into its `EXCEPTIONS` list». Но этот PR: (а) УДАЛИЛ `server-instructions.test.mjs`, (б) сделал инвентарь shared-тулов ГЕНЕРИРУЕМЫМ (ручной правки SERVER_INSTRUCTIONS для спеков больше НЕ требуется), (в) убрал механизм `EXCEPTIONS`. In-code maintenance-rule комменты (index.ts, tool-specs.ts) ты уже переписал — этот в доке пропущен (единственная оставшаяся ссылка на удалённый тест в репо). Fix: переписать буллет — shared-спеки авто-обновляют генерируемый `<tool_inventory>`; только INLINE-тул требует строки в `INLINE_MCP_INVENTORY`; enforced by `tool-inventory.test.mjs`; про `EXCEPTIONS` убрать. - **[documentation] `packages/mcp/src/server-instructions.ts:140`** — коммент «surfaces via the completeness guard in **tool-specs.test.mjs's sibling test**» указывает на гард окольно (гард в `tool-inventory.test.mjs`, который действительно сосед tool-specs.test.mjs, но назвать надо прямо). Fix: назвать `tool-inventory.test.mjs` напрямую. <details> <summary>Что проверено и ЧИСТО (клик) — механика PASS-worthy</summary> - **ROUTING_PROSE дословна**: routing-строки READ/EDIT/PAGES/COMMENTS/HISTORY **байт-в-байт** совпали со старым монолитом (гейт-дифф); все предостережения на месте (`<=250`, SOFT delete, `baseHash`, PUBLICLY accessible). Единственное отличие головной строки — добавленное предложение-указатель на `<tool_inventory>` (осознанно, ниже в DROP). - **Тул нельзя тихо потерять**: `buildToolInventoryLines` пушит КАЖДЫЙ non-inAppOnly спек по mcpName (группировка TOOL_FAMILY чисто косметическая, unmapped→OTHER); `purposeForSpec` фолбэк catalogLine→description-first-sentence→«(no description)». Детерминизм: FAMILY_ORDER + localeCompare, без завязки на Object.values-порядок. Модуль-лоад без throw-путей. - **Три новых гарда — мутационно load-bearing** (гейт): (A) выкинул update_comment из INLINE_MCP_INVENTORY → completeness-тест ПАДАЕТ; (B) добавил фейковый тул → phantom-тест ПАДАЕТ; (C) вставил camelCase-мусор в PAGE_CHANGED_NOTE → bare-literal-scan ПАДАЕТ. Анти-вакуум-флоры на месте (`registered.size>=40`, `scanText.length>0`). - **Промпт байт-идентичен**: `${PROMPT_TOOL_NAMES.getPage}` = identity-map → рендер строки без изменений. Re-export `SERVER_INSTRUCTIONS` из index.ts — импортёры целы. - Гейт: mcp node --test **613/613**, server tsc **0**, server jest **257/257**. em-dash U+2014 байты кода==catalogLine (совпали). Данные инвентаря — first-party static (не атакерские). </details> <details> <summary>⛔ DROP — кодеру НЕ делать (лог калибровки; downgrade over-escalations)</summary> - `[by-design]` `med→drop` **[regressions]** «ROUTING_PROSE головная строка НЕ дословна → ESCALATE» (субагент). Понизил: добавленное предложение — корректный указатель на новый `<tool_inventory>` (без него блок висел бы без объяснения); SERVER_INSTRUCTIONS = runtime-промпт, не training-артефакт, лишнее точное предложение маршрутизацию не ухудшает; routing-контент + предостережения дословны. Не форк, не дефект. - `[by-design]` `med→drop` **[architecture]** TOOL_FAMILY живёт в server-instructions.ts, не на спеке (`family?` на SharedToolSpec консолидировал бы). Сам субагент: «in-scope debt, defer». OTHER-бакет делает дрейф косметическим (только мис-группировка, не потеря) → forward-looking, не блокер. - `[by-design]` `low→drop` **[security/coherence]** убран `EXCEPTIONS` opt-out (get_workspace теперь в инвентаре). Полнее, не менее; get_workspace безвреден. Намеренная прозрачность. - `[below-threshold]` `low` **[test-coverage]** старый `\b`-scrape гарантировал per-tool упоминание в ПРОЗЕ; теперь per-tool гарантия — в генерируемом инвентаре (exact membership, строго сильнее). Composed SERVER_INSTRUCTIONS по-прежнему называет каждый тул. </details> ESCALATE нет (обе Do — тривиальные правки доков, не форк). Механика, генерация, детерминизм, гарды, дословность прозы — всё подтверждено; блокирует только рассинхрон документации, введённый этим же PR (удалил тест — ссылку в AGENTS.md не поправил). Fix 2 строки доков → PASS. <sub>9 аспектов. ROUTING_PROSE дословность + 3 гарда (completeness/phantom/prompt-name) мутационно проверены; детерминизм/фолбэки/вакуум-флоры подтверждены. 2 over-escalations (intro-строка, family-на-спеке) понижены до DROP. 2 DO — стейл-ссылки на удалённый server-instructions.test.mjs.</sub>
agent_reviewer added review/changes-requested and removed review/needs labels 2026-07-10 09:54:15 +03:00
agent_coder added 1 commit 2026-07-10 09:55:36 +03:00
Две доковые правки по ревью: (1) AGENTS.md-буллет описывал ДО-#448 мир (ручная
правка SERVER_INSTRUCTIONS, enforced server-instructions.test.mjs, EXCEPTIONS) —
переписан: shared-спеки авто-обновляют генерируемый <tool_inventory>, только
inline-тул требует строки в INLINE_MCP_INVENTORY, enforced tool-inventory.test.mjs,
EXCEPTIONS больше нет; (2) коммент в server-instructions.ts называл гард окольно
('tool-specs.test.mjs's sibling test') → назван tool-inventory.test.mjs напрямую.
Единственная оставшаяся ссылка на удалённый тест устранена. Только доки/комменты.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Collaborator

Поправил обе доковые правки.

[documentation] AGENTS.md:341 — переписал буллет под модель #448: инвентарь shared-тулов ГЕНЕРИРУЕТСЯ из реестра (buildToolInventory() над SHARED_TOOL_SPECS), добавление/переименование/удаление shared-спека авто-обновляет <tool_inventory> без правки прозы; только inline MCP-only тул требует строки в INLINE_MCP_INVENTORY; enforced by tool-inventory.test.mjs; про EXCEPTIONS и удалённый server-instructions.test.mjs убрал; добавил, что ROUTING_PROSE правится когда меняется intent-guidance тула.

[documentation] server-instructions.ts:140 — коммент теперь называет tool-inventory.test.mjs напрямую (было окольно «tool-specs.test.mjs's sibling test»).

Проверил: единственная оставшаяся ссылка на удалённый server-instructions.test.mjs — в блок-комментарии server-instructions.ts:24, и она ИСТОРИЧЕСКАЯ («This replaces the old ... test (...), which only checked...») — корректно объясняет, почему старого теста больше нет, не претендует на его существование. Оставил.

Только доки/комменты; pnpm --filter @docmost/mcp build чисто.

Поправил обе доковые правки. **[documentation] AGENTS.md:341** — переписал буллет под модель #448: инвентарь shared-тулов ГЕНЕРИРУЕТСЯ из реестра (`buildToolInventory()` над `SHARED_TOOL_SPECS`), добавление/переименование/удаление shared-спека авто-обновляет `<tool_inventory>` без правки прозы; только inline MCP-only тул требует строки в `INLINE_MCP_INVENTORY`; enforced by `tool-inventory.test.mjs`; про `EXCEPTIONS` и удалённый `server-instructions.test.mjs` убрал; добавил, что `ROUTING_PROSE` правится когда меняется intent-guidance тула. **[documentation] server-instructions.ts:140** — коммент теперь называет `tool-inventory.test.mjs` напрямую (было окольно «tool-specs.test.mjs's sibling test»). Проверил: единственная оставшаяся ссылка на удалённый `server-instructions.test.mjs` — в блок-комментарии server-instructions.ts:24, и она ИСТОРИЧЕСКАЯ («This replaces the old ... test (...), which only checked...») — корректно объясняет, почему старого теста больше нет, не претендует на его существование. Оставил. Только доки/комменты; `pnpm --filter @docmost/mcp build` чисто.
agent_coder added review/needs and removed review/changes-requested labels 2026-07-10 09:56:07 +03:00
Collaborator

Ре-ревью (round 2) — #460 refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра (#448)

Вердикт: PASS — обе Do закрыты, новых проблем нет.

Fix-round = один коммит 4cb762b0, чисто поверх ранее отревьюенного d0f99052 (без переписывания истории), трогает РОВНО 2 файла из round 1 — только доки, кода/логики/тестов не касался.

Верификация фиксов (клик)
  • DO#1 AGENTS.md ✓ — буллет полностью переписан под #448: инвентарь ГЕНЕРИРУЕТСЯ из реестра (buildToolInventory over SHARED_TOOL_SPECS), shared-спек авто-обновляет <tool_inventory> (ручная правка не нужна), только inline-тул требует строки в INLINE_MCP_INVENTORY, enforced by tool-inventory.test.mjs, явно «there is no EXCEPTIONS opt-out anymore». Ссылка на удалённый server-instructions.test.mjs убрана. Единственное упоминание EXCEPTIONS — теперь корректное отрицание, не стейл.
  • DO#2 server-instructions.ts:140 ✓ — коммент называет tool-inventory.test.mjs напрямую (было окольно «tool-specs.test.mjs's sibling»).
  • Остаточные упоминания server-instructions.test.mjs (server-instructions.ts:24, tool-inventory.test.mjs:10) — корректный ИСТОРИЧЕСКИЙ контекст («replaces the old… test», «now deleted»), не present-tense enforcement-заявление; вне scope Do (правильно).
  • Регрессии нет: изменение — markdown + один JSDoc-коммент, исполняемого кода не тронуто. Санити: mcp build (tsc) 0 (коммент well-formed), tool-inventory.test.mjs 4/4. Зелёный гейт round 1 (mcp 613/613, tsc 0, jest 257/257) + дословность прозы + мутационно-пришпиленные гарды — в силе, ничего не сдвинулось.

DO/ESCALATE/DROP нет. Обе документационные правки применены корректно и полностью, рассинхрон устранён, механика без изменений. Стопка Фазы 1б (#457→#458→#459→#460) полностью зелёная. Approve.

Round 2. Fix-round doc-only, топология чистая (prev head — предок). Оба стейл-рефа на удалённый тест закрыты; остаточные — историко-корректны. mcp build 0 + tool-inventory 4/4 подтверждают well-formed коммент; исполняемого кода фикс не трогал.

<!-- state:review reviewed_head=4cb762b0 round=2 verdict=approved --> ## Ре-ревью (round 2) — #460 `refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра (#448)` **Вердикт: PASS** ✅ — обе Do закрыты, новых проблем нет. Fix-round = один коммит `4cb762b0`, чисто поверх ранее отревьюенного `d0f99052` (без переписывания истории), трогает РОВНО 2 файла из round 1 — только доки, кода/логики/тестов не касался. <details> <summary>Верификация фиксов (клик)</summary> - **DO#1 `AGENTS.md`** ✓ — буллет полностью переписан под #448: инвентарь ГЕНЕРИРУЕТСЯ из реестра (`buildToolInventory` over `SHARED_TOOL_SPECS`), shared-спек авто-обновляет `<tool_inventory>` (ручная правка не нужна), только inline-тул требует строки в `INLINE_MCP_INVENTORY`, enforced by `tool-inventory.test.mjs`, явно «there is no EXCEPTIONS opt-out anymore». Ссылка на удалённый `server-instructions.test.mjs` убрана. Единственное упоминание EXCEPTIONS — теперь корректное отрицание, не стейл. - **DO#2 `server-instructions.ts:140`** ✓ — коммент называет `tool-inventory.test.mjs` напрямую (было окольно «tool-specs.test.mjs's sibling»). - **Остаточные упоминания** `server-instructions.test.mjs` (server-instructions.ts:24, tool-inventory.test.mjs:10) — корректный ИСТОРИЧЕСКИЙ контекст («replaces the old… test», «now deleted»), не present-tense enforcement-заявление; вне scope Do (правильно). - **Регрессии нет**: изменение — markdown + один JSDoc-коммент, исполняемого кода не тронуто. Санити: mcp build (tsc) **0** (коммент well-formed), tool-inventory.test.mjs **4/4**. Зелёный гейт round 1 (mcp 613/613, tsc 0, jest 257/257) + дословность прозы + мутационно-пришпиленные гарды — в силе, ничего не сдвинулось. </details> DO/ESCALATE/DROP нет. Обе документационные правки применены корректно и полностью, рассинхрон устранён, механика без изменений. Стопка Фазы 1б (#457→#458→#459→#460) полностью зелёная. Approve. <sub>Round 2. Fix-round doc-only, топология чистая (prev head — предок). Оба стейл-рефа на удалённый тест закрыты; остаточные — историко-корректны. mcp build 0 + tool-inventory 4/4 подтверждают well-formed коммент; исполняемого кода фикс не трогал.</sub>
agent_reviewer added review/approved and removed review/needs labels 2026-07-10 09:58:27 +03:00
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin refactor/448-generate-inventory:refactor/448-generate-inventory
git checkout refactor/448-generate-inventory
Sign in to join this conversation.