diff --git a/README-ja.md b/README-ja.md
index 8717201b8..89e07beb2 100644
--- a/README-ja.md
+++ b/README-ja.md
@@ -1,6 +1,6 @@
# Learn Claude Code -- 真の Agent のための Harness Engineering
-[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md)
+[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md) | [한국어](./README-ko.md)
## モデルこそが Agent である
@@ -291,7 +291,7 @@ s08 バックグラウンドタスク [6] s10 チームプロトコル
learn-claude-code/
|
|-- agents/ # Python リファレンス実装 (s01-s12 + s_full 総括)
-|-- docs/{en,zh,ja}/ # メンタルモデル優先のドキュメント (3言語)
+|-- docs/{en,zh,ja,ko}/ # メンタルモデル優先のドキュメント (4言語)
|-- web/ # インタラクティブ学習プラットフォーム (Next.js)
|-- skills/ # s05 の Skill ファイル
+-- .github/workflows/ci.yml # CI: 型チェック + ビルド
@@ -300,7 +300,7 @@ learn-claude-code/
## ドキュメント
メンタルモデル優先: 問題、解決策、ASCII図、最小限のコード。
-[English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/)
+[English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/) | [한국어](./docs/ko/)
| セッション | トピック | モットー |
|-----------|---------|---------|
diff --git a/README-ko.md b/README-ko.md
new file mode 100644
index 000000000..50b28bd8b
--- /dev/null
+++ b/README-ko.md
@@ -0,0 +1,380 @@
+[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md) | [한국어](./README-ko.md)
+
+# Learn Claude Code -- 진짜 Agent를 위한 Harness Engineering
+
+## 모델이 곧 Agent입니다
+
+코드 이야기를 시작하기 전에, 한 가지를 분명히 하고 넘어가겠습니다.
+
+**Agent란 모델입니다. 프레임워크(Framework)가 아닙니다. 프롬프트 체인(Prompt Chain)이 아닙니다. 드래그 앤 드롭(Drag-and-Drop) 워크플로도 아닙니다.**
+
+### Agent란 무엇인가
+
+Agent는 신경망(Neural Network)입니다. Transformer, RNN, 혹은 학습된 함수처럼, 수십억 번의 gradient update를 거치며 행동 시퀀스(action-sequence) 데이터 위에서 환경을 지각하고, 목표를 추론하고, 행동하는 법을 학습한 존재입니다. AI에서 "Agent"라는 말은 처음부터 이 의미였습니다. 늘 그랬습니다.
+
+인간도 Agent입니다. 수백만 년의 진화적 훈련을 통해 형성된 생물학적 신경망입니다. 감각으로 세계를 지각하고, 뇌로 추론하며, 몸으로 행동합니다. DeepMind, OpenAI, Anthropic이 "Agent"라고 말할 때도, 그 의미는 이 분야가 처음부터 써온 의미와 같습니다. **행동하는 법을 학습한 모델**입니다.
+
+역사가 그 증거를 보여줍니다.
+
+- **2013 -- DeepMind DQN plays Atari.** 단일 신경망이 raw pixel과 game score만 받아 7개의 Atari 2600 게임을 학습했고, 이전의 모든 알고리즘을 뛰어넘었으며 그중 3개에서는 인간 전문가를 이겼습니다. 2015년에는 같은 아키텍처가 [49개 게임으로 확장되어 professional human tester 수준에 도달](https://www.nature.com/articles/nature14236)했고, *Nature*에 실렸습니다. 게임별 규칙도 없었습니다. decision tree도 없었습니다. 하나의 모델이 경험으로부터 학습했습니다. 그 모델이 곧 Agent였습니다.
+
+- **2019 -- OpenAI Five conquers Dota 2.** 5개의 신경망이 10개월 동안 [45,000년 분량의 Dota 2](https://openai.com/index/openai-five-defeats-dota-2-world-champions/)를 self-play했고, 샌프란시스코 라이브 스트리밍에서 **OG** -- TI8 월드 챔피언 -- 를 2-0으로 꺾었습니다. 이후 공개 아레나에서는 42,729경기 중 99.4%를 승리했습니다. 스크립트된 전략은 없었습니다. 메타 프로그래밍된 팀 협업도 없었습니다. 모델이 온전히 self-play를 통해 팀워크, 전술, 실시간 적응을 학습했습니다.
+
+- **2019 -- DeepMind AlphaStar masters 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)했습니다. 이는 90,000명 중 상위 0.15%였습니다. 불완전 정보, 실시간 판단, 체스와 바둑을 훨씬 뛰어넘는 조합적 action space를 가진 게임입니다. Agent는 무엇이었습니까? 모델이었습니다. 학습된 모델이었습니다. 스크립트가 아니었습니다.
+
+- **2019 -- Tencent Jueyu dominates Honor of Kings.** Tencent AI Lab의 "Jueyu"는 2019년 8월 2일 World Champion Cup에서 [KPL 프로 선수를 상대로 5v5 경기에서 승리](https://www.jiemian.com/article/3371171.html)했습니다. 1v1 모드에서는 프로 선수가 [15전 중 1승만 거두었고, 8분 이상 버티지 못했습니다](https://developer.aliyun.com/article/851058). 훈련 강도는 1일이 인간 440년에 해당했습니다. 2021년까지는 전체 hero pool에서 KPL 프로를 전면적으로 앞질렀습니다. 손으로 만든 hero matchup table도 없었습니다. 스크립트된 조합도 없었습니다. self-play로 게임 전체를 처음부터 학습한 모델이었습니다.
+
+- **2024-2025 -- LLM Agent reshapes software engineering.** Claude, GPT, Gemini -- 인류의 코드와 추론 전반을 학습한 대규모 언어 모델 -- 이 coding Agent로 배치되고 있습니다. 코드베이스를 읽고, 구현을 작성하고, 장애를 디버깅하고, 팀 단위로 협업합니다. 아키텍처는 앞선 모든 Agent와 동일합니다. 학습된 모델이 환경에 놓이고, 지각하고 행동할 수 있는 도구를 부여받습니다. 차이는 단 하나입니다. 학습 규모와 해결 가능한 작업의 범용성입니다.
+
+이 모든 이정표가 같은 진실을 말하고 있습니다. **"Agent"는 결코 주변의 코드가 아닙니다. Agent는 언제나 모델 그 자체입니다.**
+
+### Agent가 아닌 것
+
+"Agent"라는 단어는 프롬프트 배관(prompt plumbing) 산업 전체에 의해 잘못 소비되고 있습니다.
+
+드래그 앤 드롭 워크플로 빌더입니다. 노코드 "AI Agent" 플랫폼입니다. 프롬프트 체인 orchestration 라이브러리입니다. 이들은 모두 같은 환상을 공유합니다. LLM API 호출을 if-else 분기, 노드 그래프, 하드코딩된 라우팅 로직으로 엮으면 그것이 곧 "Agent를 만드는 일"이라고 믿습니다.
+
+아닙니다. 그들이 만든 것은 루브 골드버그 머신입니다. 과도하게 설계된, 취약한 절차적 규칙 파이프라인입니다. LLM은 그 안에 포장된 텍스트 완성 노드처럼 끼워 넣어져 있을 뿐입니다. 그것은 Agent가 아닙니다. 거대한 망상을 가진 shell script에 가깝습니다.
+
+**프롬프트 배관식 "Agent"는 모델을 훈련하지 않는 프로그래머의 환상입니다.** 절차적 로직을 계속 쌓아 올려 지능을 힘으로 구현하려고 합니다. 거대한 rule tree, node graph, chain-of-prompt waterfall을 만들고, 언젠가 충분한 glue code가 자율적 행동을 창발시켜 주기를 바랍니다. 하지만 그렇지 않습니다. Engineering만으로 agency를 코딩할 수는 없습니다. Agency는 학습되는 것이지, 프로그래밍되는 것이 아닙니다.
+
+그런 시스템은 태어나는 순간부터 한계가 정해져 있습니다. 취약하고, 확장되지 않으며, 근본적으로 일반화가 불가능합니다. 이것은 GOFAI(Good Old-Fashioned AI), 즉 고전적 기호 AI의 현대판입니다. 수십 년 전에 학계가 버린 기호 규칙 시스템에 LLM이라는 페인트만 다시 칠한 것입니다. 포장은 다르지만, 결국 같은 막다른 길입니다.
+
+### 마인드셋의 전환: "Agent를 개발한다"에서 Harness를 개발한다로
+
+"Agent를 개발하고 있다"고 말할 때, 실제로 의미할 수 있는 것은 두 가지뿐입니다.
+
+**1. 모델을 훈련시키는 것입니다.** 강화학습, fine-tuning, RLHF, 혹은 그 밖의 gradient-based 방법으로 weight를 조정하는 일입니다. task-process data -- 실제 도메인에서의 지각, 추론, 행동의 시퀀스 -- 를 수집하고, 그것으로 모델의 행동을 형성합니다. DeepMind, OpenAI, Tencent AI Lab, Anthropic이 하는 일이 바로 이것입니다. 이것이 가장 본질적인 의미의 Agent 개발입니다.
+
+**2. Harness를 구축하는 것입니다.** 모델이 작동할 수 있는 환경을 제공하는 코드를 작성하는 일입니다. 우리 대부분이 하는 일이 이것이며, 이 저장소의 핵심도 여기에 있습니다.
+
+Harness는 Agent가 특정 도메인에서 기능하기 위해 필요한 모든 것입니다.
+
+```text
+Harness = Tools + Knowledge + Observation + Action Interfaces + Permissions
+
+ Tools: 파일 입출력, 쉘, 네트워크, 데이터베이스, 브라우저
+ Knowledge: 제품 문서, 도메인 지식, API 명세, 스타일 가이드
+ Observation: git diff, 에러 로그, 브라우저 상태, 센서 데이터
+ Action: CLI 명령, API 호출, UI 상호작용
+ Permissions: 샌드박스, 승인 워크플로, 권한 경계
+```
+
+모델이 결정합니다. Harness가 실행합니다. 모델이 추론합니다. Harness가 컨텍스트를 제공합니다. 모델은 운전자입니다. Harness는 차량입니다.
+
+**Coding Agent의 Harness는 IDE, 터미널, 파일 시스템입니다.** 농업 Agent의 Harness는 센서 시스템, 관개 제어, 기상 데이터입니다. 호텔 Agent의 Harness는 예약 시스템, 고객 커뮤니케이션 채널, 시설 관리 API입니다. Agent — 지능이자 의사결정 주체 — 는 언제나 모델입니다. Harness는 도메인마다 달라집니다. 하지만 Agent는 어떤 도메인에서도 동일한 방식으로 작동합니다.
+
+이 저장소는 차량을 만드는 방법을 가르칩니다. 코딩을 위한 차량입니다. 하지만 이 설계 패턴은 특정 분야에만 국한되지 않습니다. 농장 관리, 호텔 운영, 제조, 물류, 의료, 교육, 과학 연구까지 모두 동일하게 적용됩니다.
+
+어떤 작업이든, 지각하고 → 추론하고 → 행동해야 한다면 그곳에는 Agent가 작동할 Harness가 필요합니다.
+
+### Harness 엔지니어의 역할
+
+이 저장소를 읽고 있다면, 아마 당신은 Harness 엔지니어일 것입니다. 그리고 그것은 강력한 정체성입니다. 다음이 바로 당신의 실제 역할입니다.
+
+- **도구를 구현합니다.** Agent에게 ‘손’을 제공합니다. 파일 읽기/쓰기, 셸 실행, API 호출, 브라우저 제어, 데이터베이스 쿼리 등입니다. 각 도구는 Agent가 환경에서 수행할 수 있는 행동입니다. 작고 명확하며, 서로 조합 가능하도록 설계해야 합니다.
+
+- **지식을 큐레이션합니다.** Agent에게 도메인 전문성을 제공합니다. 제품 문서, 아키텍처 결정 기록, 스타일 가이드, 규제 요구사항 등이 여기에 포함됩니다. 모든 정보를 미리 넣지 말고, 필요할 때 불러오도록 해야 합니다(s05). Agent는 어떤 정보가 있는지 알고, 필요할 때 스스로 가져와야 합니다.
+
+- **컨텍스트를 관리합니다.** Agent에게 깨끗한 작업 공간을 제공합니다. subagent isolation(s04)은 불필요한 정보가 섞이는 것을 막고, context compression(s06)은 대화가 과도하게 길어지는 것을 방지합니다. task system(s07)은 목표를 한 번의 대화에 머물지 않고 지속시킵니다.
+
+- **권한을 제어합니다.** Agent의 행동 범위를 설정합니다. 파일 접근을 제한하고, 위험한 작업에는 승인을 요구하며, 외부 시스템과의 신뢰 경계를 명확히 합니다. 이 영역은 안전 공학과 Harness 엔지니어링이 만나는 지점입니다.
+
+- **task-process data를 수집합니다.** Agent가 수행하는 모든 행동 과정은 곧 학습 데이터입니다. 실제 환경에서의 지각 → 추론 → 행동 기록은 다음 세대 Agent 모델을 개선하는 데 사용됩니다. 즉, Harness는 단순히 Agent를 돕는 것을 넘어 Agent 자체를 더 발전시키는 역할도 합니다.
+
+당신은 지능을 만드는 사람이 아닙니다. 지능이 살아갈 환경을 만드는 사람입니다. -- Agent가 얼마나 잘 지각할 수 있는지, 얼마나 정확하게 행동할 수 있는지, 얼마나 풍부한 지식을 활용할 수 있는지 —- 이 모든 것은 Harness의 품질에 달려 있습니다.
+**좋은 Harness를 만드십시오. 나머지는 Agent가 해냅니다.**
+
+### 왜 Claude Code인가 -- Harness Engineering의 교과서
+
+왜 이 저장소는 특별히 Claude Code를 해부합니까?
+
+Claude Code는 우리가 본 것 중 가장 우아하고 완성도가 높은 Agent Harness이기 때문입니다. 무언가 영리한 트릭 하나 때문이 아닙니다. 오히려 그것이 **하지 않는 것** 때문에 중요합니다. Agent 자체가 되려 하지 않습니다. 경직된 워크플로를 강요하지 않습니다. 정교한 decision tree로 모델을 계속 의심하지 않습니다. 도구, 지식, 컨텍스트 관리, 권한 경계를 제공하고, 그다음 물러섭니다.
+
+Claude Code를 본질만 남겨 쓰면 다음과 같습니다.
+
+```text
+Claude Code = one 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입니다. 모델입니다. Anthropic이 인류의 추론과 코드 전반 위에서 훈련한 모델입니다. Harness가 Claude를 똑똑하게 만든 것이 아닙니다. Claude는 이미 똑똑합니다. Harness가 Claude에게 손과 눈, 그리고 작업 공간을 준 것입니다.
+
+이것이 Claude Code가 이상적인 교육 대상인 이유입니다. **모델을 신뢰하고, 엔지니어링의 초점을 Harness에 둘 때 무엇이 가능한지를 보여주기 때문입니다.** 이 저장소의 각 세션(s01-s12)은 Claude Code 아키텍처에서 Harness 메커니즘 하나를 reverse engineering합니다. 끝까지 오면, Claude Code의 동작 방식뿐 아니라, 어떤 도메인의 어떤 Agent에도 적용되는 Harness 공학의 보편 원리를 이해하게 됩니다.
+
+교훈은 "Claude Code를 복제하라"가 아닙니다. 교훈은 이것입니다. **최고의 Agent 제품은, 자신의 일이 Intelligence가 아니라 Harness라는 사실을 이해한 엔지니어가 만듭니다.**
+
+---
+
+## 비전: 우주를 진짜 Agent로 채우기
+
+이것은 coding Agent만의 이야기가 아닙니다.
+
+인간이 복잡하고, 다단계이며, 판단 집약적인 일을 수행하는 모든 도메인은 Agent가 작동할 수 있는 도메인입니다. 올바른 Harness만 있다면 가능합니다. 이 저장소의 패턴은 보편적입니다.
+
+```text
+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
+```
+
+루프는 언제나 같습니다. 바뀌는 것은 도구입니다. 지식이 바뀝니다. 권한이 바뀝니다. Agent -- 모델 -- 가 모든 것을 일반화합니다.
+
+이 저장소를 읽는 모든 Harness 엔지니어는 소프트웨어 엔지니어링을 훨씬 넘어서는 패턴을 배우고 있습니다. 당신은 지능적이고 자동화된 미래를 위한 인프라를 구축하는 법을 배우고 있습니다. 실제 도메인에 배포된 훌륭한 Harness 하나하나가, Agent가 지각하고, 추론하고, 행동할 수 있는 새로운 거점이 됩니다.
+
+먼저 작업장을 채웁니다. 그다음 농장과 병원과 공장입니다. 그다음 도시입니다. 그다음 행성입니다.
+
+**Bash is all you need. Real agents are all the universe needs.**
+
+---
+
+```text
+ THE AGENT PATTERN
+ =================
+
+ User --> messages[] --> LLM --> response
+ |
+ stop_reason == "tool_use"?
+ / \
+ yes no
+ | |
+ execute tools return text
+ append results
+ loop back -----------------> messages[]
+
+
+ 이것이 최소 루프입니다.
+ 모든 AI Agent에는 이 루프가 필요합니다.
+ 모델이 tool 호출과 중단 시점을 결정합니다.
+ 코드는 모델의 요청을 실행할 뿐입니다.
+ 이 저장소는 이 루프를 둘러싼 모든 것,
+ 곧 특정 도메인에서 Agent를 효과적으로 만드는 Harness를
+ 어떻게 구축하는지 가르칩니다.
+```
+
+**12개의 점진적 세션이 있습니다. 단순한 loop에서 분리된 autonomous execution까지 이어집니다.**
+**각 세션은 하나의 Harness 메커니즘을 추가합니다. 각 메커니즘에는 하나의 motto가 있습니다.**
+
+> **s01** *"One loop & Bash is all you need"* — 하나의 tool + 하나의 loop = Agent
+>
+> **s02** *"Adding a tool means adding one handler"* — loop는 바뀌지 않습니다. 새 tool은 dispatch map에 등록하기만 하면 됩니다
+>
+> **s03** *"An agent without a plan drifts"* — 먼저 단계를 적고, 그다음 실행합니다
+>
+> **s04** *"Break big tasks down; each subtask gets a clean context"* — subagent는 독립된 messages[]를 사용하여 메인 대화를 오염시키지 않습니다
+>
+> **s05** *"Load knowledge when you need it, not upfront"* — system prompt가 아니라 tool_result로 주입합니다
+>
+> **s06** *"Context will fill up; you need a way to make room"* — 3계층 압축으로 무한 세션을 구현합니다
+>
+> **s07** *"Break big goals into small tasks, order them, persist to disk"* — file-based task graph가 multi-agent collaboration의 기반이 됩니다
+>
+> **s08** *"Run slow operations in the background; the agent keeps thinking"* — daemon thread가 command를 실행하고, 완료 후 notification을 주입합니다
+>
+> **s09** *"When the task is too big for one, delegate to teammates"* — persistent teammate + async mailbox
+>
+> **s10** *"Teammates need shared communication rules"* — 하나의 request-response 패턴이 모든 협상을 구동합니다
+>
+> **s11** *"Teammates scan the board and claim tasks themselves"* — 리더가 일일이 task를 배정할 필요가 없습니다
+>
+> **s12** *"Each works in its own directory, no interference"* — task는 목표를 관리하고, worktree는 디렉터리를 관리하며, 둘은 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 메커니즘 하나를 겹쳐 올립니다. 루프 자체는 바뀌지 않습니다. 루프는 Agent의 것입니다. 메커니즘은 Harness의 것입니다.
+
+## 범위 (중요)
+
+이 저장소는 Harness Engineering의 0->1 학습 프로젝트입니다. Agent 모델을 둘러싼 환경을 구축하는 법을 배우기 위한 것입니다. 학습을 우선하기 위해, 다음과 같은 production 메커니즘은 의도적으로 단순화하거나 생략했습니다.
+
+- 완전한 event / hook bus입니다. 예를 들면 PreToolUse, SessionStart/End, ConfigChange가 있습니다.
+ s12에는 교육용으로 최소한의 append-only lifecycle event stream만 구현되어 있습니다.
+- rule-based permission governance와 trust workflow입니다.
+- session lifecycle control(resume/fork)과 고급 worktree lifecycle control입니다.
+- MCP runtime의 세부사항입니다. 예를 들면 transport, OAuth, resource subscribe, polling이 있습니다.
+
+이 저장소의 team JSONL mailbox 방식은 교육용 구현입니다. 특정 production 내부 구현을 주장하는 것이 아닙니다.
+
+## Quick Start
+
+```sh
+git clone https://github.com/shareAI-lab/learn-claude-code
+cd learn-claude-code
+pip install -r requirements.txt
+cp .env.example .env # .env를 열고 ANTHROPIC_API_KEY를 입력합니다
+
+python agents/s01_agent_loop.py # 여기서 시작합니다
+python agents/s12_worktree_task_isolation.py # 전체 세션의 도착점입니다
+python agents/s_full.py # 총정리: 모든 메커니즘 통합 버전입니다
+```
+
+### Web Platform
+
+interactive visualization, step-through animation, source viewer, 각 세션 문서를 제공합니다.
+
+```sh
+cd web && npm install && npm run dev # http://localhost:3000
+```
+
+## 학습 경로
+
+```text
+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
+```
+
+## 프로젝트 구조
+
+```text
+learn-claude-code/
+|
+|-- agents/ # Python 참조 구현 (s01-s12 + s_full capstone)
+|-- docs/{en,zh,ja,ko}/ # 멘탈 모델 우선 문서 (4개 언어)
+|-- web/ # 인터랙티브 학습 플랫폼 (Next.js)
+|-- skills/ # s05용 스킬 파일
++-- .github/workflows/ci.yml # CI: 타입 체크 + 빌드
+```
+
+## 문서
+
+멘탈 모델 우선(mental-model-first) 방식입니다. 문제, 해결책, ASCII 다이어그램, 최소 코드 중심입니다.
+[English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/) | [한국어](./docs/ko/)
+
+| 세션 | 주제 | 모토 |
+|------|------|------|
+| [s01](./docs/ko/s01-the-agent-loop.md) | The Agent Loop | *One loop & Bash is all you need* |
+| [s02](./docs/ko/s02-tool-use.md) | Tool Use | *Adding a tool means adding one handler* |
+| [s03](./docs/ko/s03-todo-write.md) | TodoWrite | *An agent without a plan drifts* |
+| [s04](./docs/ko/s04-subagent.md) | Subagents | *Break big tasks down; each subtask gets a clean context* |
+| [s05](./docs/ko/s05-skill-loading.md) | Skills | *Load knowledge when you need it, not upfront* |
+| [s06](./docs/ko/s06-context-compact.md) | Context Compact | *Context will fill up; you need a way to make room* |
+| [s07](./docs/ko/s07-task-system.md) | Tasks | *Break big goals into small tasks, order them, persist to disk* |
+| [s08](./docs/ko/s08-background-tasks.md) | Background Tasks | *Run slow operations in the background; the agent keeps thinking* |
+| [s09](./docs/ko/s09-agent-teams.md) | Agent Teams | *When the task is too big for one, delegate to teammates* |
+| [s10](./docs/ko/s10-team-protocols.md) | Team Protocols | *Teammates need shared communication rules* |
+| [s11](./docs/ko/s11-autonomous-agents.md) | Autonomous Agents | *Teammates scan the board and claim tasks themselves* |
+| [s12](./docs/ko/s12-worktree-task-isolation.md) | Worktree + Task Isolation | *Each works in its own directory, no interference* |
+
+## 다음 단계 -- 이해에서 배포까지
+
+12개 세션을 마치면 Harness Engineering의 내부 구조를 깊이 이해하게 됩니다. 그 지식을 실제로 활용하는 방법은 두 가지입니다.
+
+### Kode Agent CLI -- Open-Source Coding Agent CLI
+
+> `npm i -g @shareai-lab/kode`
+
+Skill & LSP를 지원하고, Windows-ready이며, GLM / MiniMax / DeepSeek 등 open model에 연결할 수 있습니다. 설치 후 바로 사용할 수 있습니다.
+
+GitHub: **[shareAI-lab/Kode-cli](https://github.com/shareAI-lab/Kode-cli)**
+
+### Kode Agent SDK -- 앱에 Agent 기능을 내장하기
+
+공식 Claude Code Agent SDK는 내부적으로 완전한 CLI process와 통신합니다. 즉, concurrent user마다 별도의 terminal process가 필요합니다. Kode SDK는 독립 라이브러리이며 사용자별 process overhead가 없습니다. backend, browser extension, embedded device 등에도 내장할 수 있습니다.
+
+GitHub: **[shareAI-lab/Kode-agent-sdk](https://github.com/shareAI-lab/Kode-agent-sdk)**
+
+---
+
+## Sister Repo: *on-demand sessions*에서 *always-on assistant*로
+
+이 저장소가 가르치는 Harness는 **use-and-discard** 방식입니다. terminal을 열고, Agent에게 task를 주고, 끝나면 닫습니다. 다음 session은 빈 상태에서 다시 시작합니다. 이것이 Claude Code 모델입니다.
+
+[OpenClaw](https://github.com/openclaw/openclaw)는 다른 가능성을 보여주었습니다. 같은 agent core 위에 두 가지 Harness 메커니즘만 더하면, Agent는 "불러야 움직이는 도구"에서 "30초마다 스스로 깨어나 일을 찾는 존재"로 바뀝니다.
+
+- **Heartbeat** -- 30초마다 Harness가 Agent에게 메시지를 보내, 할 일이 있는지 확인합니다. 없으면 다시 잠들고, 있으면 즉시 행동합니다.
+- **Cron** -- Agent가 스스로 미래 작업을 예약하고, 시간이 되면 자동으로 실행합니다.
+
+여기에 multi-channel IM routing(WhatsApp / Telegram / Slack / Discord 등 13+ 플랫폼), persistent context memory, Soul personality system을 더하면, Agent는 일회성 도구에서 항상 켜져 있는 personal AI assistant로 변합니다.
+
+**[claw0](https://github.com/shareAI-lab/claw0)** 는 이러한 Harness 메커니즘을 처음부터 분해해 설명하는 companion teaching repo입니다.
+
+```text
+claw agent = agent core + heartbeat + cron + IM chat + memory + soul
+```
+
+```text
+learn-claude-code claw0
+(agent harness core: (proactive always-on harness:
+ loop, tools, planning, heartbeat, cron, IM channels,
+ teams, worktree isolation) memory, soul personality)
+```
+
+## About
+
+
+WeChat으로 스캔하여 팔로우하거나,
+X에서 팔로우하세요: [shareAI-Lab](https://x.com/baicai003)
+
+## 라이선스
+
+MIT
+
+---
+
+**모델이 곧 Agent입니다. 코드는 Harness입니다. 좋은 Harness를 만드십시오. 나머지는 Agent가 해냅니다.**
+
+**Bash is all you need. Real agents are all the universe needs.**
diff --git a/README-zh.md b/README-zh.md
index 843cce1f3..30662d80a 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -1,6 +1,6 @@
# Learn Claude Code -- 真正的 Agent Harness 工程
-[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md)
+[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md) | [한국어](./README-ko.md)
## 模型就是 Agent
@@ -291,7 +291,7 @@ s08 Background Tasks [6] s10 Team Protocols [12]
learn-claude-code/
|
|-- agents/ # Python 参考实现 (s01-s12 + s_full 总纲)
-|-- docs/{en,zh,ja}/ # 心智模型优先的文档 (3 种语言)
+|-- docs/{en,zh,ja,ko}/ # 心智模型优先的文档 (4 种语言)
|-- web/ # 交互式学习平台 (Next.js)
|-- skills/ # s05 的 Skill 文件
+-- .github/workflows/ci.yml # CI: 类型检查 + 构建
@@ -300,7 +300,7 @@ learn-claude-code/
## 文档
心智模型优先: 问题、方案、ASCII 图、最小化代码。
-[English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/)
+[English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/) | [한국어](./docs/ko/)
| 课程 | 主题 | 格言 |
|------|------|------|
diff --git a/README.md b/README.md
index 02561fef1..53a077e09 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-ko.md)
# Learn Claude Code -- Harness Engineering for Real Agents
## The Model IS the Agent
@@ -290,7 +290,7 @@ s08 Background Tasks [6] s10 Team Protocols [12]
learn-claude-code/
|
|-- agents/ # Python reference implementations (s01-s12 + s_full capstone)
-|-- docs/{en,zh,ja}/ # Mental-model-first documentation (3 languages)
+|-- docs/{en,zh,ja,ko}/ # Mental-model-first documentation (4 languages)
|-- web/ # Interactive learning platform (Next.js)
|-- skills/ # Skill files for s05
+-- .github/workflows/ci.yml # CI: typecheck + build
@@ -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/ko/).
| Session | Topic | Motto |
|---------|-------|-------|
diff --git a/docs/ko/s01-the-agent-loop.md b/docs/ko/s01-the-agent-loop.md
new file mode 100644
index 000000000..72c2e8c72
--- /dev/null
+++ b/docs/ko/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`
+
+> *"One loop & Bash is all you need"* -- 도구 하나 + 루프 하나 = 에이전트.
+>
+> **하네스(Harness) 계층**: 루프 -- 모델이 현실 세계와 만나는 첫 번째 접점.
+
+## 문제
+
+언어 모델은 코드에 대해 추론할 수 있지만, 현실 세계에 손을 뻗을 수는 없다. 파일을 읽지도, 테스트를 실행하지도, 에러를 확인하지도 못한다. 루프가 없으면 도구를 호출할 때마다 사용자가 직접 결과를 복사해서 붙여넣어야 한다. 사용자 자신이 루프가 되는 셈이다.
+
+## 해결 방법
+
+```
++--------+ +-------+ +---------+
+| User | ---> | LLM | ---> | Tool |
+| prompt | | | | execute |
++--------+ +---+---+ +----+----+
+ ^ |
+ | tool_result |
+ +----------------+
+ (loop until stop_reason != "tool_use")
+```
+
+하나의 종료 조건이 전체 흐름을 제어한다. 모델이 도구 호출을 멈출 때까지 루프는 계속 돈다.
+
+## 동작 방식
+
+1. 사용자의 프롬프트가 첫 번째 메시지가 된다.
+
+```python
+messages.append({"role": "user", "content": query})
+```
+
+2. 메시지와 도구 정의를 LLM에 전송한다.
+
+```python
+response = client.messages.create(
+ model=MODEL, system=SYSTEM, messages=messages,
+ tools=TOOLS, max_tokens=8000,
+)
+```
+
+3. 어시스턴트 응답을 추가하고 `stop_reason`을 확인한다. 모델이 도구를 호출하지 않았다면 종료.
+
+```python
+messages.append({"role": "assistant", "content": response.content})
+if response.stop_reason != "tool_use":
+ return
+```
+
+4. 각 도구 호출을 실행하고 결과를 수집하여 user 메시지로 추가한다. 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})
+```
+
+이것이 30줄도 안 되는 에이전트의 전부다. 이 과정의 나머지는 모두 이 루프 위에 쌓아 올리는 것이며, 루프 자체는 변하지 않는다.
+
+## 변경 사항
+
+| Component | Before | After |
+|---------------|------------|--------------------------------|
+| Agent loop | (none) | `while True` + stop_reason |
+| Tools | (none) | `bash` (one tool) |
+| Messages | (none) | Accumulating list |
+| Control flow | (none) | `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/ko/s02-tool-use.md b/docs/ko/s02-tool-use.md
new file mode 100644
index 000000000..c9f41516f
--- /dev/null
+++ b/docs/ko/s02-tool-use.md
@@ -0,0 +1,99 @@
+# s02: Tool Use
+
+`s01 > [ s02 ] s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Adding a tool means adding one handler"* -- 루프는 그대로, 새 도구는 디스패치 맵에 등록하기만 하면 된다.
+>
+> **하네스(Harness) 계층**: 도구 디스패치 -- 모델이 닿을 수 있는 범위를 넓힌다.
+
+## 문제
+
+`bash` 하나만으로는 에이전트가 모든 것을 셸에 의존하게 된다. `cat`은 예측 불가능하게 출력을 잘라내고, `sed`는 특수 문자에서 실패하며, 모든 bash 호출은 제약 없는 보안 표면이 된다. `read_file`이나 `write_file` 같은 전용 도구를 쓰면 도구 수준에서 경로 샌드박싱을 강제할 수 있다.
+
+핵심 포인트: 도구를 추가해도 루프를 바꿀 필요가 없다.
+
+## 해결 방법
+
+```
++--------+ +-------+ +------------------+
+| User | ---> | LLM | ---> | Tool Dispatch |
+| prompt | | | | { |
++--------+ +---+---+ | bash: run_bash |
+ ^ | read: run_read |
+ | | write: run_wr |
+ +-----------+ edit: run_edit |
+ tool_result | } |
+ +------------------+
+
+The dispatch map is a dict: {tool_name: handler_function}.
+One lookup replaces any if/elif chain.
+```
+
+## 동작 방식
+
+1. 각 도구에 핸들러 함수를 정의한다. 경로 샌드박싱으로 워크스페이스 밖으로의 탈출을 방지한다.
+
+```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. 디스패치 맵이 도구 이름과 핸들러를 연결한다.
+
+```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. 루프 안에서 이름으로 핸들러를 조회한다. 루프 본체는 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,
+ })
+```
+
+도구 추가 = 핸들러 추가 + 스키마 항목 추가. 루프는 절대 바뀌지 않는다.
+
+## s01에서의 변경 사항
+
+| Component | Before (s01) | After (s02) |
+|----------------|--------------------|----------------------------|
+| Tools | 1 (bash only) | 4 (bash, read, write, edit)|
+| Dispatch | Hardcoded bash call | `TOOL_HANDLERS` dict |
+| Path safety | None | `safe_path()` sandbox |
+| Agent loop | Unchanged | Unchanged |
+
+## 직접 실행해 보기
+
+```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/ko/s03-todo-write.md b/docs/ko/s03-todo-write.md
new file mode 100644
index 000000000..fa61188b0
--- /dev/null
+++ b/docs/ko/s03-todo-write.md
@@ -0,0 +1,96 @@
+# s03: TodoWrite
+
+`s01 > s02 > [ s03 ] s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"An agent without a plan drifts"* -- 먼저 단계를 나열하고, 그다음 실행한다.
+>
+> **하네스(Harness) 계층**: 계획 수립 -- 경로를 정해주지 않으면서도 모델이 궤도를 이탈하지 않게 한다.
+
+## 문제
+
+여러 단계로 이루어진 작업에서 모델은 길을 잃는다. 같은 작업을 반복하거나, 단계를 건너뛰거나, 엉뚱한 곳으로 빠진다. 대화가 길어질수록 더 심해지는데, 도구 결과가 컨텍스트를 채우면서 시스템 프롬프트의 영향력이 희미해지기 때문이다. 10단계짜리 리팩토링에서 1~3단계를 끝낸 뒤, 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. `todo` 도구는 다른 도구와 마찬가지로 디스패치 맵에 추가된다.
+
+```python
+TOOL_HANDLERS = {
+ # ...base tools...
+ "todo": lambda **kw: TODO.update(kw["items"]),
+}
+```
+
+3. nag 리마인더가 모델이 3라운드 이상 `todo`를 호출하지 않을 경우 알림을 주입한다.
+
+```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는 하나만" 제약이 순차적 집중을 강제하고, nag 리마인더가 책임감을 부여한다.
+
+## s02에서의 변경 사항
+
+| Component | Before (s02) | After (s03) |
+|----------------|------------------|----------------------------|
+| Tools | 4 | 5 (+todo) |
+| Planning | None | TodoManager with statuses |
+| Nag injection | None | `` after 3 rounds|
+| Agent loop | Simple dispatch | + rounds_since_todo counter|
+
+## 직접 실행해 보기
+
+```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/ko/s04-subagent.md b/docs/ko/s04-subagent.md
new file mode 100644
index 000000000..bcd45903b
--- /dev/null
+++ b/docs/ko/s04-subagent.md
@@ -0,0 +1,94 @@
+# s04: Subagents
+
+`s01 > s02 > s03 > [ s04 ] s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Break big tasks down; each subtask gets a clean context"* -- 서브에이전트는 독립된 messages[]를 사용하여 메인 대화를 깔끔하게 유지한다.
+>
+> **하네스(Harness) 계층**: 컨텍스트 격리 -- 모델의 사고 명확성을 지킨다.
+
+## 문제
+
+에이전트가 작업을 진행할수록 messages 배열은 계속 커진다. 파일을 읽을 때마다, bash 출력을 받을 때마다 컨텍스트에 영구적으로 남는다. "이 프로젝트는 어떤 테스트 프레임워크를 쓰고 있나요?"라는 질문에 파일 5개를 읽어야 할 수도 있지만, 부모 에이전트에게 필요한 건 "pytest"라는 답변뿐이다.
+
+## 해결 방법
+
+```
+Parent agent Subagent
++------------------+ +------------------+
+| messages=[...] | | messages=[] | <-- fresh
+| | dispatch | |
+| tool: task | ----------> | while tool_use: |
+| prompt="..." | | call tools |
+| | summary | append results |
+| result = "..." | <---------- | return last text |
++------------------+ +------------------+
+
+Parent context stays clean. Subagent context is discarded.
+```
+
+## 동작 방식
+
+1. 부모에게 `task` 도구를 추가한다. 자식은 `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. 서브에이전트는 `messages=[]`로 시작하여 자체 루프를 실행한다. 최종 텍스트만 부모에게 반환된다.
+
+```python
+def run_subagent(prompt: str) -> str:
+ sub_messages = [{"role": "user", "content": prompt}]
+ for _ in range(30): # 안전 제한
+ 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)"
+```
+
+자식의 전체 메시지 히스토리(30회 이상의 도구 호출 포함)는 폐기된다. 부모는 한 단락 분량의 요약을 일반 `tool_result`로 받는다.
+
+## s03에서의 변경 사항
+
+| Component | Before (s03) | After (s04) |
+|----------------|------------------|---------------------------|
+| Tools | 5 | 5 (base) + task (parent) |
+| Context | Single shared | Parent + child isolation |
+| Subagent | None | `run_subagent()` function |
+| Return value | N/A | Summary text only |
+
+## 직접 실행해 보기
+
+```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/ko/s05-skill-loading.md b/docs/ko/s05-skill-loading.md
new file mode 100644
index 000000000..a6cef8d55
--- /dev/null
+++ b/docs/ko/s05-skill-loading.md
@@ -0,0 +1,108 @@
+# s05: Skills
+
+`s01 > s02 > s03 > s04 > [ s05 ] s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Load knowledge when you need it, not upfront"* -- 시스템 프롬프트가 아닌 tool_result로 주입한다.
+>
+> **하네스(Harness) 계층**: 온디맨드 지식 -- 모델이 요청할 때만 제공하는 도메인 전문성.
+
+## 문제
+
+에이전트가 도메인별 워크플로를 따르게 하고 싶다: Git 규칙, 테스트 패턴, 코드 리뷰 체크리스트. 이 모든 것을 시스템 프롬프트에 넣으면 사용하지 않는 스킬에 토큰을 낭비한다. 10개 스킬 x 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: ... |
+| |
++--------------------------------------+
+```
+
+1계층: 스킬 *이름*을 시스템 프롬프트에 배치(저비용). 2계층: 스킬 *본문*을 tool_result로 전달(온디맨드).
+
+## 동작 방식
+
+1. 각 스킬은 YAML 프론트매터가 포함된 `SKILL.md` 파일을 가진 디렉터리로 구성된다.
+
+```
+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` 파일을 재귀적으로 탐색하고, 디렉터리 이름을 스킬 식별자로 사용한다.
+
+```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. 1계층은 시스템 프롬프트에 배치하고, 2계층은 일반적인 도구 핸들러로 처리한다.
+
+```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"]),
+}
+```
+
+모델은 어떤 스킬이 존재하는지 파악하고(저비용), 필요할 때만 불러온다(고비용).
+
+## 변경 사항
+
+| 구성 요소 | Before (s04) | After (s05) |
+|----------------|------------------|----------------------------|
+| Tools | 5 (base + task) | 5 (base + load_skill) |
+| System prompt | Static string | + skill descriptions |
+| Knowledge | None | skills/\*/SKILL.md files |
+| Injection | None | Two-layer (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/ko/s06-context-compact.md b/docs/ko/s06-context-compact.md
new file mode 100644
index 000000000..13e1a36e6
--- /dev/null
+++ b/docs/ko/s06-context-compact.md
@@ -0,0 +1,124 @@
+# s06: Context Compact
+
+`s01 > s02 > s03 > s04 > s05 > [ s06 ] | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Context will fill up; you need a way to make room"* -- 3계층 압축 전략으로 무한 세션을 구현한다.
+>
+> **하네스(Harness) 계층**: 압축 -- 깨끗한 메모리로 무한 세션을 유지한다.
+
+## 문제
+
+컨텍스트 윈도우는 유한하다. 1000줄짜리 파일에 `read_file` 한 번이면 약 4000 토큰을 소비한다. 파일 30개를 읽고 bash 명령 20번을 실행하면 100,000 토큰을 넘긴다. 압축 없이는 에이전트가 대규모 코드베이스에서 작업할 수 없다.
+
+## 해결 방법
+
+적극성을 단계적으로 높이는 3계층 구조:
+
+```
+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. **1계층 -- micro_compact**: 매 LLM 호출 전에 오래된 도구 결과를 플레이스홀더로 교체한다.
+
+```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. **2계층 -- auto_compact**: 토큰이 임계값을 초과하면 전체 트랜스크립트를 디스크에 저장한 뒤 LLM에 요약을 요청한다.
+
+```python
+def auto_compact(messages: list) -> list:
+ # 복구를 위해 트랜스크립트 저장
+ 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이 요약
+ 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. **3계층 -- 수동 compact**: `compact` 도구가 동일한 요약 처리를 온디맨드로 실행한다.
+
+4. 에이전트 루프가 세 계층을 모두 통합한다:
+
+```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(...)
+ # ... 도구 실행 ...
+ if manual_compact:
+ messages[:] = auto_compact(messages) # Layer 3
+```
+
+트랜스크립트가 디스크에 전체 이력을 보존한다. 진정으로 사라지는 것은 없다 -- 활성 컨텍스트 밖으로 옮겨질 뿐이다.
+
+## 변경 사항
+
+| 구성 요소 | Before (s05) | After (s06) |
+|----------------|------------------|----------------------------|
+| Tools | 5 | 5 (base + compact) |
+| Context mgmt | None | Three-layer compression |
+| Micro-compact | None | Old results -> placeholders|
+| Auto-compact | None | Token threshold trigger |
+| Transcripts | None | Saved to .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/ko/s07-task-system.md b/docs/ko/s07-task-system.md
new file mode 100644
index 000000000..722eca9d0
--- /dev/null
+++ b/docs/ko/s07-task-system.md
@@ -0,0 +1,131 @@
+# s07: Task System
+
+`s01 > s02 > s03 > s04 > s05 > s06 | [ s07 ] s08 > s09 > s10 > s11 > s12`
+
+> *"Break big goals into small tasks, order them, persist to disk"* -- 의존 관계가 있는 파일 기반 태스크 그래프로, 멀티 에이전트 협업의 토대를 마련한다.
+>
+> **하네스(Harness) 계층**: 영속 태스크 -- 단일 대화의 수명을 넘어 유지되는 목표.
+
+## 문제
+
+s03의 TodoManager는 메모리 위의 단순한 체크리스트에 불과하다: 순서도 없고, 의존 관계도 없고, 상태는 완료 아니면 미완료뿐이다. 실제 목표에는 구조가 있다 -- 태스크 B는 태스크 A에 의존하고, 태스크 C와 D는 병렬 실행이 가능하며, 태스크 E는 C와 D 모두가 끝나기를 기다린다.
+
+명시적인 관계 없이는 에이전트가 무엇이 실행 가능하고, 무엇이 블로킹되어 있고, 무엇을 동시에 돌릴 수 있는지 판단할 수 없다. 게다가 리스트가 메모리에만 존재하므로 컨텍스트 압축(s06)이 일어나면 통째로 사라진다.
+
+## 해결 방법
+
+단순한 체크리스트를 디스크에 영속화되는 **태스크 그래프**로 승격시킨다. 각 태스크는 상태와 의존 관계(`blockedBy`)를 담은 하나의 JSON 파일이다. 태스크 그래프는 항상 세 가지 질문에 답한다:
+
+- **실행 가능한 것은?** -- `pending` 상태이면서 `blockedBy`가 비어 있는 태스크.
+- **블로킹된 것은?** -- 미완료 의존을 기다리는 태스크.
+- **완료된 것은?** -- `completed` 태스크. 완료 시 후속 태스크를 자동으로 언블로킹한다.
+
+```
+.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"}
+
+태스크 그래프 (DAG):
+ +----------+
+ +--> | task 2 | --+
+ | | pending | |
++----------+ +----------+ +--> +----------+
+| task 1 | | task 4 |
+| completed| --> +----------+ +--> | blocked |
++----------+ | task 3 | --+ +----------+
+ | pending |
+ +----------+
+
+순서: task 1이 2와 3보다 먼저 완료되어야 한다
+병렬: task 2와 3은 동시에 실행할 수 있다
+의존: task 4는 2와 3 모두를 기다린다
+상태: pending -> in_progress -> completed
+```
+
+이 태스크 그래프는 s07 이후 모든 메커니즘의 협업 백본이 된다: 백그라운드 실행(s08), 멀티 에이전트 팀(s09+), worktree 격리(s12) 모두 이 동일한 구조를 읽고 쓴다.
+
+## 동작 방식
+
+1. **TaskManager**: 태스크당 하나의 JSON 파일, 의존 그래프를 포함한 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. **의존 해제**: 태스크가 완료되면 다른 모든 태스크의 `blockedBy` 리스트에서 해당 ID를 제거하여 후속 태스크를 자동으로 언블로킹한다.
+
+```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. 네 개의 태스크 도구를 디스패치 맵에 등록한다.
+
+```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부터 태스크 그래프가 멀티스텝 작업의 기본이 된다. s03의 Todo는 가벼운 단일 세션용 체크리스트로 남는다.
+
+## 변경 사항
+
+| 구성 요소 | Before (s06) | After (s07) |
+|---|---|---|
+| Tools | 5 | 8 (`task_create/update/list/get`) |
+| 계획 모델 | 플랫 체크리스트 (메모리) | 의존 관계 태스크 그래프 (디스크) |
+| 관계 | 없음 | `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/ko/s08-background-tasks.md b/docs/ko/s08-background-tasks.md
new file mode 100644
index 000000000..4931d5799
--- /dev/null
+++ b/docs/ko/s08-background-tasks.md
@@ -0,0 +1,107 @@
+# s08: Background Tasks
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > [ s08 ] s09 > s10 > s11 > s12`
+
+> *"Run slow operations in the background; the agent keeps thinking"* -- 데몬 스레드가 명령을 실행하고, 완료 시 알림을 주입한다.
+>
+> **하네스(Harness) 계층**: 백그라운드 실행 -- 모델이 사고를 이어가는 동안 하네스(Harness)가 대기한다.
+
+## 문제
+
+일부 명령은 수 분이 걸린다: `npm install`, `pytest`, `docker build`. 블로킹 루프에서는 모델이 서브프로세스 완료를 기다리며 가만히 멈춰 있다. 사용자가 "의존성을 설치하고, 그동안 설정 파일을 만들어줘"라고 해도, 에이전트는 병렬이 아닌 순차적으로 처리한다.
+
+## 해결 방법
+
+```
+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가 스레드 안전한 알림 큐로 태스크를 추적한다.
+
+```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. 에이전트 루프가 매 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(...)
+```
+
+루프는 싱글 스레드를 유지한다. 서브프로세스 I/O만 병렬화된다.
+
+## 변경 사항
+
+| 구성 요소 | Before (s07) | After (s08) |
+|----------------|------------------|----------------------------|
+| Tools | 8 | 6 (base + background_run + check)|
+| Execution | Blocking only | Blocking + background threads|
+| Notification | None | Queue drained per loop |
+| Concurrency | None | Daemon threads |
+
+## 직접 실행해 보기
+
+```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/ko/s09-agent-teams.md b/docs/ko/s09-agent-teams.md
new file mode 100644
index 000000000..9da4ee0d3
--- /dev/null
+++ b/docs/ko/s09-agent-teams.md
@@ -0,0 +1,125 @@
+# s09: Agent Teams
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > [ s09 ] s10 > s11 > s12`
+
+> *"혼자 감당하기엔 너무 크면, 팀원에게 위임하라"* -- 영속적인 팀원 + 비동기 메일박스.
+>
+> **하네스(Harness) 레이어**: 팀 메일박스 -- 여러 모델을 파일로 조율한다.
+
+## 문제
+
+서브에이전트(s04)는 일회용이다. 생성하고, 작업하고, 요약을 돌려주고, 사라진다. 정체성도 없고, 호출 사이의 기억도 없다. 백그라운드 태스크(s08)는 셸 명령을 실행하지만, LLM 기반의 판단은 내릴 수 없다.
+
+진정한 팀워크에는 세 가지가 필요하다: (1) 단일 프롬프트를 넘어 지속되는 영속 에이전트, (2) 정체성과 생명주기 관리, (3) 에이전트 간 통신 채널.
+
+## 해결 방법
+
+```
+Teammate lifecycle:
+ spawn -> WORKING -> IDLE -> WORKING -> ... -> SHUTDOWN
+
+Communication:
+ .team/
+ config.json <- team roster + statuses
+ inbox/
+ alice.jsonl <- append-only, drain-on-read
+ 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()`은 팀원을 생성하고, 에이전트 루프를 스레드로 시작한다.
+
+```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: append-only JSONL 수신함. `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. 각 팀원은 LLM 호출 전에 수신함을 확인하고, 받은 메시지를 컨텍스트에 주입한다.
+
+```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
+ # 도구 실행, 결과 추가...
+ self._find_member(name)["status"] = "idle"
+```
+
+## s08 대비 변경 사항
+
+| 구성 요소 | 이전 (s08) | 이후 (s09) |
+|----------------|------------------|------------------------------|
+| 도구 | 6개 | 9개 (+spawn/send/read_inbox) |
+| 에이전트 | 단일 | 리드 + N명의 팀원 |
+| 영속성 | 없음 | config.json + JSONL 수신함 |
+| 스레드 | 백그라운드 명령 | 스레드별 완전한 에이전트 루프 |
+| 생명주기 | 실행 후 잊기 | idle -> working -> idle |
+| 통신 | 없음 | 메시지 + 브로드캐스트 |
+
+## 직접 해보기
+
+```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`을 입력하면 리드의 수신함을 직접 확인할 수 있다
diff --git a/docs/ko/s10-team-protocols.md b/docs/ko/s10-team-protocols.md
new file mode 100644
index 000000000..4f462ba1a
--- /dev/null
+++ b/docs/ko/s10-team-protocols.md
@@ -0,0 +1,106 @@
+# s10: Team Protocols
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > [ s10 ] s11 > s12`
+
+> *"팀원에게는 공유된 소통 규칙이 필요하다"* -- 하나의 요청-응답 패턴이 모든 협상을 이끈다.
+>
+> **하네스(Harness) 레이어**: 프로토콜 -- 모델 간 구조화된 핸드셰이크.
+
+## 문제
+
+s09에서 팀원들은 작업하고 소통하지만, 구조화된 조율은 빠져 있다.
+
+**종료**: 스레드를 강제로 죽이면 파일이 반쯤 쓰인 채로 남고 config.json이 오래된 상태가 된다. 핸드셰이크가 필요하다. 리드가 요청하고, 팀원이 승인(마무리 후 종료)하거나 거부(계속 작업)한다.
+
+**계획 승인**: 리드가 "인증 모듈을 리팩터링해"라고 말하면 팀원이 즉시 시작한다. 고위험 변경의 경우, 리드가 먼저 계획을 검토해야 한다.
+
+두 경우 모두 구조는 같다. 한쪽이 고유 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} |
+
+Shared FSM:
+ [pending] --approve--> [approved]
+ [pending] --reject---> [rejected]
+
+Trackers:
+ shutdown_requests = {req_id: {target, status}}
+ plan_requests = {req_id: {from, plan, status}}
+```
+
+## 작동 원리
+
+1. 리드가 request_id를 생성하고 수신함을 통해 종료를 요청한다.
+
+```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. 팀원이 요청을 받고 승인 또는 거부로 응답한다.
+
+```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` 상태 머신이 어떤 요청-응답 프로토콜이든 처리한다.
+
+## s09 대비 변경 사항
+
+| 구성 요소 | 이전 (s09) | 이후 (s10) |
+|----------------|------------------|-------------------------------------|
+| 도구 | 9개 | 12개 (+shutdown_req/resp +plan) |
+| 종료 | 자연 종료만 | 요청-응답 핸드셰이크 |
+| 계획 게이팅 | 없음 | 제출/검토 및 승인 |
+| 상관 관계 | 없음 | 요청별 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/ko/s11-autonomous-agents.md b/docs/ko/s11-autonomous-agents.md
new file mode 100644
index 000000000..b4bbc0519
--- /dev/null
+++ b/docs/ko/s11-autonomous-agents.md
@@ -0,0 +1,142 @@
+# s11: Autonomous Agents
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > [ s11 ] s12`
+
+> *"팀원이 보드를 스캔해서 직접 태스크를 가져간다"* -- 리드가 일일이 지시할 필요가 없다.
+>
+> **하네스(Harness) 레이어**: 자율성 -- 지시 없이 스스로 일을 찾는 모델.
+
+## 문제
+
+s09-s10에서 팀원들은 명시적으로 지시받아야만 일한다. 리드가 각 팀원을 특정 프롬프트로 생성해야 한다. 보드에 미할당 태스크가 10개? 리드가 하나씩 배정한다. 확장이 안 된다.
+
+진정한 자율성: 팀원이 태스크 보드를 직접 스캔하고, 미할당 태스크를 선점하고, 작업을 수행한 뒤, 다음 일을 찾는다.
+
+한 가지 주의점: 컨텍스트 압축(s06) 이후 에이전트가 자신이 누구인지 잊을 수 있다. 정체성 재주입으로 해결한다.
+
+## 해결 방법
+
+```
+Teammate lifecycle with idle cycle:
+
++-------+
+| spawn |
++---+---+
+ |
+ v
++-------+ tool_use +-------+
+| WORK | <------------- | LLM |
++---+---+ +-------+
+ |
+ | stop_reason != tool_use (or idle tool called)
+ v
++--------+
+| IDLE | poll every 5s for up to 60s
++---+----+
+ |
+ +---> check inbox --> message? ----------> WORK
+ |
+ +---> scan .tasks/ --> unclaimed? -------> claim -> WORK
+ |
+ +---> 60s timeout ----------------------> SHUTDOWN
+
+Identity re-injection after compression:
+ if len(messages) <= 3:
+ messages.insert(0, identity_block)
+```
+
+## 작동 원리
+
+1. 팀원 루프는 WORK와 IDLE 두 단계로 구성된다. LLM이 도구 호출을 중단하거나 `idle`을 호출하면, 팀원은 IDLE 상태에 진입한다.
+
+```python
+def _loop(self, name, role, prompt):
+ while True:
+ # -- WORK PHASE --
+ messages = [{"role": "user", "content": prompt}]
+ for _ in range(50):
+ response = client.messages.create(...)
+ if response.stop_reason != "tool_use":
+ break
+ # execute tools...
+ if idle_requested:
+ break
+
+ # -- IDLE PHASE --
+ 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 단계에서는 수신함과 태스크 보드를 반복적으로 폴링한다.
+
+```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. 태스크 보드 스캔: 대기 중이고, 소유자가 없고, 차단되지 않은 태스크를 찾는다.
+
+```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. 정체성 재주입: 컨텍스트가 너무 짧으면(압축이 발생한 경우), 정체성 블록을 삽입한다.
+
+```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) |
+|----------------|------------------|----------------------------------|
+| 도구 | 12개 | 14개 (+idle, +claim_task) |
+| 자율성 | 리드 지시형 | 자기 조직화 |
+| IDLE 단계 | 없음 | 수신함 + 태스크 보드 폴링 |
+| 태스크 선점 | 수동만 가능 | 미할당 태스크 자동 선점 |
+| 정체성 | 시스템 프롬프트 | + 압축 후 재주입 |
+| 타임아웃 | 없음 | 60초 유휴 시 자동 종료 |
+
+## 직접 해보기
+
+```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`을 입력하면 누가 작업 중이고 누가 유휴 상태인지 확인할 수 있다
diff --git a/docs/ko/s12-worktree-task-isolation.md b/docs/ko/s12-worktree-task-isolation.md
new file mode 100644
index 000000000..9ad8efb3b
--- /dev/null
+++ b/docs/ko/s12-worktree-task-isolation.md
@@ -0,0 +1,121 @@
+# s12: Worktree + Task Isolation
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > [ s12 ]`
+
+> *"각자 자기 디렉토리에서 작업하고, 서로 간섭하지 않는다"* -- 태스크는 목표를 관리하고, 워크트리는 디렉토리를 관리하며, 태스크 ID로 연결한다.
+>
+> **하네스(Harness) 레이어**: 디렉토리 격리 -- 절대 충돌하지 않는 병렬 실행 레인.
+
+## 문제
+
+s11까지 에이전트는 태스크를 자율적으로 선점하고 완료할 수 있게 되었다. 하지만 모든 태스크가 하나의 공유 디렉토리에서 실행된다. 두 에이전트가 서로 다른 모듈을 동시에 리팩터링하면 충돌이 발생한다. 에이전트 A가 `config.py`를 수정하고, 에이전트 B도 `config.py`를 수정하면, 스테이징되지 않은 변경 사항이 뒤섞이고 어느 쪽도 깔끔하게 롤백할 수 없다.
+
+태스크 보드는 *무엇을 할지*를 추적하지만, *어디에서 할지*에는 관여하지 않는다. 해결책: 각 태스크에 고유한 Git 워크트리 디렉토리를 부여한다. 태스크가 목표를 관리하고, 워크트리가 실행 컨텍스트를 관리한다. 태스크 ID로 둘을 연결한다.
+
+## 해결 방법
+
+```
+Control plane (.tasks/) Execution plane (.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 registry)
+ events.jsonl (lifecycle log)
+
+State machines:
+ Task: pending -> in_progress -> completed
+ Worktree: absent -> active -> removed | kept
+```
+
+## 작동 원리
+
+1. **태스크를 생성한다.** 먼저 목표를 영속화한다.
+
+```python
+TASKS.create("Implement auth refactor")
+# -> .tasks/task_1.json status=pending worktree=""
+```
+
+2. **워크트리를 생성하고 태스크에 바인딩한다.** `task_id`를 전달하면 태스크가 자동으로 `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. **워크트리 안에서 명령을 실행한다.** `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)` -- 디렉토리를 제거하고, 바인딩된 태스크를 완료하고, 이벤트를 발행한다. 한 번의 호출로 정리와 완료를 모두 처리한다.
+
+```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. **이벤트 스트림.** 모든 생명주기 단계가 `.worktrees/events.jsonl`에 기록된다:
+
+```json
+{
+ "event": "worktree.remove.after",
+ "task": {"id": 1, "status": "completed"},
+ "worktree": {"name": "auth-refactor", "status": "removed"},
+ "ts": 1730000000
+}
+```
+
+발행되는 이벤트: `worktree.create.before/after/failed`, `worktree.remove.before/after/failed`, `worktree.keep`, `task.completed`.
+
+장애 발생 후에는 디스크의 `.tasks/` + `.worktrees/index.json`으로부터 상태를 재구성한다. 대화 메모리는 휘발성이지만, 파일 상태는 영속적이다.
+
+## s11 대비 변경 사항
+
+| 구성 요소 | 이전 (s11) | 이후 (s12) |
+|----------------------|----------------------------|-----------------------------------------------|
+| 조율 | 태스크 보드 (소유자/상태) | 태스크 보드 + 명시적 워크트리 바인딩 |
+| 실행 범위 | 공유 디렉토리 | 태스크별 격리된 디렉토리 |
+| 복구 가능성 | 태스크 상태만 | 태스크 상태 + 워크트리 인덱스 |
+| 정리 | 태스크 완료 | 태스크 완료 + 명시적 keep/remove |
+| 생명주기 가시성 | 로그에 암묵적으로 포함 | `.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.`