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