diff --git a/skills/session-handoff/SKILL.md b/skills/session-handoff/SKILL.md index 3bcf991..974af04 100644 --- a/skills/session-handoff/SKILL.md +++ b/skills/session-handoff/SKILL.md @@ -1,35 +1,134 @@ --- name: session-handoff -version: 0.1.0 +version: 0.2.0 description: Sliding handoff между CC сессиями через `.tasks/NEXT_SESSION.md`. Read on start (orient + ask user'а перед действиями), write on substantive-commit (prefix не meta/docs/style/chore + body>200 OR files>3; первый non-trivial commit сессии всегда) или session-end фразе («завершаем сессию», «сворачиваемся», «закругляемся», «wrap up session», «end session», «we're done for now»). Триггер-строка CLAUDE.md `session handoff: read on start, write on end`. Sliding overwrite — один файл, история через git log. Project-scope, никакого global state. НЕ триггерится на «закрываем эту таску», «pause», «отбой», «разбегаемся» — task-zone / non-session phrases. --- # session-handoff -Sliding handoff prompt между CC сессиями. На старте сессии — читает `.tasks/NEXT_SESSION.md`, ориентирует агента и спрашивает user'а перед действиями. При substantive commit'е или session-end фразе — перезаписывает handoff для следующей сессии. Sliding overwrite: один файл, история — через `git log -p .tasks/NEXT_SESSION.md`. +Sliding handoff prompt между CC сессиями. На старте — читает `.tasks/NEXT_SESSION.md`, ориентирует агента и спрашивает user'а перед действиями. При substantive commit'е или session-end фразе — перезаписывает handoff для следующей сессии. Sliding overwrite: один файл, история — через `git log -p .tasks/NEXT_SESSION.md`. -Дизайн-источник (обязательно прочитать перед заполнением тела): `.workshop/.archive/2026-05-24-session-handoff-skill.md` (Round 1 design + Round 2 resolved Q1–Q10). +Forward-looking, не timeline: handoff = связка новых вещей конкретно для следующего разворота, не overview всего проекта. STATUS.md / MEMORY.md / `.wiki/log.md` остаются авторитетными для своего scope'а. + +Дизайн-источник: `~/projects/.workshop/.archive/2026-05-24-session-handoff-skill.md` (Round 1 design + Round 2 resolved Q1–Q10). ## When to use -<пусто — дописывается во втором проходе глазами по архивному буферу> +**Read mode (session start):** +- CLAUDE.md проекта содержит trigger-строку `session handoff: read on start, write on end`. +- Файл `.tasks/NEXT_SESSION.md` существует. + +**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. Это zone `using-tasks`. +- «pause», «приостанови» — task-pause, не session-end. +- «отбой», «разбегаемся» — слишком broad, может относиться к другому контексту. +- «сейчас завершу одну задачу и тогда поговорим» — частичное завершение. +- Не-git папка, или `.tasks/` отсутствует — silent exit. +- CLAUDE.md проекта НЕ содержит trigger-строку — silent exit. + +При неоднозначности — **ASK**, не угадывать: «закрываем сессию или таску?» ## Inputs -<пусто> +**Read mode:** +- `.tasks/NEXT_SESSION.md` — sliding handoff, должен существовать. +- Текущая дата (для staleness check против `_last_updated_`). + +**Write mode:** +- `git log --oneline -5` — последние commits сессии. +- `.tasks/STATUS.md` — open треки + 🔴 active task'и (для mid-task capture). +- Контекст сессии — pending user-decisions, waiting permissions, memory updates, preemptive guards. ## Steps -<пусто> +### Read mode + +1. **Detect.** Проверить что `.tasks/NEXT_SESSION.md` существует. Нет — silent exit. +2. **Staleness check.** Прочитать frontmatter `_last_updated_`. Возраст > 7 дней → отметить user'у: + ``` + handoff от (N дней назад) — возможно устарел. + Оверrайдить или продолжить? + ``` + Дождаться ответа перед продолжением. +3. **Summarize.** Прочитать тело handoff'а — 5 секций (recent commits / open треки / спроси user'а / не делать / memory updates). +4. **Orient.** Пересказать user'у одним блоком: «прошлая сессия предложила X (open треки + ask-items + don't-items + memory updates). Делаем?» +5. **Wait.** Не делать никаких действий до подтверждения user'ом. Default = orient + ask, **никакого auto-execute**. + +### Write mode + +1. **Scope check.** Это текущий проект (cwd с `.tasks/`). Никаких global мутаций, никаких других проектов. +2. **Mid-task capture.** Если в `.tasks/STATUS.md` есть 🔴 active task — захватить: + ``` + left mid-task: + where_stopped: <текст из STATUS.md> + ``` +3. **Compose content.** Собрать `.tasks/NEXT_SESSION.md`: + ```markdown + --- + _last_updated_: + session_id: + --- + + # Next session handoff + + ## Recent commits + - : (3–5 последних) + ... + + ## Open треки + | Трек | Готовность | Entry-point | + |---|---|---| + | ... | ... | ... | + + ## Спроси user'а + - + - + + ## Не делать (preemptive guards) + - + - + + ## Memory updates за сессию + - <что нового сохранилось / обновилось> + ``` + Пустую секцию — оставить заголовок + пометка `(нет на этом раунде)`. Чтобы next агент видел: не забыто, а пусто. +4. **Sliding overwrite.** `Write` поверх `.tasks/NEXT_SESSION.md` (предыдущее содержимое НЕ архивируется в `.archive/handoff-*.md` — sliding contract). История восстанавливается через `git log -p .tasks/NEXT_SESSION.md`. +5. **Stage.** `git add .tasks/NEXT_SESSION.md` — попадает в следующий commit сессии (или в текущий, если запись была вызвана session-end фразой). ## Failure modes -<пусто> +- **CLAUDE.md без trigger-строки** → silent exit, не вмешиваться. Скил project-opt-in. +- **Не git-repo / `.tasks/` отсутствует** → silent exit. Скил требует обоих условий. +- **`.tasks/NEXT_SESSION.md` отсутствует** в read mode → silent exit (первая сессия проекта, нечего читать). +- **Неоднозначная фраза** («закругляемся» в контексте отдельной таски, а не сессии) → ASK user'а «закрываем сессию или таску?», не угадывать. +- **Secret detected.** Содержимое handoff'а матчит паттерны секретов (`AKIA...`, `sk-...`, `ghp_...`, `ssh-rsa`, `BEGIN PRIVATE KEY`, JWT в обычном виде, `password=`/`token=` без obfuscation) → **abort write**, не записывать. Файл идёт в git — не место для credentials. Сообщить user'у с указанием подозрительной строки, дать дочистить контекст руками. +- **Stale handoff (> 7 дней)** в read mode → не silent, **спросить** user'а оверrайдить или продолжить (Q9 resolved 2026-05-24). +- **Mid-task без STATUS.md entry** в write mode → записать handoff без mid-task секции, не блокировать. ## Side effects -<пусто> +- Записывает / перезаписывает `.tasks/NEXT_SESSION.md` (project-scope only). +- Файл git-tracked, попадает в commit (либо вместе с session work, либо отдельным commit'ом). +- Никаких других файлов: `.archive/` не плодим (sliding), `.wiki/log.md` не дёргаем (это не promoted event), `STATUS.md` не правим. +- Никаких global мутаций, никаких других проектов, никаких user-level config writes. ## What NOT to do -<пусто> +- **Не auto-execute** действия из read handoff'а. Default = orient + ask. Прошлая сессия могла ошибиться; user agency сохраняем. +- **Не append-with-archive.** Sliding only. `.archive/handoff-.md` создавать не нужно — это создавало бы N artefact'ов, которые user не хочет. История — через git log. +- **Не триггерить на task-zone phrases** («закрываем эту таску», «pause»), broad farewells («отбой», «разбегаемся»), partial completions («сейчас завершу одну задачу и тогда поговорим»). +- **Не писать секреты** в handoff. Если контент матчит secret-patterns — abort, попросить user'а вычистить контекст. +- **Не на каждом commit'е.** Только substantive (см. эвристика в When to use). Trivial `chore: bump dep` или `docs: typo` НЕ триггерят, иначе handoff'ы шумят. +- **Не дублировать STATUS.md / MEMORY.md.** Handoff = **forward-looking связка** новых вещей для следующего разворота, не overview всего проекта. Open треки — да, но как мостик «вот где остановились», не как replica STATUS.md. +- **Не cross-project.** Per-project scope. «Завершаем сессию» в `.workshop/` не трогает `.admin/` и наоборот. +- **Не зависеть от harness `SessionEnd` hook** — такого hook'а в Claude Code нет (есть только `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop`, `Notification`). Триггер — фраза или substantive-commit detection в самом agent flow. +- **Не считать handoff авторитетным** на стороне читателя. Это рекомендация прошлой сессии, не директива. User может override любую её часть.