Skip to main content
Glama
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 не кладётся.

Maintenance

ActivityMaintained
ResponsivenessNo issues