# ๐Ÿ” Design Review โ€” Job 2174eaaf (`worktree-creator-model.md` @ `fe96db1`) - **Reviewer**: `reviewer-grok-01` ยท 2026-09-14 - **๋ฌธ์„œ**: `multi-agent-mux-wt/design-worktree-model/docs/design/worktree-creator-model.md` (`git log -1` = `fe96db1`). ๋ณธ ์ฒดํฌ์•„์›ƒ์€ `main`. - **์„ฑ๊ฒฉ**: ์„ค๊ณ„ ๋ฆฌ๋ทฐ. ์ฝ”๋“œยท๋ฌธ์„œ ๋ฏธ์ˆ˜์ •, ์ฒดํฌ์•„์›ƒ ๋ฏธ์ „ํ™˜. ์ œ์•ˆ C(creator=์›ŒํฌํŠธ๋ฆฌ, ๋ฆฌ๋ทฐ์–ด ํ’€=๋ณธ ์ฒดํฌ์•„์›ƒ, `.mam` ๊ณต์œ )๋Š” ๋‘ ๋ฌธ์ œ(๋ณ‘๋ ฌ ๊ตฌํ˜„, ๊ณต์œ  ์ฒดํฌ์•„์›ƒ `checkout` ์‚ฌ๊ณ )๋ฅผ **์ฑ„ํƒ ๊ฐ€๋Šฅํ•œ ์ˆ˜์ค€์œผ๋กœ** ํ’€๋ฉฐ, ยง5 ์— ๋น ์ง„ ์‹คํŒจ ๊ฒฝ๋กœ๋ฅผ ๋ณด์™„ํ•˜๋ฉด ๊ตฌํ˜„์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. ## ยง6 ์งˆ๋ฌธ ### 1. ์—ญํ•  ๋ถ„๋ฆฌ๊ฐ€ ๋‘ ๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š”๊ฐ€? โ€” **๋™์˜ + ๋ณด์™„** - **๋ณ‘๋ ฌ์„ฑ**: creator ๊ฐ€ ์ด์Šˆ๋ณ„ cwd/๋ธŒ๋žœ์น˜๋ฅผ ๊ฐ€์ง€๋ฉด ๊ตฌํ˜„์€ ๋™์‹œ์— ์ง„ํ–‰๋œ๋‹ค. ๋ฆฌ๋ทฐ์–ด ํ’€์€ ์žก ๋‹จ์œ„ ์ง๋ ฌ(`session_busy` rc 5 โ†’ `MAM_SESSION_BUSY_RETRY_S` 1ํšŒ, `runner.py:313-314`). ๋ฌธ์„œ ยง4 ์„œ์ˆ ๊ณผ ๋งž๋‹ค. - **checkout ์‚ฌ๊ณ **: ๋ณธ ์ฒดํฌ์•„์›ƒ์„ `main` ์— ๊ณ ์ •ํ•˜๊ณ  ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐยทcreator ์ปค๋ฐ‹์„ ์›ŒํฌํŠธ๋ฆฌ์—์„œ๋งŒ ํ•˜๋ฉด, ๊ณต์œ  `checkout` ํ•œ ๋ฐฉ์œผ๋กœ ์ „์›์ด ์›€์ง์ด๋Š” ๊ฒฝ๋กœ๋Š” ์‚ฌ๋ผ์ง„๋‹ค. - **๋†“์นœ ๊ฒฝ๋กœ (๋ฌธ์„œ๋ฅผ ๊ณ ์น  ๊ณณ: ยง4 ํ•œ๊ณ„ / ยง5 ์ถ”๊ฐ€)**: - ๋ฆฌ๋ทฐ์–ด๊ฐ€ `$WT` ์—์„œ pytest ๋ฅผ ๋Œ๋ฆฌ๋ฉด `.pytest_cache`/`__pycache__`/์‹คํŒจ ์‚ฐ์ถœ๋ฌผ์ด ์›ŒํฌํŠธ๋ฆฌ์— ๋‚จ์•„ creator ๊ฐ€ dirty ๋กœ ๋ณธ๋‹ค. PYTHONDONTWRITEBYTECODE, `--basetemp` ๋ฅผ WT ๋ฐ–, ๋ฆฌ๋ทฐ ํ›„ `git status` ์ œ์•ฝ์„ ยง5 ์— ์ ์„ ๊ฒƒ. - ์›ŒํฌํŠธ๋ฆฌ ์‚ญ์ œ ์ „ `stop` ์—†์ด `worktree remove` ํ•˜๋ฉด yaml ํ–‰ยทherdr pane ์ด ๋‚จ๋Š”๋‹ค. ๋ ˆ์‹œํ”ผ์— stop โ†’ worktree remove ์ˆœ์„œ. - ๋ชจ๋‹ˆํ„ฐ **์ž๋™๋“ฑ๋ก** (`reconcile.sh:651-654`) ์€ `pane.cwd` ๊ฐ€ `WORKSPACE_ROOT` ๋˜๋Š” ๊ทธ ํ•˜์œ„์ผ ๋•Œ๋งŒ ํƒ„๋‹ค. WT ๊ฐ€ `.../multi-agent-mux-wt/issue-20` ์ด๋ฉด MAIN ์˜ prefix ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ **๋ฏธ๋“ฑ๋ก herdr ์„ธ์…˜์€ ์ž๋™๋“ฑ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค**. yaml ์— ์ด๋ฏธ ์žˆ๋Š” ํ–‰์€ ์ด ํ•„ํ„ฐ๋ฅผ ํƒ€์ง€ ์•Š๋Š”๋‹ค. โ€œcreate ๋ ˆ์‹œํ”ผ๋กœ๋งŒ ๋“ฑ๋กโ€์„ ยง3 ์— ๋ช…์‹œํ•  ๊ฒƒ. yaml ํ–‰์„ drift ๋กœ ์ง€์šฐ์ง€๋Š” ์•Š์Œ(์ด๋ฆ„ ๋งค์นญ). ### 2. ์ œ์–ด ํ‰๋ฉด env override ๊ฐ€ ์•ˆ์ „ํ•œ๊ฐ€? โ€” **๋™์˜ + ๋ณด์™„ (ํ•„์ˆ˜)** | ๋ณ€์ˆ˜ | ๊ทผ๊ฑฐ | C ์•ˆ์—์„œ | |---|---|---| | `WORKSPACE_ROOT` | `lib.sh:26-27` ์ด๋ฏธ override | MAIN ์œผ๋กœ ๋‘๋ฉด yaml/jobs ๊ธฐ๋ณธ์ด MAIN | | `AGENT_SESSIONS_YAML` | `lib.sh:34` | ๋ช…์‹œํ•˜๋ฉด ์•ˆ์ „. ๋ฏธ์„ค์ • ์‹œ `WORKSPACE_ROOT/.mam/...` | | `MAM_JOBS_DIR` / `DELEGATE_JOB_LOGS_DIR` | `mqtt_common.py:150-163`, `186-187` โ€” `MAM_JOBS_DIR` ์šฐ์„ , ์•„๋‹ˆ๋ฉด `WORKSPACE_ROOT/.mam` | `WORKSPACE_ROOT=MAIN` ๋งŒ์œผ๋กœ๋„ jobs ๋Š” MAIN. ๋ฌธ์„œ์˜ ๋„ค ๋ณ€์ˆ˜๋Š” ๊ณผ์ž‰์ด ์•„๋‹ˆ๋ผ ๋ฐฉ์–ด. | - **status**: `status.sh:59-76` ์ด **ํ–‰์˜ `pane.cwd`** ๋กœ claude ํ”„๋กœ์ ํŠธ ํ‚ค๋ฅผ ๋งŒ๋“ ๋‹ค. WT cwd ํ–‰์„ MAIN `WORKSPACE_ROOT` ์™€ ํ˜ผ๋™ํ•˜์ง€ ์•Š์Œ. **๋™์˜.** - **resume/stop**: `resume_session.sh:42,165` ์€ `--workspace` ๊ฐ€ pane ์ƒ์„ฑ cwd. `verify_session_uuid` (`verify_session.py:90-93`) ๋Š” `workspace_key(pane.cwd) != workspace_key(ws)` ์ด๋ฉด **์ฆ‰์‹œ False**. `find_workspace_uuid` (`workspace_uuid.py:57-59`) ๋„ pane.cwd ์™€ `--workspace` ์ผ์น˜๋งŒ ๋ณธ๋‹ค. ๋”ฐ๋ผ์„œ resume/stop ์˜ `--workspace` ๋Š” **MAIN ์ด ์•„๋‹ˆ๋ผ WT(pane.cwd)** ์—ฌ์•ผ ํ•œ๋‹ค. `WORKSPACE_ROOT`/yaml ์€ MAIN. **ยง3 ๋ ˆ์‹œํ”ผ์— ์ด ์ด์›์„ฑ์„ ์“ฐ์ง€ ์•Š์œผ๋ฉด resume ์ด ๊นจ์ง„๋‹ค.** ๊ณ ์น  ๊ณณ: ยง3 ์ฝ”๋“œ๋ธ”๋ก ๋‹ค์Œ ๋ฌธ๋‹จ. - **claude ์ €์žฅ ํ‚ค**: `claude.py:117-118` `workspace_key(ctx.workspace)` โ†’ `~/.claude/projects/`. create `--workspace WT` ์ด๋ฉด ํ‚ค๊ฐ€ WT. resume ๋„ WT ๋ฅผ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค. ๋ฌธ์„œ ํ‘œ(ยง1)์™€ ๋งž์Œ. - **ํ† ํ”ฝ ์ง€๋ฌธ**: `reconcile.sh:288-290` `sha256(abspath(WORKSPACE_ROOT))[:12]`. ๋ชจ๋‹ˆํ„ฐยทcreator ๊ฐ€ ๊ฐ™์€ `WORKSPACE_ROOT=MAIN` ์ด๋ฉด ์ง€๋ฌธ์ด ํ•˜๋‚˜. HMAC/`auth_token` ์€ job ๋ ˆ์ฝ”๋“œ ๋‹จ์œ„๋ผ ๊ณต์œ  ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์™€ ๋งž์Œ. ์›ŒํฌํŠธ๋ฆฌ์—์„œ override ์—†์ด reconcile ์„ ๋Œ๋ฆฌ๋ฉด ์ง€๋ฌธ์ด ๊ฐˆ๋ผ์ง„๋‹ค โ†’ ๋ชจ๋‹ˆํ„ฐ๋Š” ํ•ญ์ƒ MAIN ์—์„œ. ### 3. A/B ๋Œ€๋น„ C ๋น„์šฉยท์ด๋“ โ€” **๋™์˜**. ๋” ์‹ผ 1๋‹จ๊ณ„๊ฐ€ ์žˆ๋‹ค. - A: ์ด์Šˆ๋‹น ์—์ด์ „ํŠธ 5๊ฐœยท๋ฌธ๋งฅ ๋ฆฌ์…‹ยท`.mam` ๋ถ„์‚ฐ. ๋น„์Œˆ. ๋™์˜. - B: ๋ณ‘๋ ฌ ์—†์Œ + creator ๊ฐ€ ๋ณธ ์ฒดํฌ์•„์›ƒ์„ ์˜ฎ๊น€. #18 ์œ ํ˜• ์ž”์กด. ๋™์˜. - C: ๊ตฌํ˜„ ๋ณ‘๋ ฌ + ๋ฆฌ๋ทฐ ๋ฌธ๋งฅ ์œ ์ง€ + ์ œ์–ด ํ‰๋ฉด ํ•˜๋‚˜. ๋งž๋‹ค. - **๋Œ€์•ˆ D (๋น„์ฐจ๋‹จ)**: ๋ฆฌ๋ทฐ์–ด์—๊ฒŒ๋„ **๊ฐ™์€ ๋ธŒ๋žœ์น˜์˜ ์ฝ๊ธฐ ์ „์šฉ ์›ŒํฌํŠธ๋ฆฌ**๋ฅผ ์ฃผ๋ฉด MAIN ํ…Œ์ŠคํŠธ ์˜ค์—ผ์„ ์ค„์ธ๋‹ค. ๋น„์šฉโ†‘. 1๋‹จ๊ณ„ C ๋กœ ์‹œ์ž‘ํ•˜๊ณ  D ๋Š” ์„ ํƒ. - **๋Œ€์•ˆ E** (ํ›…์œผ๋กœ main checkout ๊ธˆ์ง€): ๋ณ‘๋ ฌ์„ ์•ˆ ์คŒ. C ๋ฅผ ๋Œ€์ฒดํ•˜์ง€ ๋ชปํ•จ. ### 4. ยง5 ๋ˆ„๋ฝยท๊ณผ์ž‰ / ๋‹ค์ค‘ ๋ฃจํ”„๋ฅผ ๋จผ์ €? โ€” **๋ณด์™„** | ยง5 | ํŒ์ • | |---|---| | 1 ๋ธŒ๋ฆฌํ”„ ์ ˆ๋Œ€๊ฒฝ๋กœ | **ํ•„์ˆ˜, ๋ฒ”์œ„ ๋ถ€์กฑ.** `multi-agent-mux-delegate-job:199` ์ฃผ์ž…์ด `.mam/jobs//brief.md` ์ƒ๋Œ€๊ฒฝ๋กœ. creator cwd=WT ์—๋Š” ์—†์Œ. ๊ฐ™์€ ํŒŒ์ผ `:178` **Output Report Path** ๋„ ์ƒ๋Œ€๊ฒฝ๋กœ. ๋ฃจํ”„ `find_report` (`runner.py:389-394`) ๋Š” `self.mam_dir/jobs/` = MAIN. creator ๊ฐ€ WT ์— ๋ฆฌํฌํŠธ๋ฅผ ์“ฐ๋ฉด ๋ฃจํ”„๊ฐ€ ๋ชป ์ฐพ๋Š”๋‹ค. **brief ์™€ report-final.md ๋ชจ๋‘ `$REGISTRY_DIR` ์ ˆ๋Œ€๊ฒฝ๋กœ.** | | 2 `--worktree` | **ํ•„์ˆ˜.** `collect_changes_diff` `runner.py:399-408` ๊ณผ `base_commit` `runner.py:564-565` ๊ฐ€ `cwd=self.workspace_root`(MAIN HEAD). ์›ŒํฌํŠธ๋ฆฌ ๋ธŒ๋žœ์น˜ diff ๊ฐ€ ์•„๋‹˜. ์ธ์šฉ ์ •ํ™•. | | 3 create ๋ ˆ์‹œํ”ผ | **ํ•„์ˆ˜.** resume `--workspace $WT` ์ด์›์„ฑ ์ถ”๊ฐ€. | | 4 `.mam` ๊ฒฝํ•ฉ | **๋‘ `run_loop.sh` ์ „์— ํ•„์ˆ˜, 1๋‹จ๊ณ„์—๋Š” ๊ณผ์ž‰ ๊ฐ€๋Šฅ.** `loop-checkpoint.json` (`runner.py:60`)ยท`loop-guard-active` (`:427`) ๋Š” ํŒŒ์ผ ํ•˜๋‚˜. ๋‘ ๋ฃจํ”„๋Š” ์ฒดํฌํฌ์ธํŠธ๋ฅผ ๋ฎ์–ด์“ด๋‹ค. **์‹œ์ž‘์€ โ€œ๋ฃจํ”„๋Š” ํ•˜๋‚˜, creator ์žก์€ delegate-job ์œผ๋กœ๋งŒ ๋ณ‘๋ ฌโ€.** ์ด์Šˆ๋‹น ๋ฃจํ”„๋ฅผ ๋™์‹œ์— ๋Œ๋ฆฌ๋ ค๋ฉด ยง5-4 ๊ฐ€ ์„ ํ–‰. ยง4 ๋ฌธ์žฅ์— ์ด ๋‹จ๊ณ„๋ฅผ ๋ฐํž ๊ฒƒ. | | 5 ๋ธŒ๋ฆฌํ”„ ํ•„๋“œ | ํ•„์ˆ˜. | ### 5. #17 ํ•ญ๋ชฉ 4 ์™€์˜ ์ˆœ์„œ โ€” **๋™์˜** ์šด์˜ ๋ชจ๋ธ(C)์„ ๋ฌธ์„œยท๋ ˆ์‹œํ”ผ๋กœ ๊ณ ์ •ํ•œ ๋’ค, ํ•ญ๋ชฉ 4(์…ธ ๊ณ„์ธต ์ถ•์†Œ)์—์„œ `--worktree`ยท์ ˆ๋Œ€ ๋ธŒ๋ฆฌํ”„/๋ฆฌํฌํŠธ ๊ฒฝ๋กœ๋ฅผ ์ฝ”๋“œ๋กœ ํก์ˆ˜ํ•˜๋Š” ์ˆœ์„œ๊ฐ€ ๋งž๋‹ค. ํ•ญ๋ชฉ 4 ๋ฅผ ๋จผ์ € ํ•˜๋ฉด ์›ŒํฌํŠธ๋ฆฌ cwd ๊ฐ€ ๋‹ค์‹œ ๊นจ์ง„๋‹ค. ## ๋ธŒ๋ฆฌํ”„ (1)โ€“(7) ์š”์•ฝ | # | ํŒ์ • | |---|---| | (1) env ์ผ๊ด€์„ฑ | ๋™์˜. resume/stop `--workspace`=pane.cwd(WT). status ๋Š” pane.cwd ์‚ฌ์šฉ. | | (2) ์ƒ๋Œ€ brief | ๋™์˜, ๊นจ์ง. ๋ฆฌํฌํŠธ ๊ฒฝ๋กœ๋„ ๊นจ์ง. | | (3) diff/base | ๋™์˜, `runner.py:399-408`ยท`564-565`. | | (4) ๋‹ค์ค‘ ๋ฃจํ”„ | ์‹ค์œ„ํ—˜. 1๋‹จ๊ณ„๋Š” ๋ฃจํ”„ ํ•˜๋‚˜. | | (5) ์‹คํŒจ ๊ฒฝ๋กœ | pytest ์˜ค์—ผ, yaml ์ž”ํ–‰, ๋ชจ๋‹ˆํ„ฐ ์ž๋™๋“ฑ๋ก prefix, ์ž˜๋ชป๋œ WORKSPACE ๋กœ resume. ํ† ํ”ฝ/HMAC ์€ ๊ณต์œ  `.mam` ์ด๋ฉด ์•ˆ์ „. | | (6) A/B/C | ํƒ€๋‹น. D ๋Š” ํ›„์†. | | (7) #17-4 | ๋ฌธ์„œ ๋จผ์ €. | ์ฑ„ํƒ ๊ฐ€๋Šฅ. ๊ทผ๋ณธ ๊ฒฐํ•จ ์—†์Œ. ๊ตฌํ˜„ ์ „ ยง3ยทยง5-1ยทยง5-4 ๋ฌธ๊ตฌ๋ฅผ ๊ณ ์น˜๋ฉด ๋œ๋‹ค. [VERDICT: PASS]