plot-gate
by greebo3661
README.md
# plot-gate
Сервис, который **не даёт взять работу**, пока не ясны цель участка, линейка планов и взгляды интересантов. Если условие нарушено — открывается **стоп**, и следующий слот не стартует.
Это не тикетница и не чат. Это контрольная плоскость: можно ли начинать, согласован ли план, не уехал ли результат от идеала.
- REST `/v1/*` и MCP `/mcp` (Bearer)
- Тонкая админка `/admin`
- Состояние в SQLite (`./data`)
- Языковые судьи — через LLM Orchestra (локальная модель, облако не используется)
Операторский контур нашей лаборатории: [OUR-USAGE.md](OUR-USAGE.md).
## На входе
Вы отдаёте сервису **смысл работы**, не код и не тикеты.
| Что приходит | Зачем | Обязательно до слота |
|---|---|---|
| **Проект** + **идеал** | Общая картина «как должно быть для интересантов» | идеал нужен к закрытию слота |
| **Участок** (`plot`) + **цель** | Что именно меняем и зачем | цель не пустая |
| **Анализ проблем** и улучшения | Контекст участка | нет |
| **Узел** | Место работы (экран, процесс, договор) | нет |
| **Линейка планов** (≥ 2) | Есть из чего выбрать | минимум два плана |
| У плана: путь, **как пользователь увидит результат** (`user_sees`), обязательные условия | Иначе ворота не пустят | `user_sees` не пустой |
| Три взгляда: **user / owner / economy** — желаемое и опасения | Ворота интересантов | все три заполнены |
| **Бриф** (текст) | Только для черновика участков и планов | нет, черновик не пишется в БД сам |
| **Результат работы** (текст) | На закрытии слота судья сверяет с идеалом | да, на `complete` |
Жёсткие ворота **без LLM**: пустая цель, один план, пустой `user_sees`, нет взглядов, уже есть открытый стоп, нет свободного потока.
Языковые ворота **через Orchestra**: согласовать план (`agree`) и закрыть слот сверкой с идеалом (`complete`).
## На выходе
| Что получаете | Когда |
|---|---|
| **Доска проекта** (`/board`) | Участки, планы, взгляды, слоты, стопы, журнал |
| **Слот** со статусом `requested` | Ворота пройдены, работу можно брать |
| **409 + стопы** | Ворота не пустили; читайте причины, чините, зовите слот снова |
| Вердикт судьи `pass` / `fail` | После `agree` или `complete` |
| Слот `agreed` → работа → `verified` или `failed` | Закрытие сверяет результат с идеалом |
| **Журнал** | Что сделали по слоту |
| **Срез нагрузки** | Сколько слотов занято, есть ли стоп, заблокирован ли проект |
| Черновик участков/планов или пересмотра | Предложение модели, **в базу само не пишется** |
Формат REST одинаковый:
```json
{ "success": true, "data": { }, "error": null }
```
На ошибке: `success: false`, текст в `error`. Health жив, пока жив SQLite; Orchestra — отдельный флаг `orchestra: up|down`.
## Как интегрировать
Три входа, один ключ `PLOT_GATE_API_KEY`. Судьям нужен второй ключ — `ORCHESTRA_API_KEY` (только внутри контейнера).
### 1. Поднять контейнер
Нужен Docker. Сеть Orchestra создайте заранее (даже если судьи ещё не нужны — так требует compose):
```bash
docker network create llm-orchestra-net
git clone https://github.com/greebo3661/plot-gate.git
cd plot-gate
cp .env.example .env
```
В `.env` задайте длинный `PLOT_GATE_API_KEY`. Для чужой машины, не нашей лаборатории:
```
PLOT_GATE_HTTP_BIND=127.0.0.1
```
```bash
docker compose up -d --build
curl -s http://127.0.0.1:19660/health
```
Без Orchestra CRUD, доска, жёсткие ворота и админка работают. Кнопки «Черновик / Согласовать / Закрыть» вернут `503 orchestra_unavailable`, пока не заполнены `ORCHESTRA_*` и id четырёх промптов.
Промпты-канон: [`prompts/orchestra-seed/`](prompts/orchestra-seed/). Их копируют в Prompt studio Orchestra, id пишут в `.env`.
### 2. REST из своего кода
База: `http://<хост>:19660`. Заголовок: `Authorization: Bearer <PLOT_GATE_API_KEY>`.
Типовой цикл:
```http
POST /v1/projects
{ "name": "Зал", "ideal": "гость понимает схему за 10 секунд" }
POST /v1/projects/{id}/plots
{ "title": "Навигация", "goal": "гость находит свой ряд" }
POST /v1/plots/{plot_id}/plans
{ "title": "Схема у входа", "user_sees": "плакат с рядами у двери" }
PUT /v1/projects/{id}/stakeholders/user
{ "desired": "не плутать", "concerns": "мелкий шрифт" }
```
То же для `owner` и `economy`. Потом:
```http
GET /v1/projects/{id}/load # свободно ли
POST /v1/projects/{id}/slots { "plan_id": 1 }
POST /v1/slots/{slot_id}/agree
POST /v1/slots/{slot_id}/journal { "entry": "повесили макет" }
POST /v1/slots/{slot_id}/complete { "result": "гость указывает ряд с порога" }
GET /v1/projects/{id}/board
GET /v1/projects/{id}/stops # если было 409
```
Черновик из брифа (не сохраняется сам):
```http
POST /v1/projects/{id}/draft
{ "brief": "надо чтобы люди не терялись в зале" }
```
Админка для глаз: `http://<хост>:19660/admin`.
### 3. MCP в Cursor / агенте
Прямое подключение, не через хаб:
```json
{
"mcpServers": {
"plot-gate": {
"url": "http://127.0.0.1:19660/mcp",
"headers": { "Authorization": "Bearer ${env:PLOT_GATE_API_KEY}" }
}
}
}
```
Инструменты один в один с API: `list_projects`, `get_project`, `upsert_plot`, `upsert_node`, `add_plan`, `set_stakeholder`, `set_ideal`, `get_load`, `request_slot`, `agree_slot`, `complete_slot`, `append_journal`, `review_plot`, `draft_from_brief`, `list_stops`.
## Тесты
```bash
python -m pytest tests/ -q
```
Orchestra замокана, GPU не нужен.
## Чего здесь нет
- Нет GPU, Postgres, Redis, поиска.
- Нет облачной LLM: судьи только через Orchestra на вашей машине.
- `.env` в git не кладётся.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues