docs: add migration plan
This commit is contained in:
@@ -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 → страницы → данные
|
||||||
|
→ деплой/конфиг → проверка.
|
||||||
|
|
||||||
|
(Реализацию начинать только по явной команде.)
|
||||||
Reference in New Issue
Block a user