mcp__mappa__handoff_write (per-project, append-only, versioned-история, поля session_id/date/status/summary/open_treks/ask_user/guards/recent_commits, решение 14/гриллинг Q5). Чтение — entity_search(type=handoff). Без лиза, без файлов, без git-стеджинга. Ритуал закрытия сохранён (propose-only).
114 lines
10 KiB
Markdown
114 lines
10 KiB
Markdown
---
|
||
name: session-handoff
|
||
author: ours
|
||
version: 1.0.0
|
||
description: "Sliding handoff между сессиями через handoff-сущность Mappa (решение 14, гриллинг Q5): per-project, versioned-история, замена .tasks/NEXT_SESSION.md. Read on session start: orient agent, ask user before action. Write on session-end phrase or substantive commit. On session-end the agent ALSO runs the closing ritual on its own (idea 7: no invitation needed): handoff write + PROPOSE wiki-ingest + PROPOSE task-board closes — mutations only after user confirmation. Session-end phrases: «завершаем сессию», «сворачиваемся», «закругляемся», «wrap up session», «end session», «we're done for now». Trigger-line in AGENTS.md: `session handoff: read on start, write on end`. Skip task-zone phrases: «закрываем эту таску», «pause», «отбой», «разбегаемся»."
|
||
---
|
||
|
||
# session-handoff
|
||
|
||
Sliding handoff между сессиями. Канал — **handoff-сущность Mappa** (`mcp__mappa__handoff_write`, тип `h:`, per-project): поля `session_id`/`date`/`status`/`summary`/`open_treks[]`/`ask_user[]`/`guards[]`/`recent_commits[]`. Каждый write = **новая версия** (append-only, versioned-история) — файлового `.tasks/NEXT_SESSION.md` больше нет, git-история не нужна.
|
||
|
||
На старте — читает последний handoff проекта, ориентирует агента и спрашивает user'а перед действиями. При substantive commit'е или session-end фразе — пишет новый handoff для следующей сессии.
|
||
|
||
Forward-looking, не timeline: handoff = связка новых вещей конкретно для следующего разворота, не overview всего проекта. STATUS.md-эквиваленты (борд mappa) / вики остаются авторитетными для своего scope'а.
|
||
|
||
## MCP-поверхность
|
||
|
||
| Операция | Тул | Примечание |
|
||
|---|---|---|
|
||
| Запись handoff | `mcp__mappa__handoff_write(project, session_id, status, summary, open_treks?, ask_user?, guards?, recent_commits?)` | append-only; без лиза (как инбокс) |
|
||
| Чтение последнего | `mcp__mappa__entity_search(q, type='handoff', project=<имя>, limit=1)` | ORDER BY created_at DESC → первый = последний |
|
||
| Полное чтение версии | `mcp__mappa__entity_get(id)` | id internal из search |
|
||
|
||
`status` ∈ `active | paused | done`. Поля-массивы (open_treks/ask_user/guards/recent_commits) — строковые массивы; пустые секции передавать как `[]` (аналог пометки «(нет на этом раунде)» — next агент видит: пусто, не забыто).
|
||
|
||
## When to use
|
||
|
||
**Read mode (session start):**
|
||
- AGENTS.md проекта содержит trigger-строку `session handoff: read on start, write on end`.
|
||
- В mappa есть handoff-сущности проекта (search не пуст).
|
||
|
||
**Write mode (session end / substantive commit):**
|
||
- User'ская фраза из whitelist:
|
||
- русский: «завершаем сессию», «сворачиваемся», «закругляемся»
|
||
- английский: «wrap up session», «end session», «we're done for now»
|
||
- ИЛИ — agent только что сделал substantive commit. Эвристика:
|
||
- prefix НЕ в (`meta:`|`docs:`|`style:`|`chore:`|`fix typo`)
|
||
- AND (body length > 200 символов OR files changed > 3)
|
||
- Плюс: **первый** non-trivial commit сессии — всегда триггерит, даже если ниже порога (старт работы = context shift).
|
||
|
||
**Skip (false-positive guards):**
|
||
- «закрываем эту таску» — task close, не session. Это зона using-tasks.
|
||
- «pause», «приостанови» — task-pause, не session-end.
|
||
- «отбой», «разбегаемся» — слишком broad.
|
||
- «сейчас завершу одну задачу и тогда поговорим» — частичное завершение.
|
||
- Проект не в mappa / нет handoff-сущностей — silent exit.
|
||
- AGENTS.md проекта НЕ содержит trigger-строку — silent exit.
|
||
|
||
При неоднозначности — **ASK**, не угадывать: «закрываем сессию или таску?»
|
||
|
||
## Steps
|
||
|
||
### Read mode
|
||
|
||
1. **Detect.** `mcp__mappa__entity_search(q='', type='handoff', project=<имя проекта>, limit=1)` — если пусто, silent exit (первая сессия проекта).
|
||
2. **Staleness check.** `meta.date` последнего handoff'а. Возраст > 7 дней → отметить user'у:
|
||
```
|
||
handoff от <date> (N дней назад) — возможно устарел.
|
||
Оверрайдить или продолжить?
|
||
```
|
||
Дождаться ответа перед продолжением.
|
||
3. **Summarize.** Прочитать мета последнего: summary / open_treks / ask_user / guards / recent_commits.
|
||
4. **Orient.** Пересказать user'у одним блоком: «прошлая сессия предложила X (open треки + ask-items + guards). Делаем?»
|
||
5. **Wait.** Не делать никаких действий до подтверждения user'ом. Default = orient + ask, **никакого auto-execute**.
|
||
|
||
### Write mode
|
||
|
||
1. **Scope check.** Это текущий проект (cwd). Никаких global мутаций, никаких других проектов.
|
||
2. **Mid-task capture.** Если есть 🔴 active таска проекта (борд mappa / `.tasks/`) — захватить в summary:
|
||
```
|
||
left mid-task: <slug>
|
||
where_stopped: <одна строка>
|
||
```
|
||
3. **Compose content.** Собрать поля handoff:
|
||
- `session_id` — `<ISO дата>` или идентификатор сессии;
|
||
- `status` — `active` (работа продолжается) / `paused` (заморожено) / `done` (завершено);
|
||
- `summary` — связка: где остановились, mid-task, ключевые решения;
|
||
- `open_treks` — массив открытых треков (готовность + entry-point);
|
||
- `ask_user` — pending решения / ожидаемые разрешения;
|
||
- `guards` — «не делать» (preemptive guards);
|
||
- `recent_commits` — 3–5 последних коммитов (`<slug>: <subject>`).
|
||
4. **Append.** `mcp__mappa__handoff_write(project=<имя>, ...)` — сервис создаёт новую версию `h:N` (versioned-история; предыдущие версии остаются, `entity_search` вернёт свежую).
|
||
5. **Closing ritual (idea 7).** На session-end фразе (НЕ на substantive commit) после handoff-write агент сам, без приглашения, предлагает закрытие:
|
||
- **(2) Propose wiki-ingest.** Если за сессию появилось durable-знание — ПРЕДЛОЖИТЬ ingest (using-wiki v2: mappa wiki_create/update под лизом), перечислив кандидатов. Ничего не писать без подтверждения.
|
||
- **(3) Propose task-board closes.** Если есть задачи, выглядящие закрытыми — ПРЕДЛОЖИТЬ закрытия (using-tasks / mappa task_close под лизом). Уважать ralph-loop: verifier-задачи закрывать только через verifier.
|
||
- Формат — один блок: «Ритуал закрытия: (а) заингестить X в вики? (б) закрыть Y? (в) ничего.» Ждать ответа. Отказ = пропуск.
|
||
|
||
## Failure modes
|
||
|
||
- **AGENTS.md без trigger-строки** → silent exit. Скил project-opt-in.
|
||
- **Проект не в mappa / нет handoff-сущностей** → silent exit.
|
||
- **Stale handoff (> 7 дней)** в read mode → не silent, **спросить** user'а оверрайдить или продолжить.
|
||
- **Неоднозначная фраза** → ASK «закрываем сессию или таску?», не угадывать.
|
||
- **Secret detected.** Контент матчит паттерны секретов (`AKIA...`, `sk-...`, `ghp_...`, `ssh-rsa`, `BEGIN PRIVATE KEY`, `password=`/`token=`) → **abort write**. Сообщить user'у с указанием подозрительной строки.
|
||
- **Mid-task без борда** → писать handoff без mid-task секции, не блокировать.
|
||
- **Ритуал: user отказал** → пропустить, не настаивать, не повторять в этой сессии.
|
||
|
||
## Side effects
|
||
|
||
- Пишет handoff-сущность проекта (append-only, versioned-история). Никаких файлов, никаких git-коммитов за handoff.
|
||
- Ритуал закрытия предлагает wiki-ingest и закрытия тасок — но НЕ пишет их.
|
||
- Никаких global мутаций, никаких других проектов, никаких user-level config writes.
|
||
|
||
## What NOT to do
|
||
|
||
- **Не auto-execute** действия из read handoff'а. Default = orient + ask.
|
||
- **Не писать в вики / не закрывать таски по ритуалу молча.** Ритуал = предложения. Каждая мутация — после явного «да».
|
||
- **Не гонять ритуал на substantive commit.** Только session-end фраза.
|
||
- **Не писать секреты** в handoff. Если контент матчит secret-patterns — abort.
|
||
- **Не на каждом commit'е.** Только substantive (см. эвристику).
|
||
- **Не дублировать борд / вики.** Handoff = forward-looking связка, не overview.
|
||
- **Не cross-project.** Per-project scope.
|
||
- **Не считать handoff авторитетным** на стороне читателя. Это рекомендация прошлой сессии, не директива. User может override любую её часть.
|