diff --git a/README-ru.md b/README-ru.md
new file mode 100644
index 000000000..95a5ee29b
--- /dev/null
+++ b/README-ru.md
@@ -0,0 +1,377 @@
+[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md) | [Русский](./README-ru.md)
+# Learn Claude Code -- Harness Engineering для настоящих агентов
+
+## Model -- это и есть Agent
+
+Прежде чем говорить о коде, давайте раз и навсегда расставим всё по своим местам.
+
+**Agent -- это model. Не фреймворк. Не цепочка промптов. Не drag-and-drop рабочий процесс.**
+
+### Что такое Agent
+
+Agent -- это нейронная сеть: Transformer, RNN, обученная функция, которая через миллиарды шагов градиентного спуска на данных о последовательностях действий научилась воспринимать окружающую среду, рассуждать о целях и совершать действия для их достижения. Слово «agent» в сфере ИИ всегда означало именно это. Всегда.
+
+Человек -- это agent. Биологическая нейронная сеть, сформированная миллионами лет эволюционного обучения, воспринимающая мир через органы чувств, рассуждающая с помощью мозга, действующая посредством тела. Когда DeepMind, OpenAI или Anthropic говорят «agent», они имеют в виду то же самое, что это слово означало с самого начала существования области: **model, которая научилась действовать.**
+
+Доказательство написано историей:
+
+- **2013 -- DeepMind DQN играет в Atari.** Одна нейронная сеть, получая только сырые пиксели и игровые счета, научилась играть в 7 игр для Atari 2600 -- превзойдя все предыдущие алгоритмы и победив экспертов-людей в 3 из них. К 2015 году та же архитектура масштабировалась до [49 игр и сравнялась с профессиональными тестировщиками](https://www.nature.com/articles/nature14236), публикация в *Nature*. Никаких игровых правил, никаких деревьев решений. Одна model, обучающаяся на опыте. Эта model и была agent.
+
+- **2019 -- OpenAI Five покоряет Dota 2.** Пять нейронных сетей, сыгравших [45 000 лет Dota 2](https://openai.com/index/openai-five-defeats-dota-2-world-champions/) против самих себя за 10 месяцев, победили **OG** -- действующих чемпионов мира TI8 -- со счётом 2:0 в прямом эфире из Сан-Франциско. В последующем публичном турнире ИИ выиграл 99,4% из 42 729 партий против всех желающих. Никаких заскриптованных стратегий. Никакой заранее запрограммированной командной координации. Model сами научились командной работе, тактике и адаптации в реальном времени исключительно через самоигру.
+
+- **2019 -- DeepMind AlphaStar осваивает StarCraft II.** AlphaStar [победил профессиональных игроков со счётом 10:1](https://deepmind.google/blog/alphastar-mastering-the-real-time-strategy-game-starcraft-ii/) в закрытом матче, а позднее достиг [статуса Grandmaster](https://www.nature.com/articles/d41586-019-03298-6) на европейских серверах -- войдя в топ 0,15% из 90 000 игроков. Игра с неполной информацией, решениями в реальном времени и комбинаторным пространством действий, многократно превосходящим шахматы и го. Agent? Model. Обученная. Не заскриптованная.
+
+- **2019 -- Tencent Jueyu доминирует в Honor of Kings.** «Jueyu» от Tencent AI Lab [победила профессиональных игроков KPL](https://www.jiemian.com/article/3371171.html) в полноценном матче 5v5 на World Champion Cup. В режиме 1v1 профессионалы выиграли лишь [1 из 15 игр и ни разу не пережили 8 минут](https://developer.aliyun.com/article/851058). Интенсивность обучения: один день равнялся 440 человеческим годам. К 2021 году Jueyu превзошла профессионалов KPL по всему пулу героев. Никаких ручных таблиц матчапов. Никаких заскриптованных составов. Model, выучившая всю игру с нуля через самоигру.
+
+- **2024-2025 -- LLM agents меняют облик разработки ПО.** Claude, GPT, Gemini -- большие языковые model, обученные на всём массиве человеческого кода и рассуждений, -- разворачиваются как coding agents. Они читают кодовые базы, пишут реализации, отлаживают ошибки, координируют работу в командах. Архитектура идентична всем предыдущим agents: обученная model, помещённая в среду и снабжённая tools для восприятия и действия. Единственное отличие -- масштаб усвоенного и универсальность решаемых задач.
+
+Каждое из этих достижений подтверждает одно: **«agent» -- это никогда не окружающий код. Agent -- это всегда model.**
+
+### Чем Agent не является
+
+Слово «agent» было присвоено целой индустрией по прокладке промптов.
+
+Drag-and-drop конструкторы рабочих процессов. No-code платформы «AI agents». Библиотеки оркестрации цепочек промптов. Все они разделяют одно заблуждение: что соединение вызовов LLM API через ветки if-else, графы узлов и жёстко прошитую логику маршрутизации -- это «создание agent».
+
+Это не так. То, что они строят, -- машина Рубе Голдберга: чрезмерно сложный, хрупкий конвейер из процедурных правил, куда LLM вставлен как раздутая нода завершения текста. Это не agent. Это shell-скрипт с манией величия.
+
+**«Agents» из промпт-водопроводов -- это фантазия программистов, которые не обучают model.** Они пытаются брутфорсом получить интеллект, нагромождая процедурную логику -- огромные деревья правил, графы узлов, каскады цепочек промптов -- и молясь, что достаточное количество связующего кода каким-то образом породит автономное поведение. Не породит. Нельзя сконструировать агентность. Агентность -- это результат обучения, а не программирования.
+
+Такие системы мертворождённые: хрупкие, немасштабируемые, принципиально неспособные к обобщению. Это современное воскрешение GOFAI (Good Old-Fashioned AI) -- символических систем правил, от которых область отказалась десятилетия назад, теперь покрашенных в цвет LLM. Другая упаковка, тот же тупик.
+
+### Смена мышления: от «разработки agents» к разработке Harness
+
+Когда кто-то говорит «я разрабатываю agent», это может означать лишь одно из двух:
+
+**1. Обучение model.** Корректировка весов через reinforcement learning, дообучение, RLHF или другие методы на основе градиентного спуска. Сбор данных о процессе выполнения задач -- реальных последовательностей восприятия, рассуждения и действия в реальных областях -- и использование их для формирования поведения model. Именно этим занимаются DeepMind, OpenAI, Tencent AI Lab и Anthropic. Это разработка agent в истинном смысле слова.
+
+**2. Создание harness.** Написание кода, дающего model среду для работы. Это то, чем занимаемся большинство из нас, и это -- тема данного репозитория.
+
+Harness -- это всё, что нужно agent для функционирования в конкретной области:
+
+```
+Harness = Tools + Knowledge + Observation + Action Interfaces + Permissions
+
+ Tools: file I/O, shell, network, database, browser
+ Knowledge: product docs, domain references, API specs, style guides
+ Observation: git diff, error logs, browser state, sensor data
+ Action: CLI commands, API calls, UI interactions
+ Permissions: sandboxing, approval workflows, trust boundaries
+```
+
+Model принимает решения. Harness их исполняет. Model рассуждает. Harness предоставляет context. Model -- водитель. Harness -- транспортное средство.
+
+**Harness coding agent -- это его IDE, терминал и доступ к файловой системе.** Harness фермерского agent -- это массив датчиков, управление орошением и потоки погодных данных. Harness гостиничного agent -- это система бронирования, каналы общения с гостями и API управления объектом. Agent -- интеллект, принимающий решения -- всегда model. Harness меняется в зависимости от области. Agent обобщается на все области.
+
+Этот репозиторий учит создавать транспортные средства. Транспортные средства для написания кода. Но паттерны проектирования применимы к любой области: управление фермой, гостиничный бизнес, производство, логистика, здравоохранение, образование, научные исследования. Везде, где задачу нужно воспринять, осмыслить и выполнить -- agent нужен harness.
+
+### Что на самом деле делают Harness Engineers
+
+Если вы читаете этот репозиторий, скорее всего, вы harness engineer -- и это очень сильная позиция. Вот ваша настоящая работа:
+
+- **Реализуйте tools.** Дайте agent руки. Чтение/запись файлов, выполнение shell-команд, вызовы API, управление браузером, запросы к базам данных. Каждый tool -- это действие, которое agent может совершить в своей среде. Проектируйте их атомарными, компонуемыми и хорошо описанными.
+
+- **Курируйте knowledge.** Дайте agent экспертизу в области. Документация продукта, записи об архитектурных решениях, руководства по стилю, нормативные требования. Загружайте по требованию (s05), а не заранее. Agent должен знать, что доступно, и брать то, что нужно.
+
+- **Управляйте context.** Дайте agent чистую память. Изоляция subagent (s04) предотвращает утечку шума. Сжатие context (s06) предотвращает переполнение историей. Системы задач (s07) сохраняют цели за пределами одного разговора.
+
+- **Контролируйте permissions.** Задайте agent границы. Ограничьте доступ к файлам через sandbox. Требуйте подтверждения для деструктивных операций. Соблюдайте границы доверия между agent и внешними системами. Здесь безопасность встречается с harness engineering.
+
+- **Собирайте данные о процессе выполнения задач.** Каждая последовательность действий, которую agent выполняет в вашем harness, -- это обучающий сигнал. Трассировки восприятия-рассуждения-действия из реальных развёртываний -- это сырой материал для дообучения следующего поколения model agents. Ваш harness не просто обслуживает agent -- он может помочь его улучшить.
+
+Вы пишете не интеллект. Вы строите мир, в котором этот интеллект живёт. Качество этого мира -- насколько чётко agent воспринимает, насколько точно действует, насколько богаты его доступные знания -- напрямую определяет, насколько эффективно интеллект может себя проявить.
+
+**Стройте отличные harnesses. Agent сделает остальное.**
+
+### Почему Claude Code -- мастер-класс по Harness Engineering
+
+Почему этот репозиторий препарирует именно Claude Code?
+
+Потому что Claude Code -- это самый элегантный и полноценно реализованный harness для agent, который нам доводилось видеть. Не из-за какого-то одного умного трюка, а из-за того, чего он *не делает*: он не пытается быть agent. Он не навязывает жёстких рабочих процессов. Он не перепроверяет model сложными деревьями решений. Он снабжает model tools, knowledge, управлением context и границами permissions -- а затем уходит с дороги.
+
+Посмотрите, что такое Claude Code в своей сути:
+
+```
+Claude Code = один agent loop
+ + tools (bash, read, write, edit, glob, grep, browser...)
+ + on-demand skill loading
+ + context compression
+ + subagent spawning
+ + task system with dependency graph
+ + team coordination with async mailboxes
+ + worktree isolation for parallel execution
+ + permission governance
+```
+
+Вот и всё. Вся архитектура целиком. Каждый компонент -- это механизм harness: кусочек мира, построенный для agent. Сам agent? Это Claude. Model. Обученная Anthropic на всём массиве человеческого мышления и кода. Harness не делает Claude умным. Claude уже умён. Harness даёт Claude руки, глаза и рабочее пространство.
+
+Вот почему Claude Code -- идеальный предмет для изучения: **он демонстрирует, что происходит, когда вы доверяете model и сосредотачиваете свои инженерные усилия на harness.** Каждая сессия в этом репозитории (s01-s12) реконструирует один механизм harness из архитектуры Claude Code. По завершении вы понимаете не только то, как работает Claude Code, но и универсальные принципы harness engineering, применимые к любому agent в любой области.
+
+Урок не в том, чтобы «скопировать Claude Code». Урок таков: **лучшие продукты на основе agents создают инженеры, понимающие, что их работа -- это harness, а не интеллект.**
+
+---
+
+## Видение: наполнить вселенную настоящими Agents
+
+Это не только про coding agents.
+
+В каждой области, где люди выполняют сложную, многоэтапную работу, требующую суждений, могут работать agents -- при наличии правильного harness. Паттерны этого репозитория универсальны:
+
+```
+Estate management agent = model + property sensors + maintenance tools + tenant comms
+Agricultural agent = model + soil/weather data + irrigation controls + crop knowledge
+Hotel operations agent = model + booking system + guest channels + facility APIs
+Medical research agent = model + literature search + lab instruments + protocol docs
+Manufacturing agent = model + production line sensors + quality controls + logistics
+Education agent = model + curriculum knowledge + student progress + assessment tools
+```
+
+Loop всегда один и тот же. Tools меняются. Knowledge меняется. Permissions меняются. Agent -- model -- обобщается на всё.
+
+Каждый harness engineer, читающий этот репозиторий, осваивает паттерны, применимые далеко за пределами разработки ПО. Вы учитесь строить инфраструктуру для интеллектуального автоматизированного будущего. Каждый хорошо спроектированный harness, развёрнутый в реальной области, -- это ещё одно место, где agent может воспринимать, рассуждать и действовать.
+
+Сначала мы заполняем мастерские. Затем фермы, больницы, заводы. Потом города. Потом планету.
+
+**Bash is all you need. Real agents are all the universe needs.**
+
+---
+
+```
+ THE AGENT PATTERN
+ =================
+
+ User --> messages[] --> LLM --> response
+ |
+ stop_reason == "tool_use"?
+ / \
+ yes no
+ | |
+ execute tools return text
+ append results
+ loop back -----------------> messages[]
+
+
+ That's the minimal loop. Every AI agent needs this loop.
+ The MODEL decides when to call tools and when to stop.
+ The CODE just executes what the model asks for.
+ This repo teaches you to build what surrounds this loop --
+ the harness that makes the agent effective in a specific domain.
+```
+
+**12 последовательных сессий: от простого loop до изолированного автономного выполнения.**
+**Каждая сессия добавляет один механизм harness. У каждого механизма -- своё motto.**
+
+> **s01** *"Один loop и Bash -- это всё, что нужно"* — один tool + один loop = agent
+>
+> **s02** *"Добавить tool -- значит добавить один обработчик"* — loop остаётся прежним; новые tools регистрируются в таблице диспетчеризации
+>
+> **s03** *"Agent без плана блуждает"* — сначала составь список шагов, потом выполняй; завершаемость удваивается
+>
+> **s04** *"Дели большие задачи; каждая подзадача получает чистый context"* — subagents используют независимые messages[], сохраняя главный разговор чистым
+>
+> **s05** *"Загружай knowledge тогда, когда это нужно, а не заранее"* — передавай через tool_result, а не через system prompt
+>
+> **s06** *"Context заполняется; нужен способ освободить место"* — трёхуровневая стратегия сжатия для бесконечных сессий
+>
+> **s07** *"Дели большие цели на малые задачи, упорядочивай их, сохраняй на диск"* — файловый граф задач с зависимостями, закладывающий основу для многоагентного сотрудничества
+>
+> **s08** *"Запускай медленные операции в фоне; agent продолжает думать"* — daemon threads выполняют команды и отправляют уведомления по завершении
+>
+> **s09** *"Когда задача слишком велика для одного -- делегируй товарищам по команде"* — постоянные teammates + async mailboxes
+>
+> **s10** *"Teammates нужны общие правила коммуникации"* — один паттерн запрос-ответ управляет всеми переговорами
+>
+> **s11** *"Teammates сами просматривают доску и берут задачи"* — лидеру не нужно назначать каждую задачу вручную
+>
+> **s12** *"Каждый работает в своей директории, без помех"* — tasks управляют целями, worktrees управляют директориями, связанными по ID
+
+---
+
+## Основной паттерн
+
+```python
+def agent_loop(messages):
+ while True:
+ response = client.messages.create(
+ model=MODEL, system=SYSTEM,
+ messages=messages, tools=TOOLS,
+ )
+ messages.append({"role": "assistant",
+ "content": response.content})
+
+ if response.stop_reason != "tool_use":
+ return
+
+ results = []
+ for block in response.content:
+ if block.type == "tool_use":
+ output = TOOL_HANDLERS[block.name](**block.input)
+ results.append({
+ "type": "tool_result",
+ "tool_use_id": block.id,
+ "content": output,
+ })
+ messages.append({"role": "user", "content": results})
+```
+
+Каждая сессия добавляет один механизм harness поверх этого loop -- не изменяя сам loop. Loop принадлежит agent. Механизмы принадлежат harness.
+
+## Область охвата (важно)
+
+Этот репозиторий -- учебный проект уровня 0->1 по harness engineering: построению среды, окружающей model-agent.
+Намеренно упрощены или опущены некоторые производственные механизмы:
+
+- Полные шины событий/хуков (например, PreToolUse, SessionStart/End, ConfigChange).
+ s12 включает только минимальный append-only поток событий жизненного цикла в учебных целях.
+- Управление permissions на основе правил и рабочие процессы доверия
+- Управление жизненным циклом сессии (resume/fork) и расширенное управление жизненным циклом worktree
+- Полные детали MCP runtime (transport/OAuth/resource subscribe/polling)
+
+Рассматривайте протокол team JSONL mailbox в этом репозитории как учебную реализацию, а не как утверждение о каких-либо конкретных производственных внутренностях.
+
+## Быстрый старт
+
+```sh
+git clone https://github.com/shareAI-lab/learn-claude-code
+cd learn-claude-code
+pip install -r requirements.txt
+cp .env.example .env # Edit .env with your ANTHROPIC_API_KEY
+
+python agents/s01_agent_loop.py # Start here
+python agents/s12_worktree_task_isolation.py # Full progression endpoint
+python agents/s_full.py # Capstone: all mechanisms combined
+```
+
+### Веб-платформа
+
+Интерактивные визуализации, пошаговые диаграммы, просмотр исходного кода и документация.
+
+```sh
+cd web && npm install && npm run dev # http://localhost:3000
+```
+
+## Путь обучения
+
+```
+Phase 1: THE LOOP Phase 2: PLANNING & KNOWLEDGE
+================== ==============================
+s01 The Agent Loop [1] s03 TodoWrite [5]
+ while + stop_reason TodoManager + nag reminder
+ | |
+ +-> s02 Tool Use [4] s04 Subagents [5]
+ dispatch map: name->handler fresh messages[] per child
+ |
+ s05 Skills [5]
+ SKILL.md via tool_result
+ |
+ s06 Context Compact [5]
+ 3-layer compression
+
+Phase 3: PERSISTENCE Phase 4: TEAMS
+================== =====================
+s07 Tasks [8] s09 Agent Teams [9]
+ file-based CRUD + deps graph teammates + JSONL mailboxes
+ | |
+s08 Background Tasks [6] s10 Team Protocols [12]
+ daemon threads + notify queue shutdown + plan approval FSM
+ |
+ s11 Autonomous Agents [14]
+ idle cycle + auto-claim
+ |
+ s12 Worktree Isolation [16]
+ task coordination + optional isolated execution lanes
+
+ [N] = number of tools
+```
+
+## Архитектура
+
+```
+learn-claude-code/
+|
+|-- agents/ # Python reference implementations (s01-s12 + s_full capstone)
+|-- docs/{en,zh,ja}/ # Mental-model-first documentation (3 languages)
+|-- web/ # Interactive learning platform (Next.js)
+|-- skills/ # Skill files for s05
++-- .github/workflows/ci.yml # CI: typecheck + build
+```
+
+## Документация
+
+Подход «сначала ментальная модель»: проблема, решение, ASCII-диаграмма, минимальный код.
+Доступно на [English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/) | [Русский](./docs/ru/).
+
+| Сессия | Тема | Motto |
+|---------|-------|-------|
+| [s01](./docs/ru/s01-the-agent-loop.md) | The Agent Loop | *Один loop и Bash -- это всё, что нужно* |
+| [s02](./docs/ru/s02-tool-use.md) | Tool Use | *Добавить tool -- значит добавить один обработчик* |
+| [s03](./docs/ru/s03-todo-write.md) | TodoWrite | *Agent без плана блуждает* |
+| [s04](./docs/ru/s04-subagent.md) | Subagents | *Дели большие задачи; каждая подзадача получает чистый context* |
+| [s05](./docs/ru/s05-skill-loading.md) | Skills | *Загружай knowledge тогда, когда это нужно, а не заранее* |
+| [s06](./docs/ru/s06-context-compact.md) | Context Compact | *Context заполняется; нужен способ освободить место* |
+| [s07](./docs/ru/s07-task-system.md) | Tasks | *Дели большие цели на малые задачи, упорядочивай их, сохраняй на диск* |
+| [s08](./docs/ru/s08-background-tasks.md) | Background Tasks | *Запускай медленные операции в фоне; agent продолжает думать* |
+| [s09](./docs/ru/s09-agent-teams.md) | Agent Teams | *Когда задача слишком велика для одного -- делегируй teammates* |
+| [s10](./docs/ru/s10-team-protocols.md) | Team Protocols | *Teammates нужны общие правила коммуникации* |
+| [s11](./docs/ru/s11-autonomous-agents.md) | Autonomous Agents | *Teammates сами просматривают доску и берут задачи* |
+| [s12](./docs/ru/s12-worktree-task-isolation.md) | Worktree + Task Isolation | *Каждый работает в своей директории, без помех* |
+
+## Что дальше -- от понимания к созданию продуктов
+
+После 12 сессий вы понимаете harness engineering изнутри и снаружи. Два способа применить эти знания:
+
+### Kode Agent CLI -- CLI coding agent с открытым исходным кодом
+
+> `npm i -g @shareai-lab/kode`
+
+Поддержка Skill и LSP, готовность к Windows, совместимость с GLM / MiniMax / DeepSeek и другими открытыми model. Устанавливайте и работайте.
+
+GitHub: **[shareAI-lab/Kode-cli](https://github.com/shareAI-lab/Kode-cli)**
+
+### Kode Agent SDK -- встраивайте возможности Agent в своё приложение
+
+Официальный Claude Code Agent SDK взаимодействует с полноценным CLI-процессом под капотом -- каждый одновременный пользователь означает отдельный процесс терминала. Kode SDK -- это автономная библиотека без накладных расходов на процесс для каждого пользователя, встраиваемая в бэкенды, расширения браузера, встраиваемые устройства или любую среду выполнения.
+
+GitHub: **[shareAI-lab/Kode-agent-sdk](https://github.com/shareAI-lab/Kode-agent-sdk)**
+
+---
+
+## Родственный репозиторий: от *сессий по запросу* до *постоянно работающего ассистента*
+
+Harness, которому учит этот репозиторий, -- **использовать и выбрасывать**: открыл терминал, дал agent задачу, закрыл по завершении, следующая сессия начинается с чистого листа. Такова модель Claude Code.
+
+[OpenClaw](https://github.com/openclaw/openclaw) доказал другую возможность: поверх того же ядра agent два механизма harness превращают agent из «ткни, чтобы он двинулся» в «просыпается каждые 30 секунд, чтобы проверить, есть ли работа»:
+
+- **Heartbeat** -- каждые 30 секунд harness отправляет agent сообщение: есть ли что-то, что нужно сделать? Нет? Обратно спать. Есть? Действовать немедленно.
+- **Cron** -- agent может планировать свои будущие задачи, которые автоматически выполняются в нужное время.
+
+Добавьте многоканальную IM-маршрутизацию (WhatsApp / Telegram / Slack / Discord, 13+ платформ), постоянную память context и систему личности Soul -- и agent превратится из одноразового инструмента в постоянно работающего персонального ИИ-ассистента.
+
+**[claw0](https://github.com/shareAI-lab/claw0)** -- наш сопутствующий учебный репозиторий, деконструирующий эти механизмы harness с нуля:
+
+```
+claw agent = agent core + heartbeat + cron + IM chat + memory + soul
+```
+
+```
+learn-claude-code claw0
+(agent harness core: (proactive always-on harness:
+ loop, tools, planning, heartbeat, cron, IM channels,
+ teams, worktree isolation) memory, soul personality)
+```
+
+## О нас
+
+
+Сканируйте WeChat, чтобы подписаться,
+или следите в X: [shareAI-Lab](https://x.com/baicai003)
+
+## Лицензия
+
+MIT
+
+---
+
+**Model -- это agent. Код -- это harness. Стройте отличные harnesses. Agent сделает остальное.**
+
+**Bash is all you need. Real agents are all the universe needs.**
diff --git a/README.md b/README.md
index 02561fef1..4f14b82a0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md)
+[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md) | [Русский](./README-ru.md)
# Learn Claude Code -- Harness Engineering for Real Agents
## The Model IS the Agent
@@ -299,7 +299,7 @@ learn-claude-code/
## Documentation
Mental-model-first: problem, solution, ASCII diagram, minimal code.
-Available in [English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/).
+Available in [English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/) | [Русский](./docs/ru/).
| Session | Topic | Motto |
|---------|-------|-------|
diff --git a/docs/ru/s01-the-agent-loop.md b/docs/ru/s01-the-agent-loop.md
new file mode 100644
index 000000000..b38c37fd1
--- /dev/null
+++ b/docs/ru/s01-the-agent-loop.md
@@ -0,0 +1,116 @@
+# s01: The Agent Loop
+
+`[ s01 ] s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Один loop и Bash — это всё, что нужно"* -- один tool + один loop = agent.
+>
+> **Harness layer**: The loop -- первое соединение model с реальным миром.
+
+## Проблема
+
+Языковая model умеет рассуждать о коде, но не может *взаимодействовать* с реальным миром — читать файлы, запускать тесты или проверять ошибки. Без loop каждый вызов tool требует вручную копировать и вставлять результаты обратно. Вы сами становитесь loop.
+
+## Решение
+
+```
++--------+ +-------+ +---------+
+| User | ---> | LLM | ---> | Tool |
+| prompt | | | | execute |
++--------+ +---+---+ +----+----+
+ ^ |
+ | tool_result |
+ +----------------+
+ (loop until stop_reason != "tool_use")
+```
+
+Одно условие выхода управляет всем потоком. Loop работает до тех пор, пока model не прекращает вызывать tools.
+
+## Как это работает
+
+1. Запрос пользователя становится первым сообщением.
+
+```python
+messages.append({"role": "user", "content": query})
+```
+
+2. Отправляем messages и определения tools в LLM.
+
+```python
+response = client.messages.create(
+ model=MODEL, system=SYSTEM, messages=messages,
+ tools=TOOLS, max_tokens=8000,
+)
+```
+
+3. Добавляем ответ ассистента. Проверяем `stop_reason` — если model не вызвала tool, работа завершена.
+
+```python
+messages.append({"role": "assistant", "content": response.content})
+if response.stop_reason != "tool_use":
+ return
+```
+
+4. Выполняем каждый вызов tool, собираем результаты, добавляем как сообщение пользователя. Возвращаемся к шагу 2.
+
+```python
+results = []
+for block in response.content:
+ if block.type == "tool_use":
+ output = run_bash(block.input["command"])
+ results.append({
+ "type": "tool_result",
+ "tool_use_id": block.id,
+ "content": output,
+ })
+messages.append({"role": "user", "content": results})
+```
+
+Собранное в одну функцию:
+
+```python
+def agent_loop(query):
+ messages = [{"role": "user", "content": query}]
+ while True:
+ response = client.messages.create(
+ model=MODEL, system=SYSTEM, messages=messages,
+ tools=TOOLS, max_tokens=8000,
+ )
+ messages.append({"role": "assistant", "content": response.content})
+
+ if response.stop_reason != "tool_use":
+ return
+
+ results = []
+ for block in response.content:
+ if block.type == "tool_use":
+ output = run_bash(block.input["command"])
+ results.append({
+ "type": "tool_result",
+ "tool_use_id": block.id,
+ "content": output,
+ })
+ messages.append({"role": "user", "content": results})
+```
+
+Это весь agent — менее 30 строк. Всё остальное в этом курсе надстраивается сверху, не изменяя loop.
+
+## Что изменилось
+
+| Компонент | До | После |
+|---------------|------------|--------------------------------|
+| Agent loop | (нет) | `while True` + stop_reason |
+| Tools | (нет) | `bash` (один tool) |
+| Messages | (нет) | Накапливаемый список |
+| Control flow | (нет) | `stop_reason != "tool_use"` |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s01_agent_loop.py
+```
+
+1. `Create a file called hello.py that prints "Hello, World!"`
+2. `List all Python files in this directory`
+3. `What is the current git branch?`
+4. `Create a directory called test_output and write 3 files in it`
diff --git a/docs/ru/s02-tool-use.md b/docs/ru/s02-tool-use.md
new file mode 100644
index 000000000..9174ba570
--- /dev/null
+++ b/docs/ru/s02-tool-use.md
@@ -0,0 +1,99 @@
+# s02: Tool Use
+
+`s01 > [ s02 ] s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Добавить tool — значит добавить один handler"* -- loop остаётся прежним; новые tools регистрируются в dispatch map.
+>
+> **Harness layer**: Tool dispatch -- расширяем возможности model.
+
+## Проблема
+
+Имея только `bash`, agent использует оболочку для всего. `cat` обрезает вывод непредсказуемо, `sed` ломается на спецсимволах, а каждый bash-вызов — это неограниченная поверхность для атак. Специализированные tools вроде `read_file` и `write_file` позволяют применять ограничение путей на уровне tool.
+
+Ключевая идея: добавление tools не требует изменения loop.
+
+## Решение
+
+```
++--------+ +-------+ +------------------+
+| User | ---> | LLM | ---> | Tool Dispatch |
+| prompt | | | | { |
++--------+ +---+---+ | bash: run_bash |
+ ^ | read: run_read |
+ | | write: run_wr |
+ +-----------+ edit: run_edit |
+ tool_result | } |
+ +------------------+
+
+The dispatch map — это словарь: {tool_name: handler_function}.
+Один поиск заменяет любую цепочку if/elif.
+```
+
+## Как это работает
+
+1. Каждый tool получает функцию-handler. Ограничение путей предотвращает выход за пределы рабочего пространства.
+
+```python
+def safe_path(p: str) -> Path:
+ path = (WORKDIR / p).resolve()
+ if not path.is_relative_to(WORKDIR):
+ raise ValueError(f"Path escapes workspace: {p}")
+ return path
+
+def run_read(path: str, limit: int = None) -> str:
+ text = safe_path(path).read_text()
+ lines = text.splitlines()
+ if limit and limit < len(lines):
+ lines = lines[:limit]
+ return "\n".join(lines)[:50000]
+```
+
+2. Dispatch map связывает имена tools с handlers.
+
+```python
+TOOL_HANDLERS = {
+ "bash": lambda **kw: run_bash(kw["command"]),
+ "read_file": lambda **kw: run_read(kw["path"], kw.get("limit")),
+ "write_file": lambda **kw: run_write(kw["path"], kw["content"]),
+ "edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"],
+ kw["new_text"]),
+}
+```
+
+3. В loop ищем handler по имени. Тело loop осталось неизменным по сравнению с s01.
+
+```python
+for block in response.content:
+ if block.type == "tool_use":
+ handler = TOOL_HANDLERS.get(block.name)
+ output = handler(**block.input) if handler \
+ else f"Unknown tool: {block.name}"
+ results.append({
+ "type": "tool_result",
+ "tool_use_id": block.id,
+ "content": output,
+ })
+```
+
+Добавить tool = добавить handler + добавить запись в схему. Loop никогда не меняется.
+
+## Что изменилось по сравнению с s01
+
+| Компонент | До (s01) | После (s02) |
+|----------------|-----------------------|----------------------------|
+| Tools | 1 (только bash) | 4 (bash, read, write, edit)|
+| Dispatch | Жёстко закодированный bash | `TOOL_HANDLERS` dict |
+| Безопасность путей | Нет | Sandbox `safe_path()` |
+| Agent loop | Без изменений | Без изменений |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s02_tool_use.py
+```
+
+1. `Read the file requirements.txt`
+2. `Create a file called greet.py with a greet(name) function`
+3. `Edit greet.py to add a docstring to the function`
+4. `Read greet.py to verify the edit worked`
diff --git a/docs/ru/s03-todo-write.md b/docs/ru/s03-todo-write.md
new file mode 100644
index 000000000..b1c4b7e37
--- /dev/null
+++ b/docs/ru/s03-todo-write.md
@@ -0,0 +1,96 @@
+# s03: TodoWrite
+
+`s01 > s02 > [ s03 ] s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Agent без плана блуждает"* -- сначала перечисли шаги, затем выполняй.
+>
+> **Harness layer**: Планирование -- удерживаем model на курсе, не прописывая маршрут.
+
+## Проблема
+
+На многоходовых задачах model теряет нить. Она повторяет уже сделанное, пропускает шаги или уходит в сторону. Длинные диалоги усугубляют ситуацию — системный промпт тускнеет по мере того, как tool results заполняют context. Рефакторинг в 10 шагов может завершить шаги 1–3, а затем model начинает импровизировать, потому что забыла шаги 4–10.
+
+## Решение
+
+```
++--------+ +-------+ +---------+
+| User | ---> | LLM | ---> | Tools |
+| prompt | | | | + todo |
++--------+ +---+---+ +----+----+
+ ^ |
+ | tool_result |
+ +----------------+
+ |
+ +-----------+-----------+
+ | TodoManager state |
+ | [ ] task A |
+ | [>] task B <- doing |
+ | [x] task C |
+ +-----------------------+
+ |
+ if rounds_since_todo >= 3:
+ inject into tool_result
+```
+
+## Как это работает
+
+1. TodoManager хранит элементы со статусами. Одновременно только один элемент может быть в состоянии `in_progress`.
+
+```python
+class TodoManager:
+ def update(self, items: list) -> str:
+ validated, in_progress_count = [], 0
+ for item in items:
+ status = item.get("status", "pending")
+ if status == "in_progress":
+ in_progress_count += 1
+ validated.append({"id": item["id"], "text": item["text"],
+ "status": status})
+ if in_progress_count > 1:
+ raise ValueError("Only one task can be in_progress")
+ self.items = validated
+ return self.render()
+```
+
+2. Tool `todo` добавляется в dispatch map как любой другой tool.
+
+```python
+TOOL_HANDLERS = {
+ # ...базовые tools...
+ "todo": lambda **kw: TODO.update(kw["items"]),
+}
+```
+
+3. Напоминание встраивает подсказку, если model не вызывала `todo` 3 и более раундов подряд.
+
+```python
+if rounds_since_todo >= 3 and messages:
+ last = messages[-1]
+ if last["role"] == "user" and isinstance(last.get("content"), list):
+ last["content"].insert(0, {
+ "type": "text",
+ "text": "Update your todos.",
+ })
+```
+
+Ограничение «только один `in_progress` за раз» принуждает к последовательной концентрации. Напоминание создаёт механизм подотчётности.
+
+## Что изменилось по сравнению с s02
+
+| Компонент | До (s02) | После (s03) |
+|----------------|------------------|----------------------------|
+| Tools | 4 | 5 (+todo) |
+| Планирование | Нет | TodoManager со статусами |
+| Напоминание | Нет | `` после 3 раундов|
+| Agent loop | Простой dispatch | + счётчик rounds_since_todo|
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s03_todo_write.py
+```
+
+1. `Refactor the file hello.py: add type hints, docstrings, and a main guard`
+2. `Create a Python package with __init__.py, utils.py, and tests/test_utils.py`
+3. `Review all Python files and fix any style issues`
diff --git a/docs/ru/s04-subagent.md b/docs/ru/s04-subagent.md
new file mode 100644
index 000000000..75e2c7e3c
--- /dev/null
+++ b/docs/ru/s04-subagent.md
@@ -0,0 +1,94 @@
+# s04: Subagents
+
+`s01 > s02 > s03 > [ s04 ] s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Раздели большие задачи; каждая подзадача получает чистый context"* -- subagents используют независимые messages[], сохраняя основной диалог чистым.
+>
+> **Harness layer**: Context isolation -- защищаем ясность мышления model.
+
+## Проблема
+
+По мере работы agent его массив messages растёт. Каждое прочитанное содержимое файла, каждый вывод bash остаётся в context навсегда. На вопрос «Какой тестовый фреймворк использует этот проект?» может потребоваться прочитать 5 файлов — но родительскому agent нужен только ответ: «pytest».
+
+## Решение
+
+```
+Parent agent Subagent
++------------------+ +------------------+
+| messages=[...] | | messages=[] | <-- fresh
+| | dispatch | |
+| tool: task | ----------> | while tool_use: |
+| prompt="..." | | call tools |
+| | summary | append results |
+| result = "..." | <---------- | return last text |
++------------------+ +------------------+
+
+Context родителя остаётся чистым. Context subagent отбрасывается.
+```
+
+## Как это работает
+
+1. Родитель получает tool `task`. Дочерний agent получает все базовые tools, кроме `task` (без рекурсивного порождения).
+
+```python
+PARENT_TOOLS = CHILD_TOOLS + [
+ {"name": "task",
+ "description": "Spawn a subagent with fresh context.",
+ "input_schema": {
+ "type": "object",
+ "properties": {"prompt": {"type": "string"}},
+ "required": ["prompt"],
+ }},
+]
+```
+
+2. Subagent стартует с `messages=[]` и запускает собственный loop. Родителю возвращается только финальный текст.
+
+```python
+def run_subagent(prompt: str) -> str:
+ sub_messages = [{"role": "user", "content": prompt}]
+ for _ in range(30): # safety limit
+ response = client.messages.create(
+ model=MODEL, system=SUBAGENT_SYSTEM,
+ messages=sub_messages,
+ tools=CHILD_TOOLS, max_tokens=8000,
+ )
+ sub_messages.append({"role": "assistant",
+ "content": response.content})
+ if response.stop_reason != "tool_use":
+ break
+ results = []
+ for block in response.content:
+ if block.type == "tool_use":
+ handler = TOOL_HANDLERS.get(block.name)
+ output = handler(**block.input)
+ results.append({"type": "tool_result",
+ "tool_use_id": block.id,
+ "content": str(output)[:50000]})
+ sub_messages.append({"role": "user", "content": results})
+ return "".join(
+ b.text for b in response.content if hasattr(b, "text")
+ ) or "(no summary)"
+```
+
+Вся история сообщений дочернего agent (возможно, 30+ вызовов tools) отбрасывается. Родитель получает краткое резюме в один абзац как обычный `tool_result`.
+
+## Что изменилось по сравнению с s03
+
+| Компонент | До (s03) | После (s04) |
+|----------------|-------------------|---------------------------|
+| Tools | 5 | 5 (базовые) + task (родитель) |
+| Context | Единый общий | Изоляция родителя и дочернего |
+| Subagent | Нет | Функция `run_subagent()` |
+| Возвращаемое значение | Нет | Только текст резюме |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s04_subagent.py
+```
+
+1. `Use a subtask to find what testing framework this project uses`
+2. `Delegate: read all .py files and summarize what each one does`
+3. `Use a task to create a new module, then verify it from here`
diff --git a/docs/ru/s05-skill-loading.md b/docs/ru/s05-skill-loading.md
new file mode 100644
index 000000000..9caa91c45
--- /dev/null
+++ b/docs/ru/s05-skill-loading.md
@@ -0,0 +1,108 @@
+# s05: Skills
+
+`s01 > s02 > s03 > s04 > [ s05 ] s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Загружай знания тогда, когда они нужны, а не заранее"* -- внедряй через tool_result, а не через системный промпт.
+>
+> **Harness layer**: Знания по запросу -- экспертиза предметной области, загружаемая по мере необходимости model.
+
+## Проблема
+
+Вы хотите, чтобы agent следовал рабочим процессам конкретной предметной области: соглашениям git, паттернам тестирования, чек-листам code review. Размещение всего в системном промпте расходует токены на неиспользуемые skill. 10 skill по 2000 токенов каждый = 20 000 токенов, большинство из которых не имеют отношения к конкретной задаче.
+
+## Решение
+
+```
+System prompt (Layer 1 -- always present):
++--------------------------------------+
+| You are a coding agent. |
+| Skills available: |
+| - git: Git workflow helpers | ~100 tokens/skill
+| - test: Testing best practices |
++--------------------------------------+
+
+When model calls load_skill("git"):
++--------------------------------------+
+| tool_result (Layer 2 -- on demand): |
+| |
+| Full git workflow instructions... | ~2000 tokens
+| Step 1: ... |
+| |
++--------------------------------------+
+```
+
+Layer 1: *названия* skill в системном промпте (дёшево). Layer 2: полное *содержимое* через tool_result (по запросу).
+
+## Как это работает
+
+1. Каждый skill — это директория с файлом `SKILL.md`, содержащим YAML frontmatter.
+
+```
+skills/
+ pdf/
+ SKILL.md # ---\n name: pdf\n description: Process PDF files\n ---\n ...
+ code-review/
+ SKILL.md # ---\n name: code-review\n description: Review code\n ---\n ...
+```
+
+2. SkillLoader сканирует файлы `SKILL.md`, используя имя директории как идентификатор skill.
+
+```python
+class SkillLoader:
+ def __init__(self, skills_dir: Path):
+ self.skills = {}
+ for f in sorted(skills_dir.rglob("SKILL.md")):
+ text = f.read_text()
+ meta, body = self._parse_frontmatter(text)
+ name = meta.get("name", f.parent.name)
+ self.skills[name] = {"meta": meta, "body": body}
+
+ def get_descriptions(self) -> str:
+ lines = []
+ for name, skill in self.skills.items():
+ desc = skill["meta"].get("description", "")
+ lines.append(f" - {name}: {desc}")
+ return "\n".join(lines)
+
+ def get_content(self, name: str) -> str:
+ skill = self.skills.get(name)
+ if not skill:
+ return f"Error: Unknown skill '{name}'."
+ return f"\n{skill['body']}\n"
+```
+
+3. Layer 1 попадает в системный промпт. Layer 2 — это ещё один tool handler.
+
+```python
+SYSTEM = f"""You are a coding agent at {WORKDIR}.
+Skills available:
+{SKILL_LOADER.get_descriptions()}"""
+
+TOOL_HANDLERS = {
+ # ...base tools...
+ "load_skill": lambda **kw: SKILL_LOADER.get_content(kw["name"]),
+}
+```
+
+Model узнаёт, какие skill существуют (дёшево), и загружает их при необходимости (дорого).
+
+## Что изменилось по сравнению с s04
+
+| Компонент | До (s04) | После (s05) |
+|----------------|------------------|----------------------------|
+| Tools | 5 (base + task) | 5 (base + load_skill) |
+| System prompt | Статическая строка | + описания skill |
+| Знания | Отсутствуют | файлы skills/\*/SKILL.md |
+| Внедрение | Отсутствует | Двухуровневое (system + result)|
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s05_skill_loading.py
+```
+
+1. `What skills are available?`
+2. `Load the agent-builder skill and follow its instructions`
+3. `I need to do a code review -- load the relevant skill first`
+4. `Build an MCP server using the mcp-builder skill`
diff --git a/docs/ru/s06-context-compact.md b/docs/ru/s06-context-compact.md
new file mode 100644
index 000000000..fb39f60ee
--- /dev/null
+++ b/docs/ru/s06-context-compact.md
@@ -0,0 +1,124 @@
+# s06: Context Compact
+
+`s01 > s02 > s03 > s04 > s05 > [ s06 ] | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Context заполнится; нужен способ освободить место"* -- трёхуровневая стратегия сжатия для бесконечных сессий.
+>
+> **Harness layer**: Сжатие -- чистая память для бесконечных сессий.
+
+## Проблема
+
+Окно context конечно. Один вызов `read_file` на файл из 1000 строк стоит ~4000 токенов. После чтения 30 файлов и выполнения 20 bash-команд накапливается 100 000+ токенов. Без сжатия agent не может работать с большими кодовыми базами.
+
+## Решение
+
+Три уровня, с нарастающей агрессивностью:
+
+```
+Every turn:
++------------------+
+| Tool call result |
++------------------+
+ |
+ v
+[Layer 1: micro_compact] (silent, every turn)
+ Replace tool_result > 3 turns old
+ with "[Previous: used {tool_name}]"
+ |
+ v
+[Check: tokens > 50000?]
+ | |
+ no yes
+ | |
+ v v
+continue [Layer 2: auto_compact]
+ Save transcript to .transcripts/
+ LLM summarizes conversation.
+ Replace all messages with [summary].
+ |
+ v
+ [Layer 3: compact tool]
+ Model calls compact explicitly.
+ Same summarization as auto_compact.
+```
+
+## Как это работает
+
+1. **Layer 1 -- micro_compact**: Перед каждым вызовом LLM заменяет старые результаты tool на заглушки.
+
+```python
+def micro_compact(messages: list) -> list:
+ tool_results = []
+ for i, msg in enumerate(messages):
+ if msg["role"] == "user" and isinstance(msg.get("content"), list):
+ for j, part in enumerate(msg["content"]):
+ if isinstance(part, dict) and part.get("type") == "tool_result":
+ tool_results.append((i, j, part))
+ if len(tool_results) <= KEEP_RECENT:
+ return messages
+ for _, _, part in tool_results[:-KEEP_RECENT]:
+ if len(part.get("content", "")) > 100:
+ part["content"] = f"[Previous: used {tool_name}]"
+ return messages
+```
+
+2. **Layer 2 -- auto_compact**: Когда количество токенов превышает порог, сохраняет полный transcript на диск, затем просит LLM создать резюме.
+
+```python
+def auto_compact(messages: list) -> list:
+ # Save transcript for recovery
+ transcript_path = TRANSCRIPT_DIR / f"transcript_{int(time.time())}.jsonl"
+ with open(transcript_path, "w") as f:
+ for msg in messages:
+ f.write(json.dumps(msg, default=str) + "\n")
+ # LLM summarizes
+ response = client.messages.create(
+ model=MODEL,
+ messages=[{"role": "user", "content":
+ "Summarize this conversation for continuity..."
+ + json.dumps(messages, default=str)[:80000]}],
+ max_tokens=2000,
+ )
+ return [
+ {"role": "user", "content": f"[Compressed]\n\n{response.content[0].text}"},
+ ]
+```
+
+3. **Layer 3 -- ручное сжатие**: tool `compact` запускает то же самое суммирование по требованию.
+
+4. loop объединяет все три уровня:
+
+```python
+def agent_loop(messages: list):
+ while True:
+ micro_compact(messages) # Layer 1
+ if estimate_tokens(messages) > THRESHOLD:
+ messages[:] = auto_compact(messages) # Layer 2
+ response = client.messages.create(...)
+ # ... tool execution ...
+ if manual_compact:
+ messages[:] = auto_compact(messages) # Layer 3
+```
+
+Transcript сохраняют полную историю на диске. Ничто не теряется по-настоящему -- данные просто перемещаются за пределы активного context.
+
+## Что изменилось по сравнению с s05
+
+| Компонент | До (s05) | После (s06) |
+|----------------|------------------|----------------------------|
+| Tools | 5 | 5 (base + compact) |
+| Управление context | Отсутствует | Трёхуровневое сжатие |
+| Micro-compact | Отсутствует | Старые результаты -> заглушки|
+| Auto-compact | Отсутствует | Срабатывание по порогу токенов|
+| Transcript | Отсутствуют | Сохраняются в .transcripts/|
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s06_context_compact.py
+```
+
+1. `Read every Python file in the agents/ directory one by one` (наблюдай, как micro-compact заменяет старые результаты)
+2. `Keep reading files until compression triggers automatically`
+3. `Use the compact tool to manually compress the conversation`
diff --git a/docs/ru/s07-task-system.md b/docs/ru/s07-task-system.md
new file mode 100644
index 000000000..ecdff65ed
--- /dev/null
+++ b/docs/ru/s07-task-system.md
@@ -0,0 +1,131 @@
+# s07: Task System
+
+`s01 > s02 > s03 > s04 > s05 > s06 | [ s07 ] s08 > s09 > s10 > s11 > s12`
+
+> *"Разбивай большие цели на маленькие task, упорядочивай их, сохраняй на диск"* -- файловый граф task с зависимостями, закладывающий основу для многоагентного взаимодействия.
+>
+> **Harness layer**: Постоянные task -- цели, которые переживают любой отдельный разговор.
+
+## Проблема
+
+TodoManager из s03 — это плоский чек-лист в памяти: без упорядочивания, без зависимостей, без статусов помимо «сделано или нет». Реальные цели имеют структуру -- task B зависит от task A, task C и D можно выполнять параллельно, task E ждёт завершения обеих: C и D.
+
+Без явных связей agent не может определить, что готово к выполнению, что заблокировано и что можно запустить одновременно. А поскольку список живёт только в памяти, сжатие context (s06) полностью его уничтожает.
+
+## Решение
+
+Превратить чек-лист в **граф task**, сохраняемый на диск. Каждый task — это JSON-файл со статусом и зависимостями (`blockedBy`). Граф в любой момент отвечает на три вопроса:
+
+- **Что готово?** -- task со статусом `pending` и пустым `blockedBy`.
+- **Что заблокировано?** -- task, ожидающие завершения зависимостей.
+- **Что сделано?** -- task со статусом `completed`, завершение которых автоматически разблокирует зависимые task.
+
+```
+.tasks/
+ task_1.json {"id":1, "status":"completed"}
+ task_2.json {"id":2, "blockedBy":[1], "status":"pending"}
+ task_3.json {"id":3, "blockedBy":[1], "status":"pending"}
+ task_4.json {"id":4, "blockedBy":[2,3], "status":"pending"}
+
+Task graph (DAG):
+ +----------+
+ +--> | task 2 | --+
+ | | pending | |
++----------+ +----------+ +--> +----------+
+| task 1 | | task 4 |
+| completed| --> +----------+ +--> | blocked |
++----------+ | task 3 | --+ +----------+
+ | pending |
+ +----------+
+
+Ordering: task 1 must finish before 2 and 3
+Parallelism: tasks 2 and 3 can run at the same time
+Dependencies: task 4 waits for both 2 and 3
+Status: pending -> in_progress -> completed
+```
+
+Этот граф task становится основой координации для всего, что идёт после s07: фоновое выполнение (s08), многоагентные команды (s09+) и изоляция через worktree (s12) -- всё это читает из этой же структуры и пишет в неё.
+
+## Как это работает
+
+1. **TaskManager**: один JSON-файл на task, CRUD с графом зависимостей.
+
+```python
+class TaskManager:
+ def __init__(self, tasks_dir: Path):
+ self.dir = tasks_dir
+ self.dir.mkdir(exist_ok=True)
+ self._next_id = self._max_id() + 1
+
+ def create(self, subject, description=""):
+ task = {"id": self._next_id, "subject": subject,
+ "status": "pending", "blockedBy": [],
+ "owner": ""}
+ self._save(task)
+ self._next_id += 1
+ return json.dumps(task, indent=2)
+```
+
+2. **Разрешение зависимостей**: завершение task удаляет его ID из списка `blockedBy` всех остальных task, автоматически разблокируя зависимые.
+
+```python
+def _clear_dependency(self, completed_id):
+ for f in self.dir.glob("task_*.json"):
+ task = json.loads(f.read_text())
+ if completed_id in task.get("blockedBy", []):
+ task["blockedBy"].remove(completed_id)
+ self._save(task)
+```
+
+3. **Статус и управление зависимостями**: `update` обрабатывает переходы состояний и рёбра зависимостей.
+
+```python
+def update(self, task_id, status=None,
+ add_blocked_by=None, remove_blocked_by=None):
+ task = self._load(task_id)
+ if status:
+ task["status"] = status
+ if status == "completed":
+ self._clear_dependency(task_id)
+ if add_blocked_by:
+ task["blockedBy"] = list(set(task["blockedBy"] + add_blocked_by))
+ if remove_blocked_by:
+ task["blockedBy"] = [x for x in task["blockedBy"] if x not in remove_blocked_by]
+ self._save(task)
+```
+
+4. Четыре tool для task добавляются в таблицу обработчиков.
+
+```python
+TOOL_HANDLERS = {
+ # ...base tools...
+ "task_create": lambda **kw: TASKS.create(kw["subject"]),
+ "task_update": lambda **kw: TASKS.update(kw["task_id"], kw.get("status")),
+ "task_list": lambda **kw: TASKS.list_all(),
+ "task_get": lambda **kw: TASKS.get(kw["task_id"]),
+}
+```
+
+Начиная с s07, граф task используется по умолчанию для многошаговых работ. Todo из s03 остаётся для быстрых чек-листов в рамках одной сессии.
+
+## Что изменилось по сравнению с s06
+
+| Компонент | До (s06) | После (s07) |
+|---|---|---|
+| Tools | 5 | 8 (`task_create/update/list/get`) |
+| Модель планирования | Плоский чек-лист (в памяти) | Граф task с зависимостями (на диске) |
+| Связи | Отсутствуют | Рёбра `blockedBy` |
+| Отслеживание статусов | Сделано или нет | `pending` -> `in_progress` -> `completed` |
+| Сохранение | Теряется при сжатии | Переживает сжатие и перезапуски |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s07_task_system.py
+```
+
+1. `Create 3 tasks: "Setup project", "Write code", "Write tests". Make them depend on each other in order.`
+2. `List all tasks and show the dependency graph`
+3. `Complete task 1 and then list tasks to see task 2 unblocked`
+4. `Create a task board for refactoring: parse -> transform -> emit -> test, where transform and emit can run in parallel after parse`
diff --git a/docs/ru/s08-background-tasks.md b/docs/ru/s08-background-tasks.md
new file mode 100644
index 000000000..dbcf375b6
--- /dev/null
+++ b/docs/ru/s08-background-tasks.md
@@ -0,0 +1,107 @@
+# s08: Background Tasks
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > [ s08 ] s09 > s10 > s11 > s12`
+
+> *"Запускай медленные операции в background; agent продолжает думать"* -- потоки-демоны выполняют команды и уведомляют о завершении.
+>
+> **Harness layer**: Фоновое выполнение -- model думает, пока harness ждёт.
+
+## Проблема
+
+Некоторые команды выполняются минутами: `npm install`, `pytest`, `docker build`. При блокирующем loop model простаивает в ожидании. Если пользователь просит «установи зависимости и пока они устанавливаются, создай конфигурационный файл», agent выполняет задачи последовательно, а не параллельно.
+
+## Решение
+
+```
+Main thread Background thread
++-----------------+ +-----------------+
+| agent loop | | subprocess runs |
+| ... | | ... |
+| [LLM call] <---+------- | enqueue(result) |
+| ^drain queue | +-----------------+
++-----------------+
+
+Timeline:
+Agent --[spawn A]--[spawn B]--[other work]----
+ | |
+ v v
+ [A runs] [B runs] (parallel)
+ | |
+ +-- results injected before next LLM call --+
+```
+
+## Как это работает
+
+1. BackgroundManager отслеживает task с потокобезопасной очередью уведомлений.
+
+```python
+class BackgroundManager:
+ def __init__(self):
+ self.tasks = {}
+ self._notification_queue = []
+ self._lock = threading.Lock()
+```
+
+2. `run()` запускает поток-демон и немедленно возвращает управление.
+
+```python
+def run(self, command: str) -> str:
+ task_id = str(uuid.uuid4())[:8]
+ self.tasks[task_id] = {"status": "running", "command": command}
+ thread = threading.Thread(
+ target=self._execute, args=(task_id, command), daemon=True)
+ thread.start()
+ return f"Background task {task_id} started"
+```
+
+3. Когда подпроцесс завершается, его результат помещается в очередь уведомлений.
+
+```python
+def _execute(self, task_id, command):
+ try:
+ r = subprocess.run(command, shell=True, cwd=WORKDIR,
+ capture_output=True, text=True, timeout=300)
+ output = (r.stdout + r.stderr).strip()[:50000]
+ except subprocess.TimeoutExpired:
+ output = "Error: Timeout (300s)"
+ with self._lock:
+ self._notification_queue.append({
+ "task_id": task_id, "result": output[:500]})
+```
+
+4. agent loop опустошает очередь уведомлений перед каждым вызовом LLM.
+
+```python
+def agent_loop(messages: list):
+ while True:
+ notifs = BG.drain_notifications()
+ if notifs:
+ notif_text = "\n".join(
+ f"[bg:{n['task_id']}] {n['result']}" for n in notifs)
+ messages.append({"role": "user",
+ "content": f"\n{notif_text}\n"
+ f""})
+ response = client.messages.create(...)
+```
+
+loop остаётся однопоточным. Параллелизируется только ввод-вывод подпроцессов.
+
+## Что изменилось по сравнению с s07
+
+| Компонент | До (s07) | После (s08) |
+|----------------|------------------|----------------------------|
+| Tools | 8 | 6 (base + background_run + check)|
+| Выполнение | Только блокирующее | Блокирующее + background-потоки|
+| Уведомления | Отсутствуют | Очередь, опустошаемая за loop|
+| Параллелизм | Отсутствует | Потоки-демоны |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s08_background_tasks.py
+```
+
+1. `Run "sleep 5 && echo done" in the background, then create a file while it runs`
+2. `Start 3 background tasks: "sleep 2", "sleep 4", "sleep 6". Check their status.`
+3. `Run pytest in the background and keep working on other things`
diff --git a/docs/ru/s09-agent-teams.md b/docs/ru/s09-agent-teams.md
new file mode 100644
index 000000000..95590d8d6
--- /dev/null
+++ b/docs/ru/s09-agent-teams.md
@@ -0,0 +1,125 @@
+# s09: Команды агентов
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > [ s09 ] s10 > s11 > s12`
+
+> *"Когда задача слишком велика для одного — делегируй коллегам"* -- постоянные коллеги + асинхронные mailbox-ы.
+>
+> **Harness layer**: Team mailbox-ы -- несколько model-ей, скоординированных через файлы.
+
+## Проблема
+
+Subagent-ы (s04) одноразовые: запустить, поработать, вернуть резюме, завершить. Нет идентичности, нет памяти между вызовами. Фоновые задачи (s08) выполняют команды оболочки, но не могут принимать решения под управлением LLM.
+
+Настоящая командная работа требует: (1) постоянных агентов, которые живут дольше одного промпта, (2) управления идентичностью и жизненным циклом, (3) канала коммуникации между агентами.
+
+## Решение
+
+```
+Жизненный цикл коллеги:
+ spawn -> WORKING -> IDLE -> WORKING -> ... -> SHUTDOWN
+
+Коммуникация:
+ .team/
+ config.json <- состав команды + статусы
+ inbox/
+ alice.jsonl <- только дозапись, очищается при чтении
+ bob.jsonl
+ lead.jsonl
+
+ +--------+ send("alice","bob","...") +--------+
+ | alice | -----------------------------> | bob |
+ | loop | bob.jsonl << {json_line} | loop |
+ +--------+ +--------+
+ ^ |
+ | BUS.read_inbox("alice") |
+ +---- alice.jsonl -> read + drain ---------+
+```
+
+## Как это работает
+
+1. TeammateManager поддерживает config.json со списком команды.
+
+```python
+class TeammateManager:
+ def __init__(self, team_dir: Path):
+ self.dir = team_dir
+ self.dir.mkdir(exist_ok=True)
+ self.config_path = self.dir / "config.json"
+ self.config = self._load_config()
+ self.threads = {}
+```
+
+2. `spawn()` создаёт коллегу и запускает его agent loop в отдельном потоке.
+
+```python
+def spawn(self, name: str, role: str, prompt: str) -> str:
+ member = {"name": name, "role": role, "status": "working"}
+ self.config["members"].append(member)
+ self._save_config()
+ thread = threading.Thread(
+ target=self._teammate_loop,
+ args=(name, role, prompt), daemon=True)
+ thread.start()
+ return f"Spawned teammate '{name}' (role: {role})"
+```
+
+3. MessageBus: JSONL inbox-ы с дозаписью. `send()` добавляет строку JSON; `read_inbox()` читает всё и очищает.
+
+```python
+class MessageBus:
+ def send(self, sender, to, content, msg_type="message", extra=None):
+ msg = {"type": msg_type, "from": sender,
+ "content": content, "timestamp": time.time()}
+ if extra:
+ msg.update(extra)
+ with open(self.dir / f"{to}.jsonl", "a") as f:
+ f.write(json.dumps(msg) + "\n")
+
+ def read_inbox(self, name):
+ path = self.dir / f"{name}.jsonl"
+ if not path.exists(): return "[]"
+ msgs = [json.loads(l) for l in path.read_text().strip().splitlines() if l]
+ path.write_text("") # drain
+ return json.dumps(msgs, indent=2)
+```
+
+4. Каждый коллега проверяет свой inbox перед каждым вызовом LLM, добавляя полученные сообщения в context.
+
+```python
+def _teammate_loop(self, name, role, prompt):
+ messages = [{"role": "user", "content": prompt}]
+ for _ in range(50):
+ inbox = BUS.read_inbox(name)
+ if inbox != "[]":
+ messages.append({"role": "user",
+ "content": f"{inbox}"})
+ response = client.messages.create(...)
+ if response.stop_reason != "tool_use":
+ break
+ # выполнить tool-ы, добавить результаты...
+ self._find_member(name)["status"] = "idle"
+```
+
+## Что изменилось по сравнению с s08
+
+| Компонент | До (s08) | После (s09) |
+|----------------|------------------|----------------------------|
+| Tool-ы | 6 | 9 (+spawn/send/read_inbox) |
+| Агенты | Один | Lead + N коллег |
+| Персистентность| Нет | config.json + JSONL inbox-ы|
+| Потоки | Фоновые команды | Полный agent loop в потоке |
+| Жизненный цикл | Запустить-забыть | idle -> working -> idle |
+| Коммуникация | Нет | message + broadcast |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s09_agent_teams.py
+```
+
+1. `Spawn alice (coder) and bob (tester). Have alice send bob a message.`
+2. `Broadcast "status update: phase 1 complete" to all teammates`
+3. `Check the lead inbox for any messages`
+4. Введи `/team`, чтобы увидеть список команды со статусами
+5. Введи `/inbox`, чтобы вручную проверить inbox лида
diff --git a/docs/ru/s10-team-protocols.md b/docs/ru/s10-team-protocols.md
new file mode 100644
index 000000000..99b90500b
--- /dev/null
+++ b/docs/ru/s10-team-protocols.md
@@ -0,0 +1,106 @@
+# s10: Team Protocols
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > [ s10 ] s11 > s12`
+
+> *"Коллегам нужны общие правила коммуникации"* -- один паттерн запрос-ответ управляет всеми переговорами.
+>
+> **Harness layer**: Protocol-ы -- структурированные handshake-и между model-ями.
+
+## Проблема
+
+В s09 коллеги работают и общаются, но им не хватает структурированной координации:
+
+**Завершение работы**: Принудительное завершение потока оставляет файлы недозаписанными, а config.json устаревшим. Нужен handshake: лид запрашивает, коллега соглашается (завершить и выйти) или отказывает (продолжать работу).
+
+**Согласование плана**: Когда лид говорит «отрефакторь модуль аутентификации», коллега сразу приступает. Для высокорисковых изменений лид должен сначала проверить план.
+
+Оба случая имеют одинаковую структуру: одна сторона отправляет запрос с уникальным ID, другая отвечает, ссылаясь на этот же ID.
+
+## Решение
+
+```
+Shutdown Protocol Plan Approval Protocol
+================== ======================
+
+Lead Teammate Teammate Lead
+ | | | |
+ |--shutdown_req-->| |--plan_req------>|
+ | {req_id:"abc"} | | {req_id:"xyz"} |
+ | | | |
+ |<--shutdown_resp-| |<--plan_resp-----|
+ | {req_id:"abc", | | {req_id:"xyz", |
+ | approve:true} | | approve:true} |
+
+Общий FSM:
+ [pending] --approve--> [approved]
+ [pending] --reject---> [rejected]
+
+Трекеры:
+ shutdown_requests = {req_id: {target, status}}
+ plan_requests = {req_id: {from, plan, status}}
+```
+
+## Как это работает
+
+1. Лид инициирует завершение работы, генерируя request_id и отправляя его через inbox.
+
+```python
+shutdown_requests = {}
+
+def handle_shutdown_request(teammate: str) -> str:
+ req_id = str(uuid.uuid4())[:8]
+ shutdown_requests[req_id] = {"target": teammate, "status": "pending"}
+ BUS.send("lead", teammate, "Please shut down gracefully.",
+ "shutdown_request", {"request_id": req_id})
+ return f"Shutdown request {req_id} sent (status: pending)"
+```
+
+2. Коллега получает запрос и отвечает — approve или reject.
+
+```python
+if tool_name == "shutdown_response":
+ req_id = args["request_id"]
+ approve = args["approve"]
+ shutdown_requests[req_id]["status"] = "approved" if approve else "rejected"
+ BUS.send(sender, "lead", args.get("reason", ""),
+ "shutdown_response",
+ {"request_id": req_id, "approve": approve})
+```
+
+3. Согласование плана следует идентичному паттерну. Коллега отправляет план (генерируя request_id), лид проверяет (ссылаясь на тот же request_id).
+
+```python
+plan_requests = {}
+
+def handle_plan_review(request_id, approve, feedback=""):
+ req = plan_requests[request_id]
+ req["status"] = "approved" if approve else "rejected"
+ BUS.send("lead", req["from"], feedback,
+ "plan_approval_response",
+ {"request_id": request_id, "approve": approve})
+```
+
+Один FSM, два применения. Одна и та же машина состояний `pending -> approved | rejected` обслуживает любой protocol запрос-ответ.
+
+## Что изменилось по сравнению с s09
+
+| Компонент | До (s09) | После (s10) |
+|----------------|------------------|------------------------------|
+| Tool-ы | 9 | 12 (+shutdown_req/resp +plan)|
+| Завершение | Естественный выход| Handshake запрос-ответ |
+| Контроль плана | Нет | Отправка/проверка с согласованием|
+| Корреляция | Нет | request_id для каждого запроса|
+| FSM | Нет | pending -> approved/rejected |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s10_team_protocols.py
+```
+
+1. `Spawn alice as a coder. Then request her shutdown.`
+2. `List teammates to see alice's status after shutdown approval`
+3. `Spawn bob with a risky refactoring task. Review and reject his plan.`
+4. `Spawn charlie, have him submit a plan, then approve it.`
+5. Введи `/team`, чтобы следить за статусами
diff --git a/docs/ru/s11-autonomous-agents.md b/docs/ru/s11-autonomous-agents.md
new file mode 100644
index 000000000..3566705b7
--- /dev/null
+++ b/docs/ru/s11-autonomous-agents.md
@@ -0,0 +1,142 @@
+# s11: Автономные агенты
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > [ s11 ] s12`
+
+> *"Коллеги сами просматривают доску и берут задачи"* -- лиду не нужно назначать каждую вручную.
+>
+> **Harness layer**: Автономность -- model-и, которые находят работу без указаний.
+
+## Проблема
+
+В s09-s10 коллеги работают только тогда, когда им явно говорят. Лид должен запустить каждого с конкретным промптом. Десять невзятых задач на доске? Лид назначает каждую вручную. Не масштабируется.
+
+Настоящая автономность: коллеги сами просматривают доску задач, берут свободные задачи, работают над ними, затем ищут следующие.
+
+Один нюанс: после сжатия context-а (s06) агент может забыть, кто он. Повторная инъекция идентичности решает эту проблему.
+
+## Решение
+
+```
+Жизненный цикл коллеги с циклом ожидания:
+
++-------+
+| spawn |
++---+---+
+ |
+ v
++-------+ tool_use +-------+
+| WORK | <------------- | LLM |
++---+---+ +-------+
+ |
+ | stop_reason != tool_use (or idle tool called)
+ v
++--------+
+| IDLE | опрос каждые 5с, до 60с
++---+----+
+ |
+ +---> проверить inbox --> сообщение? -------> WORK
+ |
+ +---> сканировать .tasks/ --> свободная? ---> взять -> WORK
+ |
+ +---> таймаут 60с --------------------------> SHUTDOWN
+
+Повторная инъекция идентичности после сжатия:
+ if len(messages) <= 3:
+ messages.insert(0, identity_block)
+```
+
+## Как это работает
+
+1. Loop коллеги имеет две фазы: WORK и IDLE. Когда LLM перестаёт вызывать tool-ы (или вызывает `idle`), коллега переходит в IDLE.
+
+```python
+def _loop(self, name, role, prompt):
+ while True:
+ # -- ФАЗА WORK --
+ messages = [{"role": "user", "content": prompt}]
+ for _ in range(50):
+ response = client.messages.create(...)
+ if response.stop_reason != "tool_use":
+ break
+ # выполнить tool-ы...
+ if idle_requested:
+ break
+
+ # -- ФАЗА IDLE --
+ self._set_status(name, "idle")
+ resume = self._idle_poll(name, messages)
+ if not resume:
+ self._set_status(name, "shutdown")
+ return
+ self._set_status(name, "working")
+```
+
+2. Фаза IDLE опрашивает inbox и доску задач в цикле.
+
+```python
+def _idle_poll(self, name, messages):
+ for _ in range(IDLE_TIMEOUT // POLL_INTERVAL): # 60s / 5s = 12
+ time.sleep(POLL_INTERVAL)
+ inbox = BUS.read_inbox(name)
+ if inbox:
+ messages.append({"role": "user",
+ "content": f"{inbox}"})
+ return True
+ unclaimed = scan_unclaimed_tasks()
+ if unclaimed:
+ claim_task(unclaimed[0]["id"], name)
+ messages.append({"role": "user",
+ "content": f"Task #{unclaimed[0]['id']}: "
+ f"{unclaimed[0]['subject']}"})
+ return True
+ return False # таймаут -> завершение
+```
+
+3. Сканирование доски задач: найти задачи в статусе pending, без владельца, без блокировок.
+
+```python
+def scan_unclaimed_tasks() -> list:
+ unclaimed = []
+ for f in sorted(TASKS_DIR.glob("task_*.json")):
+ task = json.loads(f.read_text())
+ if (task.get("status") == "pending"
+ and not task.get("owner")
+ and not task.get("blockedBy")):
+ unclaimed.append(task)
+ return unclaimed
+```
+
+4. Повторная инъекция идентичности: когда context слишком короткий (произошло сжатие), вставить блок идентичности.
+
+```python
+if len(messages) <= 3:
+ messages.insert(0, {"role": "user",
+ "content": f"You are '{name}', role: {role}, "
+ f"team: {team_name}. Continue your work."})
+ messages.insert(1, {"role": "assistant",
+ "content": f"I am {name}. Continuing."})
+```
+
+## Что изменилось по сравнению с s10
+
+| Компонент | До (s10) | После (s11) |
+|----------------|------------------|----------------------------|
+| Tool-ы | 12 | 14 (+idle, +claim_task) |
+| Автономность | Управляется лидом| Самоорганизующаяся |
+| Фаза IDLE | Нет | Опрос inbox + доски задач |
+| Взятие задач | Только вручную | Авто-взятие свободных задач|
+| Идентичность | System prompt | + повторная инъекция после сжатия|
+| Таймаут | Нет | 60с IDLE -> авто-завершение|
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s11_autonomous_agents.py
+```
+
+1. `Create 3 tasks on the board, then spawn alice and bob. Watch them auto-claim.`
+2. `Spawn a coder teammate and let it find work from the task board itself`
+3. `Create tasks with dependencies. Watch teammates respect the blocked order.`
+4. Введи `/tasks`, чтобы увидеть доску задач с владельцами
+5. Введи `/team`, чтобы следить за тем, кто работает, а кто в IDLE
diff --git a/docs/ru/s12-worktree-task-isolation.md b/docs/ru/s12-worktree-task-isolation.md
new file mode 100644
index 000000000..537e86f03
--- /dev/null
+++ b/docs/ru/s12-worktree-task-isolation.md
@@ -0,0 +1,121 @@
+# s12: Worktree + Изоляция задач
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > [ s12 ]`
+
+> *"Каждый работает в своей директории — никаких конфликтов"* -- task-и управляют целями, worktree-ы управляют директориями, связанными по ID.
+>
+> **Harness layer**: Изоляция директорий -- параллельные полосы выполнения, которые никогда не пересекаются.
+
+## Проблема
+
+К s11 агенты могут самостоятельно брать и выполнять task-и. Но каждая task выполняется в одной общей директории. Два агента, рефакторящих разные модули одновременно, столкнутся: агент A редактирует `config.py`, агент B редактирует `config.py`, нестейджированные изменения смешиваются, и ни один не может откатиться чисто.
+
+Доска задач отслеживает *что делать*, но не имеет мнения о *где делать*. Решение: дать каждой task свой git worktree. Task-и управляют целями, worktree-ы управляют контекстом выполнения. Связать их по task ID.
+
+## Решение
+
+```
+Плоскость управления (.tasks/) Плоскость выполнения (.worktrees/)
++------------------+ +------------------------+
+| task_1.json | | auth-refactor/ |
+| status: in_progress <------> branch: wt/auth-refactor
+| worktree: "auth-refactor" | task_id: 1 |
++------------------+ +------------------------+
+| task_2.json | | ui-login/ |
+| status: pending <------> branch: wt/ui-login
+| worktree: "ui-login" | task_id: 2 |
++------------------+ +------------------------+
+ |
+ index.json (реестр worktree-ов)
+ events.jsonl (лог жизненного цикла)
+
+Машины состояний:
+ Task: pending -> in_progress -> completed
+ Worktree: absent -> active -> removed | kept
+```
+
+## Как это работает
+
+1. **Создать task.** Сначала сохранить цель.
+
+```python
+TASKS.create("Implement auth refactor")
+# -> .tasks/task_1.json status=pending worktree=""
+```
+
+2. **Создать worktree и привязать к task.** Передача `task_id` автоматически переводит task в `in_progress`.
+
+```python
+WORKTREES.create("auth-refactor", task_id=1)
+# -> git worktree add -b wt/auth-refactor .worktrees/auth-refactor HEAD
+# -> index.json получает новую запись, task_1.json получает worktree="auth-refactor"
+```
+
+Привязка записывает состояние на обе стороны:
+
+```python
+def bind_worktree(self, task_id, worktree):
+ task = self._load(task_id)
+ task["worktree"] = worktree
+ if task["status"] == "pending":
+ task["status"] = "in_progress"
+ self._save(task)
+```
+
+3. **Выполнять команды в worktree.** `cwd` указывает на изолированную директорию.
+
+```python
+subprocess.run(command, shell=True, cwd=worktree_path,
+ capture_output=True, text=True, timeout=300)
+```
+
+4. **Завершить работу.** Два варианта:
+ - `worktree_keep(name)` -- сохранить директорию для дальнейшего использования.
+ - `worktree_remove(name, complete_task=True)` -- удалить директорию, завершить привязанную task, отправить event. Один вызов обрабатывает и teardown, и завершение.
+
+```python
+def remove(self, name, force=False, complete_task=False):
+ self._run_git(["worktree", "remove", wt["path"]])
+ if complete_task and wt.get("task_id") is not None:
+ self.tasks.update(wt["task_id"], status="completed")
+ self.tasks.unbind_worktree(wt["task_id"])
+ self.events.emit("task.completed", ...)
+```
+
+5. **Поток event-ов.** Каждый шаг жизненного цикла отправляет запись в `.worktrees/events.jsonl`:
+
+```json
+{
+ "event": "worktree.remove.after",
+ "task": {"id": 1, "status": "completed"},
+ "worktree": {"name": "auth-refactor", "status": "removed"},
+ "ts": 1730000000
+}
+```
+
+Отправляемые event-ы: `worktree.create.before/after/failed`, `worktree.remove.before/after/failed`, `worktree.keep`, `task.completed`.
+
+После сбоя состояние восстанавливается из `.tasks/` + `.worktrees/index.json` на диске. Память в разговоре энергозависима; состояние в файлах — нет.
+
+## Что изменилось по сравнению с s11
+
+| Компонент | До (s11) | После (s12) |
+|-----------------------|----------------------------|----------------------------------------------|
+| Координация | Доска задач (owner/status) | Доска задач + явная привязка worktree |
+| Область выполнения | Общая директория | Изолированная директория на task |
+| Восстанавливаемость | Только статус task | Статус task + индекс worktree |
+| Завершение работы | Завершение task | Завершение task + явный keep/remove |
+| Видимость жизн. цикла | Неявно в логах | Явные event-ы в `.worktrees/events.jsonl` |
+
+## Попробуй сам
+
+```sh
+cd learn-claude-code
+python agents/s12_worktree_task_isolation.py
+```
+
+1. `Create tasks for backend auth and frontend login page, then list tasks.`
+2. `Create worktree "auth-refactor" for task 1, then bind task 2 to a new worktree "ui-login".`
+3. `Run "git status --short" in worktree "auth-refactor".`
+4. `Keep worktree "ui-login", then list worktrees and inspect events.`
+5. `Remove worktree "auth-refactor" with complete_task=true, then list tasks/worktrees/events.`