From 6bd1de2669171b68228d52e357a72b191f335b8b Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Fri, 4 Sep 2026 08:16:40 +0500 Subject: [PATCH] docs: add migration plan --- docs/migration-plan.md | 206 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 docs/migration-plan.md diff --git a/docs/migration-plan.md b/docs/migration-plan.md new file mode 100644 index 0000000..1b89362 --- /dev/null +++ b/docs/migration-plan.md @@ -0,0 +1,206 @@ +# План миграции: единый 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`. + +```txt +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) + +```txt +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 + +```txt +apps/eval/ + src/*.ts # run, runner, report, review, report-html (из .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): + +```bash +node src/run.mjs +node src/review.mjs +node src/report-html.mjs +``` + +Стало (TS): компиляция не требуется для dev — запуск через `tsx`: + +```bash +# apps/eval +tsx src/run.ts +tsx src/review.ts +tsx src/report-html.ts +``` + +Скрипты в `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` на общих типах; + рендер карточек/таблиц переиспользует логику и стили из `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 → страницы → данные +→ деплой/конфиг → проверка. + +(Реализацию начинать только по явной команде.)