fix(ci,mcp): REGISTRY_STAMP в build-артефакте + кросс-пакетный CI-прогон — закрыть skew build/ vs src/ и «guard в чужом пакете» #447

Open
opened 2026-07-10 06:51:26 +03:00 by agent_vscode · 0 comments
Collaborator

Зачем

Два структурных слепых пятна, из-за которых parity-guard'ы не спасают:

1. Skew build/ vs src/. Рантайм сервера грузит скомпилированный packages/mcp/build/index.js (docmost-client.loader.ts: require.resolve('@docmost/mcp')main: ./build/index.js; build/ в .gitignore, untracked). А все серверные guard-тесты читают исходники: shared-tool-specs.contract.spec.ts и tool-tiers.spec.ts импортируют ../../../../../../packages/mcp/src/tool-specs. Правка src/tool-specs.ts без пересборки → тесты зелёные, работающий сервер расходится со спеками. Loader ловит только полное отсутствие реестра («rebuild the package»), не по-тульный дрейф.

2. Guard в чужом пакете. Спеки добавляют в packages/mcp, а parity/phantom-catalog-тесты живут в jest-сьюте apps/server. PR #434 (drawio) трогал только packages/mcp — автор прогнал mcp-тесты, всё зелёное; сломанный in-app обнаружился уже на develop CI после мёржа (чинилось постфактум в f46d89ea).

Механика

  1. REGISTRY_STAMP: на этапе tsc/pretest генерировать в build константу-хэш содержимого tool-specs.ts (имена+схемы+описания). Loader в dev/test сверяет хэш загруженного build с хэшом, вычисленным от src, и падает с внятным «stale build — rebuild @docmost/mcp». В prod (где src нет) — no-op.
  2. Кросс-пакетный CI: PR, трогающий packages/mcp/** ИЛИ apps/server/src/core/ai-chat/**, обязан прогонять оба тест-сьюта (mcp node:test + серверный jest тулов). Реализация — path-фильтр в Gitea Actions workflow.
  3. Опционально: dev-скрипт watch уже есть (pnpm --filter @docmost/mcp watch) — упомянуть в AGENTS.md как обязательный при правке спеков.

Критерии приёмки

  • Правка src/tool-specs.ts без пересборки → красный локальный прогон серверных тестов/старта dev-сервера с сообщением про stale build.
  • PR, добавляющий спек в packages/mcp без in-app-проводки, краснеет в CI самого PR, а не на develop после мёржа.

Примечание: после #445 (автопроводка) класс «забыли провести in-app» умирает по построению, но stamp остаётся полезен — он ловит любой дрейф стейл-артефакта (описания, схемы, tier), а кросс-пакетный CI — любые будущие межпакетные контракты.

Связано: #416 (роадмап), #445, #446; коммит f46d89ea (PR #434).

## Зачем Два структурных слепых пятна, из-за которых parity-guard'ы не спасают: **1. Skew `build/` vs `src/`.** Рантайм сервера грузит **скомпилированный** `packages/mcp/build/index.js` (`docmost-client.loader.ts`: `require.resolve('@docmost/mcp')` → `main: ./build/index.js`; `build/` в .gitignore, untracked). А **все серверные guard-тесты читают исходники**: `shared-tool-specs.contract.spec.ts` и `tool-tiers.spec.ts` импортируют `../../../../../../packages/mcp/src/tool-specs`. Правка `src/tool-specs.ts` без пересборки → тесты зелёные, работающий сервер расходится со спеками. Loader ловит только полное отсутствие реестра («rebuild the package»), не по-тульный дрейф. **2. Guard в чужом пакете.** Спеки добавляют в `packages/mcp`, а parity/phantom-catalog-тесты живут в jest-сьюте `apps/server`. PR #434 (drawio) трогал только `packages/mcp` — автор прогнал mcp-тесты, всё зелёное; сломанный in-app обнаружился уже на develop CI после мёржа (чинилось постфактум в f46d89ea). ## Механика 1. **REGISTRY_STAMP**: на этапе `tsc`/`pretest` генерировать в build константу-хэш содержимого `tool-specs.ts` (имена+схемы+описания). Loader в dev/test сверяет хэш загруженного build с хэшом, вычисленным от `src`, и падает с внятным «stale build — rebuild @docmost/mcp». В prod (где `src` нет) — no-op. 2. **Кросс-пакетный CI**: PR, трогающий `packages/mcp/**` ИЛИ `apps/server/src/core/ai-chat/**`, обязан прогонять **оба** тест-сьюта (mcp node:test + серверный jest тулов). Реализация — path-фильтр в Gitea Actions workflow. 3. Опционально: dev-скрипт `watch` уже есть (`pnpm --filter @docmost/mcp watch`) — упомянуть в AGENTS.md как обязательный при правке спеков. ## Критерии приёмки - Правка `src/tool-specs.ts` без пересборки → красный локальный прогон серверных тестов/старта dev-сервера с сообщением про stale build. - PR, добавляющий спек в `packages/mcp` без in-app-проводки, краснеет **в CI самого PR**, а не на develop после мёржа. Примечание: после #445 (автопроводка) класс «забыли провести in-app» умирает по построению, но stamp остаётся полезен — он ловит любой дрейф стейл-артефакта (описания, схемы, tier), а кросс-пакетный CI — любые будущие межпакетные контракты. Связано: #416 (роадмап), #445, #446; коммит f46d89ea (PR #434).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#447