diff --git a/README-ja.md b/README-ja.md
index 919d2f4be..2c50c7048 100644
--- a/README-ja.md
+++ b/README-ja.md
@@ -1,6 +1,6 @@
# Learn Claude Code -- 0 から 1 へ構築する nano Claude Code-like agent
-[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md)
+[English](./README.md) | [简体中文](./README-zh.md) | [日本語](./README-ja.md) | [繁體中文](./README-zhtw.md)
```
THE AGENT PATTERN
diff --git a/README-zh.md b/README-zh.md
index 3cd2cfc68..d5b0ff402 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -1,6 +1,6 @@
# Learn Claude Code -- 从 0 到 1 构建 nano Claude Code-like agent
-[English](./README.md) | [中文](./README-zh.md) | [日本語](./README-ja.md)
+[English](./README.md) | [简体中文](./README-zh.md) | [日本語](./README-ja.md) | [繁體中文](./README-zhtw.md)
```
THE AGENT PATTERN
diff --git a/README-zhtw.md b/README-zhtw.md
new file mode 100644
index 000000000..36c5e4bab
--- /dev/null
+++ b/README-zhtw.md
@@ -0,0 +1,237 @@
+# Learn Claude Code -- 從 0 到 1 打造 nano Claude Code-like agent
+
+[English](./README.md) | [简体中文](./README-zh.md) | [日本語](./README-ja.md) | [繁體中文](./README-zhtw.md)
+
+```
+ THE AGENT PATTERN
+ =================
+
+ User --> messages[] --> LLM --> response
+ |
+ stop_reason == "tool_use"?
+ / \
+ yes no
+ | |
+ execute tools return text
+ append results
+ loop back -----------------> messages[]
+
+
+ 這就是最小迴圈。每個 AI coding agent 都離不開它。
+ Production agents 還會疊加 policy、permissions 與 lifecycle layers。
+```
+
+**12 個循序漸進的章節,從簡單迴圈一路到隔離式自主執行。**
+**每個章節只新增一個機制。每個機制都有一句格言。**
+
+> **s01** *"One loop & Bash is all you need"* — 一個工具 + 一個迴圈 = 一個 agent
+>
+> **s02** *"Adding a tool means adding one handler"* — 主迴圈不變;新工具只要註冊進 dispatch map
+>
+> **s03** *"An agent without a plan drifts"* — 先列步驟,再執行;完成率翻倍
+>
+> **s04** *"Break big tasks down; each subtask gets a clean context"* — subagents 使用獨立 messages[],讓主對話保持乾淨
+>
+> **s05** *"Load knowledge when you need it, not upfront"* — 透過 tool_result 注入,而不是放進 system prompt
+>
+> **s06** *"Context will fill up; you need a way to make room"* — 三層壓縮策略,換來幾乎無限的 sessions
+>
+> **s07** *"Break big goals into small tasks, order them, persist to disk"* — 以檔案為基礎、含 dependencies 的 task graph,為 multi-agent 協作打下基礎
+>
+> **s08** *"Run slow operations in the background; the agent keeps thinking"* — 透過背景執行緒執行任務,完成後再發送通知
+
+> **s09** *"When the task is too big for one, delegate to teammates"* — 永遠存在的隊友 + 非同步信件
+>
+> **s10** *"Teammates need shared communication rules"* — 一套 request-response pattern 驅動所有溝通
+>
+> **s11** *"Teammates scan the board and claim tasks themselves"* — 不需要逐一指派,而是主動認領工作去執行
+>
+> **s12** *"Each works in its own directory, no interference"* — tasks 管理 goals,worktrees 管理 directories,以 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})
+```
+
+每個章節都在這個迴圈上疊加一個機制 -- 但迴圈本身始終不變。
+
+## 範圍(重要)
+
+此 repository 是一個 0->1 學習型專案,用來建構 nano Claude Code-like agent。
+為了讓學習路徑更清晰,這個 repository 刻意簡化或省略了部分 production 機制:
+
+- 完整的 event/hook buses(例如 PreToolUse、SessionStart/End、ConfigChange)。
+ s12 僅提供教學用途的最小 append-only lifecycle event stream。
+- 以規則為基礎的 permission governance 與 trust workflows
+- Session lifecycle controls(resume/fork)與更完整的 worktree lifecycle controls
+- 完整 MCP runtime 細節(transport/OAuth/resource subscribe/polling)
+
+此 repository 中的 team JSONL mailbox protocol 僅為教學實作,不代表任何特定 production internals。
+
+## 快速開始
+
+```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 平台
+
+互動式視覺化、逐步圖解、原始碼檢視器,以及對應文件。
+
+```sh
+cd web && npm install && npm run dev # http://localhost:3000
+```
+
+## 學習路徑
+
+```
+第一階段:THE LOOP 第二階段: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
+
+第三階段:PERSISTENCE 第四階段: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 參考實作 (s01-s12 + s_full capstone)
+|-- docs/{en,zh,ja}/ # Mental-model-first 文件 (3 種語言)
+|-- web/ # 互動式學習平台 (Next.js)
+|-- skills/ # s05 的 Skill 檔案
++-- .github/workflows/ci.yml # CI: 檢查型別 + 建制專案
+```
+
+## 文件
+
+Mental-model-first:問題、解法、ASCII 圖、最小化程式碼。
+提供 [English](./docs/en/) | [中文](./docs/zh/) | [日本語](./docs/ja/)。
+
+| Session | Topic | Motto |
+|---------|-------|-------|
+| [s01](./docs/en/s01-the-agent-loop.md) | The Agent Loop | *One loop & Bash is all you need* |
+| [s02](./docs/en/s02-tool-use.md) | Tool Use | *Adding a tool means adding one handler* |
+| [s03](./docs/en/s03-todo-write.md) | TodoWrite | *An agent without a plan drifts* |
+| [s04](./docs/en/s04-subagent.md) | Subagents | *Break big tasks down; each subtask gets a clean context* |
+| [s05](./docs/en/s05-skill-loading.md) | Skills | *Load knowledge when you need it, not upfront* |
+| [s06](./docs/en/s06-context-compact.md) | Context Compact | *Context will fill up; you need a way to make room* |
+| [s07](./docs/en/s07-task-system.md) | Tasks | *Break big goals into small tasks, order them, persist to disk* |
+| [s08](./docs/en/s08-background-tasks.md) | Background Tasks | *Run slow operations in the background; the agent keeps thinking* |
+| [s09](./docs/en/s09-agent-teams.md) | Agent Teams | *When the task is too big for one, delegate to teammates* |
+| [s10](./docs/en/s10-team-protocols.md) | Team Protocols | *Teammates need shared communication rules* |
+| [s11](./docs/en/s11-autonomous-agents.md) | Autonomous Agents | *Teammates scan the board and claim tasks themselves* |
+| [s12](./docs/en/s12-worktree-task-isolation.md) | Worktree + Task Isolation | *Each works in its own directory, no interference* |
+
+## 接下來 -- 從理解到落地
+
+完成 12 個章節後,你已經由內到外掌握 agent 的運作原理。把這些知識化為產品有兩種方式:
+
+### Kode Agent CLI -- Open-Source Coding Agent CLI
+
+> `npm i -g @shareai-lab/kode`
+
+支援 Skill 與 LSP,適用於 Windows,並可串接 GLM / MiniMax / DeepSeek 等開放模型。安裝後即可上手。
+
+GitHub: **[shareAI-lab/Kode-cli](https://github.com/shareAI-lab/Kode-cli)**
+
+### Kode Agent SDK -- 將 Agent 能力嵌入你的 App
+
+官方 Claude Code Agent SDK 底層會與完整 CLI process 通訊 -- 每個並發使用者都會對應一個獨立 terminal process。Kode SDK 是獨立 library,沒有 per-user process 負擔,可嵌入 backends、browser extensions、embedded devices,或任何 runtime。
+
+GitHub: **[shareAI-lab/Kode-agent-sdk](https://github.com/shareAI-lab/Kode-agent-sdk)**
+
+---
+
+## 姊妹 Repo:從 *on-demand sessions* 到 *always-on assistant*
+
+本 repository 教的 agent 屬於 **use-and-discard** 模式 -- 開 terminal、交付任務、完成後關閉;下次重開就是全新 session。這就是 Claude Code 的模式。
+
+[OpenClaw](https://github.com/openclaw/openclaw) 證明了另一種可能:在同樣的 agent core 上再加兩個機制,就能讓 agent 從「推一下才動」變成「每 30 秒自動醒來找事做」:
+
+- **Heartbeat** -- 系統每 30 秒會送一則訊息給 agent,讓它檢查是否有事可做。沒事就繼續休眠;有事就立刻處理。
+- **Cron** -- agent 可以替自己安排未來任務,到點自動執行。
+
+再加上多通道 IM routing(WhatsApp / Telegram / Slack / Discord,13+ 平台)、持久化 context memory,以及 Soul personality system,agent 就會從一次性工具進化為 always-on 的個人 AI 助手。
+
+**[claw0](https://github.com/shareAI-lab/claw0)** 是我們的姊妹教學 repository,從零拆解這些機制:
+
+```
+claw agent = agent core + heartbeat + cron + IM chat + memory + soul
+```
+
+```
+learn-claude-code claw0
+(agent runtime core: (proactive always-on assistant:
+ loop, tools, planning, heartbeat, cron, IM channels,
+ teams, worktree isolation) memory, soul personality)
+```
+
+## About
+
+
+使用 WeChat 掃描即可追蹤我們,
+或在 X 追蹤:[shareAI-Lab](https://x.com/baicai003)
+
+## 授權
+
+MIT
+
+---
+**模型就是 agent。我們的工作,是給它工具,然後讓開。**
\ No newline at end of file
diff --git a/README.md b/README.md
index 9018362c4..0c50056e3 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-zhtw.md)
# Learn Claude Code -- A nano Claude Code-like agent, built from 0 to 1
```
@@ -161,7 +161,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/zhtw/)
| Session | Topic | Motto |
|---------|-------|-------|
diff --git a/docs/zhtw/s01-the-agent-loop.md b/docs/zhtw/s01-the-agent-loop.md
new file mode 100644
index 000000000..52c575ad5
--- /dev/null
+++ b/docs/zhtw/s01-the-agent-loop.md
@@ -0,0 +1,114 @@
+# s01: Agent 迴圈
+
+`[ s01 ] s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"One loop & Bash is all you need"* -- 一個工具 + 一個迴圈 = 一個 agent。
+
+## 問題
+
+語言模型可以推理程式碼,但它無法直接*碰觸*真實世界 -- 不能讀檔、跑測試、檢查錯誤。沒有迴圈時,每次工具呼叫都得手動複製貼上結果回去。你就成了那個迴圈本身。
+
+## 解法
+
+```
++--------+ +-------+ +---------+
+| User | ---> | LLM | ---> | Tool |
+| prompt | | | | execute |
++--------+ +---+---+ +----+----+
+ ^ |
+ | tool_result |
+ +----------------+
+ (loop until stop_reason != "tool_use")
+```
+
+整個流程只靠一個退出條件控制。只要模型還在呼叫工具,迴圈就持續執行。
+
+## 運作方式
+
+1. 把使用者輸入當成第一則訊息。
+
+```python
+messages.append({"role": "user", "content": query})
+```
+
+2. 把 messages 與 tool definitions 一起送進 LLM。
+
+```python
+response = client.messages.create(
+ model=MODEL, system=SYSTEM, messages=messages,
+ tools=TOOLS, max_tokens=8000,
+)
+```
+
+3. 先附加 assistant 回覆。接著檢查 `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 行,就有完整 agent。後續課程都只是疊加在這個基礎上 -- 不會改動這個迴圈。
+
+## 相較前一版的變更
+
+| Component | Before | After |
+|---------------|------------|--------------------------------|
+| Agent loop | (none) | `while True` + stop_reason |
+| Tools | (none) | `bash` (one tool) |
+| Messages | (none) | 累積訊息佇列 |
+| 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/zhtw/s02-tool-use.md b/docs/zhtw/s02-tool-use.md
new file mode 100644
index 000000000..a98fc310a
--- /dev/null
+++ b/docs/zhtw/s02-tool-use.md
@@ -0,0 +1,97 @@
+# s02: Tool Use
+
+`s01 > [ s02 ] s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Adding a tool means adding one handler"* -- 主迴圈保持不變;新工具只要註冊進 dispatch map。
+
+## 問題
+
+只有 `bash` 時,agent 幾乎所有事都得 shell out。`cat` 可能會不穩定截斷、`sed` 在特殊字元上容易失敗,而且每一次 bash 呼叫都是未受約束的安全面。像 `read_file`、`write_file` 這類專用工具,可以在 tool 層就強制做 path sandboxing。
+
+關鍵洞察:新增工具,不需要改迴圈。
+
+## 解法
+
+```
++--------+ +-------+ +------------------+
+| 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. 每個工具對應一個 handler。path sandboxing 可防止跳出工作目錄。
+
+```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 將 tool name 對應到 handler。
+
+```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. 在迴圈中依 name 查表拿 handler。迴圈本體與 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,
+ })
+```
+
+新增工具 = 新增 handler + 新增 schema entry。迴圈不需要改。
+
+## 相較 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/zhtw/s03-todo-write.md b/docs/zhtw/s03-todo-write.md
new file mode 100644
index 000000000..23bf8d3af
--- /dev/null
+++ b/docs/zhtw/s03-todo-write.md
@@ -0,0 +1,94 @@
+# s03: TodoWrite
+
+`s01 > s02 > [ s03 ] s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"An agent without a plan drifts"* -- 先列步驟,再執行。
+
+## 問題
+
+多步驟任務時,模型容易失焦:重複做事、跳過步驟、或越走越偏。對話一長會更嚴重 -- tool results 一直塞進 context,system prompt 的約束會慢慢被稀釋。像 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 會保存 task 與狀態;同一時間只允許一個 `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` 工具就和其他工具一樣,放進 dispatch map。
+
+```python
+TOOL_HANDLERS = {
+ # ...base tools...
+ "todo": lambda **kw: TODO.update(kw["items"]),
+}
+```
+
+3. 若模型連續 3 輪以上沒呼叫 `todo`,就注入 nag reminder。
+
+```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 reminder 則提供持續的行為約束。
+
+## 相較 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/zhtw/s04-subagent.md b/docs/zhtw/s04-subagent.md
new file mode 100644
index 000000000..050d6f028
--- /dev/null
+++ b/docs/zhtw/s04-subagent.md
@@ -0,0 +1,92 @@
+# s04: Subagents
+
+`s01 > s02 > s03 > [ s04 ] s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Break big tasks down; each subtask gets a clean context"* -- subagents 使用獨立 messages[],讓主對話保持乾淨。
+
+## 問題
+
+agent 持續工作時,messages array 會不斷變長。每一次讀檔、每一段 bash 輸出都會永久留在 context。像「這個專案用哪個測試框架?」可能要讀 5 個檔案,但 parent 真正需要的答案其實只有一句:「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. parent 有 `task` 工具;child 只有 base 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=[]` 起跑,跑自己的迴圈。最後只回傳最終文字給 parent。
+
+```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)"
+```
+
+child 的完整訊息歷史(可能 30+ 次 tool calls)都會被丟棄。parent 只收到一段摘要,作為一般 `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/zhtw/s05-skill-loading.md b/docs/zhtw/s05-skill-loading.md
new file mode 100644
index 000000000..eb26d7b66
--- /dev/null
+++ b/docs/zhtw/s05-skill-loading.md
@@ -0,0 +1,106 @@
+# s05: Skills
+
+`s01 > s02 > s03 > s04 > [ s05 ] s06 | s07 > s08 > s09 > s10 > s11 > s12`
+
+> *"Load knowledge when you need it, not upfront"* -- 透過 tool_result 注入,不塞進 system prompt。
+
+## 問題
+
+你希望 agent 遵循特定領域流程:git 慣例、測試模式、code review checklist。若把所有內容都塞進 system prompt,會把大量 token 浪費在根本用不到的 skills 上。10 個 skill、每個 2000 tokens,就等於 20,000 tokens;而大多數任務其實只會用到其中一小部分。
+
+## 解法
+
+```
+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:system prompt 只放 skill *名稱*(便宜)。Layer 2:完整 skill *內容* 透過 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 ID。
+
+```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 放進 system prompt;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"]),
+}
+```
+
+模型先知道有哪些 skills(低成本),再在需要時載入內容(高成本)。
+
+## 相較 s04 的變更
+
+| Component | 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/zhtw/s06-context-compact.md b/docs/zhtw/s06-context-compact.md
new file mode 100644
index 000000000..109afcd83
--- /dev/null
+++ b/docs/zhtw/s06-context-compact.md
@@ -0,0 +1,123 @@
+# 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"* -- 三層壓縮策略,讓 sessions 幾乎可無限延伸。
+
+## 問題
+
+context window 是有限的。一次 `read_file` 讀到 1000 行,可能就吃掉約 4000 tokens。讀 30 個檔案再跑 20 次 bash,整體就會超過 100,000 tokens。若沒有壓縮策略,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 results 換成 placeholder。
+
+```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**:tokens 超過門檻時,先把完整對話存到磁碟,再請 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}"},
+ {"role": "assistant", "content": "Understood. Continuing."},
+ ]
+```
+
+3. **Layer 3 -- manual 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(...)
+ # ... tool execution ...
+ if manual_compact:
+ messages[:] = auto_compact(messages) # Layer 3
+```
+
+transcripts 會把完整歷史保存到磁碟。資料不是消失,而是移出「活躍 context」。
+
+## 相較 s05 的變更
+
+| Component | 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` (watch micro-compact replace old results)
+2. `Keep reading files until compression triggers automatically`
+3. `Use the compact tool to manually compress the conversation`
diff --git a/docs/zhtw/s07-task-system.md b/docs/zhtw/s07-task-system.md
new file mode 100644
index 000000000..f9730a66c
--- /dev/null
+++ b/docs/zhtw/s07-task-system.md
@@ -0,0 +1,125 @@
+# 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"* -- 檔案式 task graph(含 dependencies),是 multi-agent 協作的基礎。
+
+## 問題
+
+s03 的 TodoManager 只是記憶體中的平面 checklist:沒有順序、沒有 dependencies、狀態也只有做完或沒做完。真實目標往往有結構 -- task B 依賴 task A、tasks C 與 D 可平行、task E 要等 C 與 D 都完成。
+
+沒有明確關係,agent 就無法判斷哪些可做、哪些被卡住、哪些可同時進行。而且清單只在記憶體裡,經過 context compression(s06)就會被洗掉。
+
+## 解法
+
+把 checklist 升級成「落地到磁碟」的 **task graph**。每個 task 都是一個 JSON 檔案,包含 status、dependencies(`blockedBy`)與 dependents(`blocks`)。這張圖會即時回答三個問題:
+
+- **哪些可做?** -- `pending` 且 `blockedBy` 為空的 tasks。
+- **哪些被卡住?** -- 正在等待未完成 dependencies 的 tasks。
+- **哪些已完成?** -- `completed` tasks;完成時會自動解除 dependents 的阻塞。
+
+```
+.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 graph 從 s07 開始成為協作主幹:s08 的背景執行、s09+ 的多 agent 團隊、s12 的 worktree 隔離,都會讀寫同一套結構。
+
+## 運作方式
+
+1. **TaskManager**:每個 task 一個 JSON 檔,提供含 dependency graph 的 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": [],
+ "blocks": [], "owner": ""}
+ self._save(task)
+ self._next_id += 1
+ return json.dumps(task, indent=2)
+```
+
+2. **Dependency resolution**:task 完成後,會把自己的 ID 從其他 task 的 `blockedBy` 清掉,自動解鎖 dependents。
+
+```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. **Status + dependency wiring**:`update` 同時處理狀態遷移與 dependency 關係。
+
+```python
+def update(self, task_id, status=None,
+ add_blocked_by=None, add_blocks=None):
+ task = self._load(task_id)
+ if status:
+ task["status"] = status
+ if status == "completed":
+ self._clear_dependency(task_id)
+ self._save(task)
+```
+
+4. 四個 task 工具加入 dispatch map。
+
+```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 graph 是預設的多步任務模型;s03 的 Todo 則保留給單次 session 的快速 checklist。
+
+## 相較 s06 的變更
+
+| Component | Before (s06) | After (s07) |
+|---|---|---|
+| Tools | 5 | 8 (`task_create/update/list/get`) |
+| Planning model | Flat checklist (in-memory) | Task graph with dependencies (on disk) |
+| Relationships | None | `blockedBy` + `blocks` edges |
+| Status tracking | Done or not | `pending` -> `in_progress` -> `completed` |
+| Persistence | Lost on compression | Survives compression and restarts |
+
+## 動手試試
+
+```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/zhtw/s08-background-tasks.md b/docs/zhtw/s08-background-tasks.md
new file mode 100644
index 000000000..6cf755604
--- /dev/null
+++ b/docs/zhtw/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"* -- daemon threads 在背景執行命令,完成時注入通知。
+
+## 問題
+
+有些命令會跑很久:`npm install`、`pytest`、`docker build`。若迴圈是 blocking,模型只能乾等。當使用者說「先安裝相依套件,安裝同時幫我建立設定檔」,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 用 thread-safe notification queue 管理背景任務。
+
+```python
+class BackgroundManager:
+ def __init__(self):
+ self.tasks = {}
+ self._notification_queue = []
+ self._lock = threading.Lock()
+```
+
+2. `run()` 啟動 daemon thread,立即回傳。
+
+```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. subprocess 完成後,把結果丟進 notification queue。
+
+```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 前,agent loop 先 drain notifications。
+
+```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""})
+ messages.append({"role": "assistant",
+ "content": "Noted background results."})
+ response = client.messages.create(...)
+```
+
+迴圈仍維持單執行緒;只有 subprocess I/O 被平行化。
+
+## 相較 s07 的變更
+
+| Component | 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/zhtw/s09-agent-teams.md b/docs/zhtw/s09-agent-teams.md
new file mode 100644
index 000000000..0aade0e68
--- /dev/null
+++ b/docs/zhtw/s09-agent-teams.md
@@ -0,0 +1,125 @@
+# s09: Agent Teams
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > [ s09 ] s10 > s11 > s12`
+
+> *"When the task is too big for one, delegate to teammates"* -- 持久化 teammates + 非同步 mailboxes。
+
+## 問題
+
+subagents(s04)是一次性的:生成、工作、回傳摘要、結束。沒有身分,也沒有跨呼叫記憶。背景任務(s08)能跑 shell 命令,但無法做 LLM 導向的決策。
+
+真正的團隊協作需要三件事:(1) 可跨單次 prompt 存活的 persistent agents,(2) 身分與生命週期管理,(3) agents 之間的溝通通道。
+
+## 解法
+
+```
+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` 維護 team roster。
+
+```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()` 會建立 teammate,並在 thread 中啟動其 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:append-only JSONL inbox。`send()` 追加 JSON line;`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. 每位 teammate 在每次 LLM 呼叫前都先看 inbox,並把收到的訊息注入 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}"})
+ messages.append({"role": "assistant",
+ "content": "Noted inbox messages."})
+ response = client.messages.create(...)
+ if response.stop_reason != "tool_use":
+ break
+ # execute tools, append results...
+ self._find_member(name)["status"] = "idle"
+```
+
+## 相較 s08 的變更
+
+| Component | Before (s08) | After (s09) |
+|----------------|------------------|----------------------------|
+| Tools | 6 | 9 (+spawn/send/read_inbox) |
+| Agents | Single | Lead + N teammates |
+| Persistence | None | config.json + JSONL inboxes|
+| Threads | Background cmds | Full agent loops per thread|
+| Lifecycle | Fire-and-forget | idle -> working -> idle |
+| Communication | None | 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. Type `/team` to see the team roster with statuses
+5. Type `/inbox` to manually check the lead's inbox
diff --git a/docs/zhtw/s10-team-protocols.md b/docs/zhtw/s10-team-protocols.md
new file mode 100644
index 000000000..b06a74aac
--- /dev/null
+++ b/docs/zhtw/s10-team-protocols.md
@@ -0,0 +1,104 @@
+# s10: Team Protocols
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > [ s10 ] s11 > s12`
+
+> *"Teammates need shared communication rules"* -- 一套 request-response pattern 可驅動所有協商。
+
+## 問題
+
+s09 中,teammates 已能工作與溝通,但仍缺乏結構化協調:
+
+**Shutdown**:直接殺 thread 會留下半寫檔案與過期 config.json。你需要 handshake:lead 發請求,teammate 回覆 approve(收尾後退出)或 reject(繼續工作)。
+
+**Plan approval**:當 lead 說「重構 auth module」時,teammate 會立刻開工。對高風險變更,應先把 plan 送審。
+
+兩者本質相同:一方送出帶唯一 ID 的 request,另一方引用同一 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. lead 發起 shutdown:先產生 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. teammate 收到請求後,以 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. Plan approval 也是同一模式:teammate 送 plan(產生 request_id),lead 以同一 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` 這個狀態機可處理任意 request-response protocol。
+
+## 相較 s09 的變更
+
+| Component | Before (s09) | After (s10) |
+|----------------|------------------|------------------------------|
+| Tools | 9 | 12 (+shutdown_req/resp +plan)|
+| Shutdown | Natural exit only| Request-response handshake |
+| Plan gating | None | Submit/review with approval |
+| Correlation | None | request_id per request |
+| FSM | None | 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. Type `/team` to monitor statuses
diff --git a/docs/zhtw/s11-autonomous-agents.md b/docs/zhtw/s11-autonomous-agents.md
new file mode 100644
index 000000000..f341eddfc
--- /dev/null
+++ b/docs/zhtw/s11-autonomous-agents.md
@@ -0,0 +1,140 @@
+# s11: Autonomous Agents
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > [ s11 ] s12`
+
+> *"Teammates scan the board and claim tasks themselves"* -- 不需要 lead 一項一項指派。
+
+## 問題
+
+在 s09-s10 中,teammates 只有在被明確指示時才會工作。lead 必須為每位 teammate 下具體 prompt。task board 上有 10 個未認領任務?lead 得手動分派 10 次。這無法擴展。
+
+真正的自主是:teammates 自己掃 task board、認領未認領任務、完成後再繼續找下一個。
+
+還有一個細節:context compression(s06)後,agent 可能忘記自己是誰。identity re-injection 可解決這件事。
+
+## 解法
+
+```
+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. teammate loop 分兩段: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 階段會循環檢查 inbox 與 task board。
+
+```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 # timeout -> shutdown
+```
+
+3. task board 掃描條件:`pending`、無 owner、且未被 blocked。
+
+```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. identity re-injection:若 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 的變更
+
+| Component | Before (s10) | After (s11) |
+|----------------|------------------|----------------------------|
+| Tools | 12 | 14 (+idle, +claim_task) |
+| Autonomy | Lead-directed | Self-organizing |
+| Idle phase | None | Poll inbox + task board |
+| Task claiming | Manual only | Auto-claim unclaimed tasks |
+| Identity | System prompt | + re-injection after compress|
+| Timeout | None | 60s idle -> auto shutdown |
+
+## 動手試試
+
+```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. Type `/tasks` to see the task board with owners
+5. Type `/team` to monitor who is working vs idle
diff --git a/docs/zhtw/s12-worktree-task-isolation.md b/docs/zhtw/s12-worktree-task-isolation.md
new file mode 100644
index 000000000..3ad5bf0af
--- /dev/null
+++ b/docs/zhtw/s12-worktree-task-isolation.md
@@ -0,0 +1,119 @@
+# s12: Worktree + Task Isolation
+
+`s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > [ s12 ]`
+
+> *"Each works in its own directory, no interference"* -- tasks 管目標,worktrees 管目錄,兩者以 ID 綁定。
+
+## 問題
+
+到 s11 為止,agents 已能自主認領並完成任務;但所有任務都在同一個共享目錄執行。若兩個 agents 同時重構不同模組,很容易互相干擾:agent A 改 `config.py`,agent B 也改 `config.py`,未暫存變更混在一起,兩邊都難以乾淨回復。
+
+task board 只管理 *做什麼*,不管理 *在哪裡做*。解法是:每個 task 給一個獨立 git worktree。tasks 管目標,worktrees 管執行上下文,並用 task 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. **先建立 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 gets new entry, task_1.json gets 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、送出事件。一次呼叫完成 teardown + completion。
+
+```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`。
+
+若發生 crash,可透過磁碟上的 `.tasks/` + `.worktrees/index.json` 重建狀態。對話記憶是易失的,檔案狀態才是可持久恢復的。
+
+## 相較 s11 的變更
+
+| Component | Before (s11) | After (s12) |
+|--------------------|----------------------------|----------------------------------------------|
+| Coordination | Task board (owner/status) | Task board + explicit worktree binding |
+| Execution scope | Shared directory | Task-scoped isolated directory |
+| Recoverability | Task status only | Task status + worktree index |
+| Teardown | Task completion | Task completion + explicit keep/remove |
+| Lifecycle visibility | Implicit in logs | Explicit events in `.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.`