10 KiB
План миграции: единый SvelteKit-проект + типизированный eval
Статус: утверждён для проработки (запуск реализации — по отдельной команде). Последнее обновление: 2026-09-04
1. Общая цель
Убрать избыточное разделение на два проекта и перевести всё в один SvelteKit-проект
на Vercel, а eval-harness — с JavaScript (.mjs) на TypeScript, с общими типами
между eval и сайтом.
Итог: один домен, один деплой, один контракт данных для отчётов (он не «ломается», потому что eval и рендер сидят на одних типах).
2. Целевая архитектура
2.1. Общий пакет типов — packages/types
Workspace-пакет @duck/types, используемый и eval, и apps/web.
packages/types/
package.json # name: "@duck/types" (через pnpm pkg)
tsconfig.json
src/index.ts # общий контракт
Типы (защищают контракт отчёта):
Task { id, question, answer }ScenarioName = "control" | "blind" | "mentor"ScenarioSummary { tasks, reviewed, correct, accuracy, pending, duckUsed, toolCalls, avgCalls }PerTaskRow { id, scenario, correct: boolean|null, duckUsed, toolCalls, promptTokens, genTokens, duckTokens, response, expected, question }ModelReport,ReportRoot { generatedAt, mcpUrl, prompts, models, aggregate, reviewedAt? }Reviews(контрактreview.json)
Роль: и apps/eval при записи out/report.json, и apps/web при рендере /reports
используют эти типы. Рассогласование схемы → ошибка на этапе компиляции, а не падение в проде.
2.2. Приложение — apps/web (единственный деплой на Vercel)
apps/web/ # SvelteKit + TypeScript + @sveltejs/adapter-vercel
src/routes/
+layout.svelte # общий nav-каркас
+page.svelte # / — домашняя (заглушка «скоро»)
/mcp/+page.svelte # /mcp — описание MCP + FAQ/README
/reports/+page.svelte # /reports — полные отчёты (рендер из report.json)
/api/mcp/+server.ts # /api/mcp — MCP endpoint (mcp-handler)
src/lib/
mcp.ts # перенос из apps/mcp/lib/mcp.ts
reports.ts # рендер-хелперы на базе @duck/types
static/report.json # коммитится — источник для /reports
Домен: rubber-duck-mcp.vercel.app — единственный. Всё на нём:
/→ домашняя/mcp→ описание/reports→ отчёты/api/mcp→ MCP endpoint
2.3. Eval — типизация в TS
apps/eval/
src/*.ts # run, runner, report, review (из .mjs)
lib/mcpClient.ts # (из lib/mcpClient.mjs)
lib/ollama.ts # (из lib/ollama.mjs)
tsconfig.json
out/report.json # генерируется (НЕ коммитится)
data/tasks.json # (как есть)
3. Все решённые вопросы (закрытые решения)
| Вопрос | Решение |
|---|---|
| Домен | единый rubber-duck-mcp.vercel.app |
| Куда класть SvelteKit | новая папка apps/web |
| Линковка Vercel | перелинковать существующий project mcp на apps/web (домен сохр.) |
| Frontend-домен | удалить rubber-duck-frontend.vercel.app и Vercel-проект frontend |
report.json в проде |
коммитить в apps/web/static/report.json |
Страница /reports |
полный формат (сводные таблицы по моделям + разбивка по задачам) |
| MCP-фреймворк | mcp-handler совместим с SvelteKit (web-standard (Request) => Response), Next не нужен |
| Язык eval | TypeScript + общий пакет типов |
4. Изменение запуска (было → стало)
Сейчас (JS):
node src/run.mjs
node src/review.mjs
Стало (TS): компиляция не требуется для dev — запуск через tsx:
# apps/eval
tsx src/run.ts
tsx src/review.ts
Локальная генерация статического
report.html(report-html) убрана:/reportsна сайте рендерит те же данные изreport.jsonчерез Svelte-компоненты на общих типах.
Скрипты в apps/eval/package.json и корневом package.json (eval:*) обновляются на tsx.
Добавляется:
- typecheck:
tsc --noEmitдля eval и web (контракт не ломается). - dev-зависимости eval:
tsx,typescript,@types/node.
5. Шаги реализации (поэтапно)
Шаг 1 — packages/types
- Создать workspace-пакет
@duck/types(манифест черезpnpm pkg). - Написать
src/index.tsс общим контрактом +tsconfig.json. - Убедиться, что pnpm-workspace (
packages: apps/*) знает проpackages/*.
Шаг 2 — eval → TypeScript
- Переименовать
lib/*.mjs→.ts,src/*.mjs→.ts. - Подключить
@duck/types, поправить импорты. - Добавить
tsconfig.json, зависимости (tsx,typescript,@types/node) черезpnpm pkg/pnpm add. - Обновить скрипты запуска (
eval:*→tsx ...). - Проверка:
tsc --noEmit+ короткий прогонtsx src/run.ts --limit 1.
Шаг 3 — apps/web (SvelteKit)
- Инициализировать SvelteKit + TypeScript +
@sveltejs/adapter-vercel. - Подключить
@duck/types.
Шаг 4 — Перенос MCP
apps/mcp/lib/mcp.ts→apps/web/src/lib/mcp.ts.apps/mcp/app/api/mcp/route.ts→apps/web/src/routes/api/mcp/+server.ts(mcp-handler принимаетRequest→ из SvelteKit передаёмevent.request).- Убедиться, что
runtime = "nodejs"задан.
Шаг 5 — Страницы
+layout.svelte— навигация;/— заглушка «скоро» (дизайн позже);/mcp— описание + FAQ + README (перенести текст из старойpage.tsx);/reports—loadизstatic/report.jsonчерезlib/reports.tsна общих типах; рендер карточек/таблиц — Svelte-компоненты (визуальный стиль перенесён из прежнегоreport-html.mjs).
Шаг 6 — Данные
- Скопировать
apps/eval/out/report.json→apps/web/static/report.jsonи закоммитить. - Добавить команду «sync отчёта на сайт» (копирует report.json после прогона eval).
Шаг 7 — Деплой/конфиг
apps/web/package.json+ корневой:dev,build,deploy→apps/web;eval:*→tsx; убратьdeploy-mcp,deploy-frontend.- Удалить
apps/frontend+ скрипты + Vercel-проект/домен frontend. - Удалить
apps/mcp(Next) после переноса. - Перелинковать Vercel-проект
mcpнаapps/web; проверить, что домен назначен на проект.
Шаг 8 — Проверка
tsc --noEmit(eval + web).pnpm dev→ проверить страницы и/api/mcp.vercel --prod→ verify на домене:/,/mcp,/reports,/api/mcp(quack).
6. Что НЕ делаем сейчас
- Детальный дизайн страниц/домашней (делаем позднее, отдельно).
- Автоматическое обновление
report.jsonна каждый прогон (только sync-команда). - Расширенное наполнение FAQ/README (только перенос базового текста).
7. Риски и митигация
| Риск | Митигация |
|---|---|
mcp-handler под Next |
фреймворк-агностичен (web-standard Request/Response), проверено по d.ts |
| Нужна компиляция для запуска eval | dev — tsx; при необходимости tsc build для prod-скриптов |
| Несовместимость схемы отчёта | общие типы @duck/types + tsc --noEmit в eval и web |
| Необратимое удаление Vercel-проектов | frontend/mcp удаляем аккуратно, после успешного переноса |
report.json рассинхронизируется с прогоном |
явная команда sync + коммит |
8. Порядок выполнения
Поэтапно, с проверкой на каждом шаге:
packages/types → eval-TS → apps/web (скелет) → перенос MCP → страницы → данные
→ деплой/конфиг → проверка.
(Реализацию начинать только по явной команде.)