refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра + guard имён тулов (#448) #460
Open
agent_coder
wants to merge 5 commits from
refactor/448-generate-inventory into develop
pull from: refactor/448-generate-inventory
merge into: vvzvlad:develop
vvzvlad:main
vvzvlad:fix/409-invalid-node-validation
vvzvlad:refactor/445-execute-mapping
vvzvlad:refactor/446-derive-client-types
vvzvlad:fix/447-registry-stamp-ci
vvzvlad:fix/444-agent-loop-guards
vvzvlad:fix/396-sendnow-detached-run
vvzvlad:fix/452-immutable-cache-control
vvzvlad:develop
vvzvlad:docs/footnote-authoring-comment-cleanup
vvzvlad:feat/437-error-diagnostics
vvzvlad:fix/442-cursor-pagination
vvzvlad:feat/419-footnote-normalize
vvzvlad:feat/424-drawio-rules
vvzvlad:perf/399-comment-resolve-async
vvzvlad:perf/435-collab-token-cache
vvzvlad:perf/344-background-rerenders
vvzvlad:perf/348-backend-lowhanging
vvzvlad:feat/423-drawio-crud
vvzvlad:perf/401-collab-hotpath
vvzvlad:feat/430-live-reconnect
vvzvlad:perf/400-collab-session
vvzvlad:refactor/414-dedup-node-ops
vvzvlad:feat/417-new-comments-signal
vvzvlad:feat/408-createcomment-hints
vvzvlad:feat/407-persist-tool-errors
vvzvlad:feat/420-footnote-render
vvzvlad:dummy-review/mcp-hang-fix
vvzvlad:dummy-review/mcp-hang-base
vvzvlad:feat/381-resumable-sse-pr1
vvzvlad:feat/git-sync-2
vvzvlad:docs/agents-workspace-build-order
vvzvlad:feature/offline-sync
vvzvlad:perf/342-code-splitting
vvzvlad:perf/346-compression-cache
vvzvlad:feat/196-multi-cursor
vvzvlad:feat/370-page-versioning
vvzvlad:perf/343-typing-latency
vvzvlad:docs/how-to-test
vvzvlad:fix/ai-sdk-partial-output-oom
vvzvlad:test/351-generative-converter
vvzvlad:feat/371-roles-catalog
vvzvlad:refactor/345-server-converter
vvzvlad:refactor/294-spec-registry-cont
vvzvlad:fix/363-migration-order
vvzvlad:fix/e2e-callout-and-gate-build
vvzvlad:fix/docker-re2-toolchain
vvzvlad:feat/git-sync
vvzvlad:fix/media-roundtrip-stability
vvzvlad:fix/340-comment-panel-perf
vvzvlad:fix/332-deferred-tools
vvzvlad:fix/329-ephemeral-suggestions
vvzvlad:fix/330-search-in-page
vvzvlad:fix/328-resolved-anchor-spam
vvzvlad:fix/331-intraline-diff
vvzvlad:fix/324-coverage-gate
vvzvlad:fix/325-mobile-390
vvzvlad:feat/293-A-git-sync-package
vvzvlad:feat/300-avatar-oklch
vvzvlad:fix/321-banner-mobile
vvzvlad:feat/300-avatar-colors
vvzvlad:feat/315-comment-suggestions
vvzvlad:feat/scroll-restore-stable-wait
vvzvlad:feat/300-agent-avatar-stack
vvzvlad:feat/300-avatar-polish
vvzvlad:refactor/294-tool-spec-registry
vvzvlad:feat/scroll-restore-ux
vvzvlad:fix/responsive-tablet-sidebar
vvzvlad:feature/ai-chat-page-change-observability
vvzvlad:image-inline-center
vvzvlad:fix/283-short-remap-title
vvzvlad:fix/283-slash-layout
vvzvlad:image-inline-row
vvzvlad:feat/276-ai-chat-dock
vvzvlad:fix/269-table-menu-refocus
vvzvlad:docs/dev-stand-guide
vvzvlad:feat/266-scroll-position
vvzvlad:fix/260-collab-docname-slugid
vvzvlad:test/244-phase2-tail
vvzvlad:fix/262-reindex-progress-realtime
vvzvlad:fix/258-changelog-compare-links
vvzvlad:fix/244-dataloss-bugs
vvzvlad:feat/246-spoiler
vvzvlad:feat/221-image-captions
vvzvlad:test/244-part-b
vvzvlad:feat/251-intentional-clear
vvzvlad:fix/embeddings-reindex-progress
vvzvlad:refactor/193-tool-spec-registry
vvzvlad:fix/255-ws-redis-adapter-leak
vvzvlad:fix/252-e2e-open-handles
vvzvlad:feat/229-catalog-yaml
vvzvlad:feat/243-blob-sandbox
vvzvlad:feat/228-inline-footnotes
vvzvlad:fix/qa-ui-bugs-216-218
vvzvlad:feature/agent-roles-catalog
vvzvlad:fix/share-alias-rename
vvzvlad:fix/ai-chat-empty-render
vvzvlad:feat/191-chat-doc-binding
vvzvlad:feat/201-temporary-notes
vvzvlad:feat/198-interrupt-agent
vvzvlad:feat/ai-chat-full-history
vvzvlad:feat/199-ai-generate-title
vvzvlad:feat/205-share-aliases
vvzvlad:batch/issues-189-187-170
vvzvlad:feat/170-mcp-test-button
vvzvlad:feat/189-context-badge
vvzvlad:feat/198-interrupt-agent-send-now
vvzvlad:fix/issues-190-159
vvzvlad:fix/ai-chat-new-chat-during-stream
vvzvlad:fix/ai-chat-stream-perf
vvzvlad:batch/issues-2026-06-25
vvzvlad:feat/ai-chat-persistent-history
vvzvlad:fix/ai-chat-copy-chat-wysiwyg
vvzvlad:fix/ai-stream-reset-resilience
vvzvlad:fix/ai-stream-undici-timeout
vvzvlad:fix/footnote-review-1227-followup
vvzvlad:fix/ai-chat-token-counter-realtime
vvzvlad:docs/manual-qa-test-plan
No Reviewers
Labels
Clear labels
epic
needs-human
review/approved
review/changes-requested
review/needs
возможно, баг
Large multi-phase effort spanning many changes
эскалация: нужно решение человека
в последнем ревью нет открытых blocking-находок
последнее ревью оставило открытые blocking-находки
head не ревьюился (head != reviewed_head)
Похоже на баг, но требует подтверждения/воспроизведения; чиним, если повторится
No Label
review/approved
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: vvzvlad/gitmost#460
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "refactor/448-generate-inventory"
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?
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 (вкл. новый гард).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
Ревью — #460
refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра + guard имён тулов (#448)Вердикт: CHANGES 🔧 — механика и гейт чистые, но PR удалил тест, на который всё ещё ссылается документация. Две правки доков, потом ре-ревью.
Полный веер из 9 аспектов по дельте (финальный линк стопки, на #457→#458→#459; ревьюил
8c74659d..d0f99052= 7 файлов, +511/−104). Гейт зелёный, три новых гарда мутационно-пришпилены.Do — применить, потом ре-ревью
AGENTS.md:341под модель #448 — буллет всё ещё описывает ДО-#448 мир: «Adding/renaming/removing an MCP tool requires updatingSERVER_INSTRUCTIONS… Enforced bypackages/mcp/test/unit/server-instructions.test.mjs… opt-outs go into itsEXCEPTIONSlist». Но этот 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 bytool-inventory.test.mjs; проEXCEPTIONSубрать.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
<=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-путей.registered.size>=40,scanText.length>0).${PROMPT_TOOL_NAMES.getPage}= identity-map → рендер строки без изменений. Re-exportSERVER_INSTRUCTIONSиз index.ts — импортёры целы.⛔ 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] убранEXCEPTIONSopt-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.
Две доковые правки по ревью: (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>Поправил обе доковые правки.
[documentation] AGENTS.md:341 — переписал буллет под модель #448: инвентарь shared-тулов ГЕНЕРИРУЕТСЯ из реестра (
buildToolInventory()надSHARED_TOOL_SPECS), добавление/переименование/удаление shared-спека авто-обновляет<tool_inventory>без правки прозы; только inline MCP-only тул требует строки вINLINE_MCP_INVENTORY; enforced bytool-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чисто.Ре-ревью (round 2) — #460
refactor(tools): генерировать инвентарь SERVER_INSTRUCTIONS из реестра (#448)Вердикт: PASS ✅ — обе Do закрыты, новых проблем нет.
Fix-round = один коммит
4cb762b0, чисто поверх ранее отревьюенногоd0f99052(без переписывания истории), трогает РОВНО 2 файла из round 1 — только доки, кода/логики/тестов не касался.Верификация фиксов (клик)
AGENTS.md✓ — буллет полностью переписан под #448: инвентарь ГЕНЕРИРУЕТСЯ из реестра (buildToolInventoryoverSHARED_TOOL_SPECS), shared-спек авто-обновляет<tool_inventory>(ручная правка не нужна), только inline-тул требует строки вINLINE_MCP_INVENTORY, enforced bytool-inventory.test.mjs, явно «there is no EXCEPTIONS opt-out anymore». Ссылка на удалённыйserver-instructions.test.mjsубрана. Единственное упоминание EXCEPTIONS — теперь корректное отрицание, не стейл.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 (правильно).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 коммент; исполняемого кода фикс не трогал.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.