# ๐Ÿ“ ๊ตฌํ˜„ ๊ณ„ํš์„œ Rev.2 โ€” `PRIVATE_SERVER.md` ํ™•์žฅ ๋ฐ `implementation_plan.md` ์‹ ์„ค - **Job ID**: `8c651798` (Rev.1 = `d42004ee`) - **Planner**: claude (session: `herdr:canary-projects-multi-agent-mux-creator-claude`) - **Role**: Planner (`MULTI_AGENT_RULES.md` ยง1 โ€” ๋ณธ ์ž‘์—…์—์„œ ์ €์žฅ์†Œ ์ฝ”๋“œ **0๊ฑด ์ˆ˜์ •**) - **๋ฐ˜์˜ ๋Œ€์ƒ Challenge**: `019495f4` (agy, Worker / Plan Reviewer) โ€” `[VERDICT: PASS WITH CHALLENGE]` - **๊ธฐ์ค€ ์ปค๋ฐ‹**: `a9934ad` โ€” ํ…Œ์ŠคํŠธ ๋ฒ ์ด์Šค๋ผ์ธ **276** --- ## 0. Challenge ํŒ์ • ์š”์•ฝ Challenge 3๊ฑด์„ **์‹ค์ธก์œผ๋กœ ํŒ์ •**ํ–ˆ์Šต๋‹ˆ๋‹ค. 3๊ฑด ๋ชจ๋‘ **์ง€์ ์€ ํƒ€๋‹น**ํ•˜๋‚˜, ๊ทธ์ค‘ 1๊ฑด์€ **์ œ์‹œ๋œ ํ•ด๋ฒ• ์ž์ฒด๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š๊ณ **, 1๊ฑด์€ **์ง€์ ๋ณด๋‹ค ์‹ฌ๊ฐ**ํ•˜๋ฉฐ, 1๊ฑด์€ **Rev.1 ์— ์ด๋ฏธ ์žˆ๋˜ ์กฐํ•ญ์˜ ๊ตฌ์ฒดํ™”**์ž…๋‹ˆ๋‹ค. | # | ์ง€์  | ํŒ์ • | ์‹ค์ธก ๊ทผ๊ฑฐ | |---|---|---|---| | **C1-a** | E-3 ์ˆ˜์ •์— `registry.py register` ์ •ํ™•ํ•œ ์ธ์ž๊ฐ€ ํ•„์š” | โœ… **์ฑ„ํƒ** โ€” `--prompt` ๋Š” ์‹ค์ œ๋กœ required | `registry.py:240` `p_reg.add_argument("--prompt", required=True)` | | **C1-b** | "`--job-id ` ๋ฅผ ์“ด๋‹ค (not `--job`)" + ๋ณต์‚ฌยท๋ถ™์—ฌ๋„ฃ๊ธฐ ๋ช…๋ น ์ œ์‹œ | โŒ **์‹ค์ธก ๋ฐ˜์ฆ โ€” ํ•ด๋ฒ•์ด ๋™์ž‘ํ•˜์ง€ ์•Š์Œ** | `--job-id` ๋Š” `register` ์„œ๋ธŒํŒŒ์„œ์— **์กด์žฌํ•˜์ง€ ์•Š์Œ**. ์‹คํ–‰ ์‹œ `error: unrecognized arguments: --job-id test-ping-01` | | **C1-c** | (์ œ์‹œ ๋ช…๋ น์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„) | โš ๏ธ **์ถ”๊ฐ€ ๊ฒฐํ•จ 2๊ฑด ๋ฐœ๊ฒฌ** | โ‘  `--registry-dir` ๋Š” **๋ถ€๋ชจ ํŒŒ์„œ** ์ธ์ž๋ผ ์„œ๋ธŒ์ปค๋งจ๋“œ **์•ž**์— ์™€์•ผ ํ•จ(์‹ค์ธก ์˜ค๋ฅ˜) โ‘ก ํ…Œ์ŠคํŠธ ์žก์ด `pending` ์œผ๋กœ **์˜๊ตฌ ์ž”์กด** โ†’ `--wait-any` ๊ฐ€ ์ˆ˜์ง‘ | | **C2** | `/etc/nats/nats.conf` ยท `/data` ๋Š” ๋น„๋ฃจํŠธ ํ™˜๊ฒฝ์—์„œ `Permission denied` | โœ… **์ฑ„ํƒ โ€” ์‹ฌ๊ฐ๋„ ์ƒํ–ฅ** | macOS ๋Š” `Permission denied` ๊ฐ€ ์•„๋‹ˆ๋ผ **`Read-only file system`**. `/` ๊ฐ€ sealed APFS ๋ผ **sudo ๋กœ๋„ ์ƒ์„ฑ ๋ถˆ๊ฐ€** | | **C3** | G-D2 ๋ฅผ ์ฝ”๋“œ ํŽœ์Šค ๋ฒ”์œ„๋กœ ํ•œ์ •ํ•  ๊ฒƒ | โœ… **์ฑ„ํƒ โ€” ๋‹จ, Rev.1 ยง5.5 ์— ์ด๋ฏธ ๋ช…์‹œ๋œ ์กฐํ•ญ** | Rev.1 ์›๋ฌธ: *"์ •๊ทœ์‹์ด ์ฝ”๋“œ ๋ธ”๋ก ๋ฐ–์˜ ์‚ฐ๋ฌธ๊นŒ์ง€ ์žก์œผ๋ฉด ์˜คํƒ์ด ๋‚ฉ๋‹ˆ๋‹ค. ํŽœ์Šค(```) ์•ˆ ๋ธ”๋ก์œผ๋กœ ์Šค์ฝ”ํ”„๋ฅผ ํ•œ์ •ํ•˜๊ณ โ€ฆ"* โ€” ๋‹ค๋งŒ **๊ตฌ์ฒด์  ์ถฉ๋Œ ์‚ฌ๋ก€๋ฅผ ํŠน์ •ํ•œ ๊ฒƒ์€ ์œ ํšจํ•œ ๊ธฐ์—ฌ** | **๋ฉ”ํƒ€ ๊ด€์ฐฐ**: C1-b ๋Š” ์ด ๋ฆฌ๋ทฐ๊ฐ€ ๊ต์ •ํ•˜๋ ค๋Š” ๊ฒฐํ•จ(E-1ยทE-2ยทE-3 = *๊ฒ€์ฆ๋˜์ง€ ์•Š์€ ๋ณต์‚ฌยท๋ถ™์—ฌ๋„ฃ๊ธฐ ๋ช…๋ น*)๊ณผ **์ •ํ™•ํžˆ ๊ฐ™์€ ์œ ํ˜•**์„ ์žฌ์ƒ์‚ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ยง5.5 ๋ฌธ์„œ ๋“œ๋ฆฌํ”„ํŠธ ๊ฐ€๋“œ์˜ ํ•„์š”์„ฑ์„ ์—ญ์„ค์ ์œผ๋กœ ์ž…์ฆํ•˜๋ฏ€๋กœ, **Rev.2 ๋Š” ๊ฐ€๋“œ ๋ฒ”์œ„๋ฅผ ๋ฌธ์„œ ๋‚ด ์‹คํ–‰ ๋ช…๋ น ์ „๋ฐ˜์œผ๋กœ ํ™•๋Œ€**ํ•ฉ๋‹ˆ๋‹ค(G-D4 ์‹ ์„ค). --- ## 1. C1 ์ •๋ฐ€ ํŒ์ • โ€” E-3 ์ˆ˜์ •์˜ ์ •ํ™•ํ•œ ๋ช…๋ น ### 1.1 ๋ฐ˜์ฆ โ€” `--job-id` ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค Challenge ๊ฐ€ "copy-pasteable" ๋กœ ์ œ์‹œํ•œ ๋ช…๋ น์„ ๊ทธ๋Œ€๋กœ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ: ``` $ registry.py --registry-dir register --job-id test-ping-01 \ --prompt "Private broker connectivity test" --agent-session "herdr:test" registry.py: error: unrecognized arguments: --job-id test-ping-01 ``` `register` ์„œ๋ธŒํŒŒ์„œ(`registry.py:239-252`)์˜ ์ธ์ž๋Š” ๋‹ค์Œ์ด ์ „๋ถ€์ž…๋‹ˆ๋‹ค: ``` --prompt (required) --agent --agent-session --role --timeout --idle-timeout --bits --artifact --auth-token --job-type --reviewer --reviewer-session --max-iterations ``` **`--job-id` ๋„ `--job` ๋„ ์—†์Šต๋‹ˆ๋‹ค.** ํ˜ผ๋™์˜ ์›์ธ์€ ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์ž…๋‹ˆ๋‹ค โ€” `register_job()` **ํ•จ์ˆ˜**์—๋Š” `job_id` ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ๊ณ (`registry.py:72` `job_id = job_id or generate_job_id(bits)`), CLI ์˜ `main()` ์€ ์ด๋ฅผ **์ „๋‹ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**(`:304-318` ์˜ `register_job(...)` ํ˜ธ์ถœ์— `job_id=` ์ธ์ž ๋ถ€์žฌ). ์ฆ‰ **CLI ๋กœ๋Š” ์žก ID ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์—†๊ณ , ํ•ญ์ƒ ์ƒˆ๋กœ ์ฑ„๋ฒˆ๋ฉ๋‹ˆ๋‹ค.** ### 1.2 ์ถ”๊ฐ€ ๊ฒฐํ•จ โ€” `--registry-dir` ์œ„์น˜ ``` $ registry.py register --registry-dir --prompt "x" registry.py: error: unrecognized arguments: --registry-dir ``` `--registry-dir` ์€ `registry.py:236` ์—์„œ **๋ถ€๋ชจ ํŒŒ์„œ**์— ๋“ฑ๋ก๋˜๋ฏ€๋กœ **์„œ๋ธŒ์ปค๋งจ๋“œ ์•ž**์— ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ์— ์‹ค๋ฆด ๋ช…๋ น์ด๋ผ๋ฉด ์ด ์ˆœ์„œ๋ฅผ ํ‹€๋ฆฌ๊ฒŒ ์ ์„ ์—ฌ์ง€๋ฅผ ์—†์• ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ### 1.3 ์ถ”๊ฐ€ ๊ฒฐํ•จ โ€” ํ…Œ์ŠคํŠธ ์žก์˜ ์˜๊ตฌ ์ž”์กด `register_job()` ์€ `status: "pending"`(`registry.py:84`)์œผ๋กœ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  `job_subscriber.py::_collect_jobs()` ์˜ `--wait-any` ๋Š” **`status in ("pending","running")` ์ธ ๋ชจ๋“  ์žก์„ ์ˆ˜์ง‘**ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ •๋ฆฌํ•˜์ง€ ์•Š์€ ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ ์žก์€: - `job_subscriber.py --wait-any` ๊ฐ€ **์˜์›ํžˆ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์œ ๋ น ์žก**์ด ๋˜๊ณ , - `pick_pending` ์˜ ํ›„๋ณด๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค(`agent_session` ์ผ์น˜ ์‹œ). **`registry.py` ์—๋Š” delete/remove ์„œ๋ธŒ์ปค๋งจ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค**(`register/list/get/status/update/get-feedback/pick/logs` ๊ฐ€ ์ „๋ถ€). ๋”ฐ๋ผ์„œ ์ •๋ฆฌ๋Š” `status` ์„œ๋ธŒ์ปค๋งจ๋“œ๋กœ ์ข…๊ฒฐ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ •์„์ž…๋‹ˆ๋‹ค. ### 1.4 ์ฑ„ํƒ โ€” `PRIVATE_SERVER.md` ยง6 ์— ์‹ค๋ฆด ์ตœ์ข… ๋ช…๋ น ```bash # 1) ์ž„์‹œ ์žก ๋“ฑ๋ก โ€” ID ๋Š” ์ง€์ •ํ•  ์ˆ˜ ์—†๊ณ  ์ž๋™ ์ฑ„๋ฒˆ๋˜๋ฏ€๋กœ stdout ์„ ๋ฐ˜๋“œ์‹œ ์บก์ฒ˜ํ•œ๋‹ค JID=$(.venv/bin/python .agents/skills/multi-agent-mux-delegate-job/scripts/registry.py \ --registry-dir .mam/jobs \ register \ --prompt "Private broker connectivity test" \ --agent-session "herdr:test") echo "registered job: $JID" # 2) ์ด๋ฒคํŠธ ๋ฐœํ–‰ (rc=0 ๋‹จ์–ธ) .venv/bin/python .agents/skills/multi-agent-mux-delegate-job/scripts/publish_event.py \ --registry-dir .mam/jobs \ --job "$JID" \ --event progress \ --detail "Private broker connection verified" -v # 3) ์ ‘์† ๋Œ€์ƒ ๋‹จ์–ธ โ€” ๊ฐœ์ธ ์„œ๋ฒ„ IP ๊ฐ€ ๋ณด์ด๊ณ  broker.hivemq.com ์ด ์—†์–ด์•ผ ํ•œ๋‹ค # (-v ๋กœ๊ทธ ๋˜๋Š” ๊ฐ์‚ฌ ๋กœ๊ทธ์—์„œ ํ™•์ธ) # 4) ์ •๋ฆฌ โ€” ๋ฏธ์ •๋ฆฌ ์‹œ --wait-any ๊ฐ€ ์ˆ˜์ง‘ํ•˜๋Š” ์œ ๋ น ์žก์œผ๋กœ ๋‚จ๋Š”๋‹ค .venv/bin/python .agents/skills/multi-agent-mux-delegate-job/scripts/registry.py \ --registry-dir .mam/jobs status --job "$JID" --set completed ``` > ์ฃผ์˜ 3๊ฐ€์ง€๋ฅผ ๋ฌธ์„œ์— ๊ฐ์ฃผ๋กœ ๋ช…์‹œ: โ‘  **`--registry-dir` ์€ ์„œ๋ธŒ์ปค๋งจ๋“œ ์•ž** โ‘ก **์žก ID ๋Š” ์ง€์ • ๋ถˆ๊ฐ€, ์บก์ฒ˜ ํ•„์ˆ˜** โ‘ข **4)๋ฒˆ ์ •๋ฆฌ ์ƒ๋žต ๊ธˆ์ง€**. --- ## 2. C2 ํŒ์ • โ€” ์‹ฌ๊ฐ๋„ ์ƒํ–ฅ (Permission denied ๊ฐ€ ์•„๋‹ˆ๋ผ ์ƒ์„ฑ ๋ถˆ๊ฐ€) Challenge ๋Š” ๋น„๋ฃจํŠธ ํ™˜๊ฒฝ์˜ `Permission denied` ๋ฅผ ์ง€์ ํ–ˆ์Šต๋‹ˆ๋‹ค. **์‹ค์ธก ๊ฒฐ๊ณผ macOS ์—์„œ๋Š” ๊ทธ๋ณด๋‹ค ๊ฐ•ํ•œ ์ œ์•ฝ์ž…๋‹ˆ๋‹ค**: ``` $ mkdir -p /data mkdir: /data: Read-only file system $ mount | grep 'on / ' /dev/disk3s1s1 on / (apfs, sealed, local, read-only, journaled) ``` macOS ์˜ ๋ฃจํŠธ ๋ณผ๋ฅจ์€ **sealed read-only APFS** ์ด๋ฏ€๋กœ `store_dir: "/data"` ๋Š” **`sudo` ๋กœ๋„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค**(`/etc/synthetic.conf` ํŽธ์ง‘ + ์žฌ๋ถ€ํŒ…์ด ํ•„์š”). ๊ทธ๋ฆฌ๊ณ  **๋ณธ ํ”„๋กœ์ ํŠธ์˜ ๊ฐœ๋ฐœ ํ”Œ๋žซํผ์ด darwin** ์ด๋ฏ€๋กœ, Rev.1 ยง3 A-2 ์˜ ๋„ค์ดํ‹ฐ๋ธŒ ์Šค๋‹ˆํŽซ์€ **์ฃผ ์‚ฌ์šฉ ํ™˜๊ฒฝ์—์„œ ๊ณง๋ฐ”๋กœ ์‹คํŒจ**ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ C2 ๋Š” "์‹ค์šฉ์„ฑ ๊ฐœ์„ "์ด ์•„๋‹ˆ๋ผ **E-2 ๊ต์ •์•ˆ ์ž์ฒด์˜ ๊ฒฐํ•จ**์œผ๋กœ ๋ถ„๋ฅ˜ํ•˜๊ณ , ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์œผ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ### 2.1 ์ฑ„ํƒ โ€” ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ๊ธฐ๋ณธ๊ฐ’ **๋„ค์ดํ‹ฐ๋ธŒ (๊ธฐ๋ณธ ๊ฒฝ๋กœ โ€” sudo ๋ถˆํ•„์š”)** ```conf # ~/.config/nats/nats.conf server_name: mam-hub jetstream { store_dir: "~/.local/share/nats/data" # ํ™ˆ ๋””๋ ‰ํ„ฐ๋ฆฌ. ๋ฃจํŠธ ๋ณผ๋ฅจ ์ ‘๊ทผ ์—†์Œ max_file: 10G } http_port: 8222 mqtt { port: 1883 } websocket { port: 8080, no_tls: true } # ๋‚ด๋ถ€๋ง ํ•œ์ • ``` ```bash mkdir -p ~/.config/nats ~/.local/share/nats/data nats-server -c ~/.config/nats/nats.conf ``` **Docker Compose (์ƒ๋Œ€ ๊ฒฝ๋กœ + ๋„ค์ž„๋“œ ๋ณผ๋ฅจ)** ```yaml services: nats: image: nats:latest container_name: mam-nats restart: unless-stopped command: ["-c", "/etc/nats/nats.conf"] volumes: - ./nats.conf:/etc/nats/nats.conf:ro # ํ˜ธ์ŠคํŠธ ์ƒ๋Œ€ ๊ฒฝ๋กœ - nats-data:/data # ๋„ค์ž„๋“œ ๋ณผ๋ฅจ ports: - "1883:1883" # MQTT 3.1.1 (ํ‰๋ฉด A: MAM) - "4222:4222" # NATS - "8222:8222" # HTTP ๋ชจ๋‹ˆํ„ฐ๋ง - "8080:8080" # WebSocket (ํ‰๋ฉด B) volumes: nats-data: ``` ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ `nats.conf` ๋Š” `store_dir: "/data"` ๋ฅผ ์”๋‹ˆ๋‹ค(**์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ๋Š” ์œ ํšจ** โ€” ํ˜ธ์ŠคํŠธ ๋ฃจํŠธ์™€ ๋ฌด๊ด€). > โš ๏ธ ๋ฌธ์„œ์— ๋ช…์‹œํ•  ๊ฒ€์ฆ ํฌ์ธํŠธ: ๋„ค์ž„๋“œ ๋ณผ๋ฅจ์˜ ์†Œ์œ ๊ถŒ์ด ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ์‚ฌ์šฉ์ž์™€ ๋งž์ง€ ์•Š์œผ๋ฉด JetStream ์ด ๊ธฐ๋™์— ์‹คํŒจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. **๊ธฐ๋™ ์งํ›„ `curl -s localhost:8222/jsz` ๋กœ JetStream ํ™œ์„ฑ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜๋“œ์‹œ ํ™•์ธ**ํ•˜๋„๋ก ์ ˆ์ฐจ์— ๋„ฃ์Šต๋‹ˆ๋‹ค. (์ด ํ™•์ธ์€ ยง3 A-3 Step 1 ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์ณ์ง‘๋‹ˆ๋‹ค.) --- ## 3. C3 ํŒ์ • โ€” ๊ธฐ์กด ์กฐํ•ญ์˜ ๊ตฌ์ฒดํ™” (์ฑ„ํƒ) Rev.1 ยง5.5 ๋Š” ์ด๋ฏธ ๋‹ค์Œ์„ ๋ช…์‹œํ–ˆ์Šต๋‹ˆ๋‹ค: > **๊ฐ€๋“œ ๊ตฌํ˜„ ์ฃผ์˜**: ์ •๊ทœ์‹์ด ์ฝ”๋“œ ๋ธ”๋ก ๋ฐ–์˜ ์‚ฐ๋ฌธ๊นŒ์ง€ ์žก์œผ๋ฉด ์˜คํƒ์ด ๋‚ฉ๋‹ˆ๋‹ค. **ํŽœ์Šค(```) ์•ˆ ๋ธ”๋ก์œผ๋กœ ์Šค์ฝ”ํ”„๋ฅผ ํ•œ์ •**ํ•˜๊ณ , G-D1 ์€ `mqtt_common` ์„ import ํ•ด ์‹ค์ œ ์ง‘ํ•ฉ๊ณผ ๋Œ€์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ C3 ์€ ์‹ ๊ทœ ๋ฐœ๊ฒฌ์ด ์•„๋‹ˆ๋ผ **๋™์ผ ์กฐํ•ญ์˜ ์žฌํ™•์ธ**์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ Challenge ๊ฐ€ ํŠน์ •ํ•œ **๊ตฌ์ฒด์  ์ถฉ๋Œ ์‚ฌ๋ก€๋Š” ์œ ํšจํ•œ ๊ธฐ์—ฌ**์ž…๋‹ˆ๋‹ค โ€” Rev.1 ยง6 ์€ `-m 1883` ์— ๋Œ€ํ•ด *"๊ธฐ์กด ์•ˆ๋‚ด๋Š” ์˜ค๋ฅ˜์˜€๋‹ค"๋Š” ์ •์ • ๊ฐ์ฃผ*๋ฅผ ๊ถŒ๊ณ ํ–ˆ๊ณ , Creator ๊ฐ€ `MAM_MQTT_*` ์— ๋Œ€ํ•ด์„œ๋„ ๊ฐ™์€ ๊ฐ์ฃผ๋ฅผ ์“ฐ๋ฉด **G-D2 ๊ฐ€ ์ž๊ธฐ ๋ฌธ์„œ์˜ ์ •์ • ์„ค๋ช…์— ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค**. ์ด ์ƒํ˜ธ์ž‘์šฉ์„ Rev.1 ์€ ์งš์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ### 3.1 ์ฑ„ํƒ โ€” G-D2 ์ŠคํŽ™ ํ™•์ • - **ํŒ์ • ๋Œ€์ƒ**: ` ```bash `, ` ```conf `, ` ```yaml ` ๋ฐ `.mam.env` ๋ธ”๋ก **์•ˆ์ชฝ๋งŒ**. - **ํŒ์ • ์ œ์™ธ**: ์‚ฐ๋ฌธ, `> [!NOTE]` ์ธ์šฉ, ํ‘œ, ๊ฐ์ฃผ โ€” ์ฆ‰ **์ •์ • ๊ฐ์ฃผ๋Š” ์ž์œ ๋กญ๊ฒŒ ์ž‘์„ฑ ๊ฐ€๋Šฅ**. - **๊ตฌํ˜„**: ํŒŒ์ผ ์ „์ฒด `re.search` ๊ธˆ์ง€. ํŽœ์Šค ํŒŒ์‹ฑ ํ›„ ๋ธ”๋ก ๋ณธ๋ฌธ์— ๋Œ€ํ•ด์„œ๋งŒ `MAM_MQTT_` ๋ถ€์žฌ๋ฅผ ๋‹จ์–ธ. - **์ž๊ธฐ๊ฒ€์ฆ**: ๊ฐ€๋“œ ์ž์ฒด๊ฐ€ ์Šค์ฝ”ํ•‘์„ ์ง€ํ‚ค๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด, **ํ…Œ์ŠคํŠธ๊ฐ€ "์‚ฐ๋ฌธ์— `MAM_MQTT_` ๋ฅผ ํฌํ•จํ•œ ์ž„์‹œ ๋ฌธ์„œ"๋ฅผ ๋งŒ๋“ค์–ด ํ†ต๊ณผํ•จ์„ ํ•จ๊ป˜ ๋‹จ์–ธ**ํ•ฉ๋‹ˆ๋‹ค(์˜คํƒ ๋ฐฉ์ง€ ํšŒ๊ท€). --- ## 4. ์‹ ์„ค โ€” G-D4 (C1-b ๊ฐ€ ๋“œ๋Ÿฌ๋‚ธ ๊ตฌ์กฐ์  ๊ฒฐํ•จ) E-1ยทE-2ยทE-3 ์™€ C1-b ๋Š” ๋ชจ๋‘ **"๋ฌธ์„œ์— ์‹ค๋ฆฐ ๋ช…๋ น์ด ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค"** ๋Š” ๋‹จ์ผ ์›์ธ์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. G-D1~G-D3 ๋Š” *ํŠน์ • ๋ฌธ์ž์—ด*์„ ๊ฐ์‹œํ•  ๋ฟ ์ด ์›์ธ์„ ๋ง‰์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. | ID | ๊ฐ€๋“œ | ๊ฒ€์ฆ ๋ฐฉ์‹ | |---|---|---| | **G-D4** | `PRIVATE_SERVER.md` ยง6 ์˜ ๊ฒ€์ฆ ์ ˆ์ฐจ์— ๋“ฑ์žฅํ•˜๋Š” `registry.py` / `publish_event.py` ํ˜ธ์ถœ์˜ **์ธ์ž ์ด๋ฆ„์ด ์‹ค์ œ argparse ํŒŒ์„œ์— ์กด์žฌ**ํ•  ๊ฒƒ | ๋ฌธ์„œ์—์„œ ๋ช…๋ น์„ ์ถ”์ถœ โ†’ ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ์˜ `_build_parser()` ๋ฅผ import โ†’ ๊ฐ ํ”Œ๋ž˜๊ทธ๊ฐ€ ํŒŒ์„œ์— ๋“ฑ๋ก๋˜์–ด ์žˆ๋Š”์ง€ ๋Œ€์กฐ. **`--job-id` ๊ฐ™์€ ์œ ๋ น ์ธ์ž๋ฅผ ์ฆ‰์‹œ ๊ฒ€์ถœ** | **Mutation**: ๋ฌธ์„œ์˜ `--job` ์„ `--job-id` ๋กœ ๋˜๋Œ๋ฆฌ๋ฉด FAIL ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. > ๊ตฌํ˜„ ์ฃผ์˜: ์‹ค์ œ๋กœ ๋ช…๋ น์„ **์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**(๋ธŒ๋กœ์ปคยท๋„คํŠธ์›Œํฌ ์˜์กด). ํŒŒ์„œ ๋Œ€์กฐ๋งŒ์œผ๋กœ C1-b ์œ ํ˜•์€ ์ „๋ถ€ ์žกํž™๋‹ˆ๋‹ค. **ํ…Œ์ŠคํŠธ ์ฆ๋ถ„ ์ „๋ง ๊ฐฑ์‹ **: 276 โ†’ **286**(Track 0 G-1~G-10) โ†’ **290**(G-D1~G-D4) โ†’ **291**(Track 2 G-11). --- ## 5. Phase A โ€” `PRIVATE_SERVER.md` ๊ต์ • (Rev.2 ํ™•์ •๋ณธ) Rev.1 ์—์„œ ๋ฐœ๊ฒฌํ•œ E-1~E-4 ๋Š” ํŒ์ • ๋ณ€๊ฒฝ ์—†์ด ์œ ์ง€๋˜๋ฉฐ, C1ยทC2 ๋ฅผ ๋ฐ˜์˜ํ•ด A-2ยทA-3 ์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. | ํ•ญ๋ชฉ | ๋‚ด์šฉ | Rev.2 ๋ณ€๊ฒฝ | |---|---|---| | **A-1** (E-1) | ยง5 ์˜ `MAM_MQTT_*` โ†’ `MQTT_BROKER`/`MQTT_PORT`/`MQTT_TLS`/`MQTT_USERNAME`/`MQTT_PASSWORD` + `MQTT_CA_CERTS`/`MQTT_CERTFILE`/`MQTT_KEYFILE` ์ถ”๊ฐ€. `.mam.env:39-64` ํ…œํ”Œ๋ฆฟ๊ณผ 1:1 ์ •๋ ฌ. OS ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์šฐ์„ ์ˆœ์œ„ 1์ค„ ๋ช…์‹œ | ๋ถˆ๋ณ€ | | **A-2** (E-2) | `-m 1883` **3๊ฐœ์†Œ ์ „๋Ÿ‰ ์ œ๊ฑฐ**(ยง4.1 ๋ฐฉ๋ฒ• AยทB, ยง7 Phase 2), `mqtt { port: 1883 }` ์„ค์ • ๋ธ”๋ก + `-c` ๋„์ž…, `8080` ๋…ธ์ถœ, Compose ํฌํŠธ ์ฃผ์„ ์ •์ •, `max_file` ์ƒํ•œ | ๐Ÿ”„ **๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์œผ๋กœ ์ „ํ™˜**(ยง2.1). ๋„ค์ดํ‹ฐ๋ธŒ `~/.config/nats/nats.conf` + `~/.local/share/nats/data`, Docker `./nats.conf` + ๋„ค์ž„๋“œ ๋ณผ๋ฅจ | | **A-3** (E-3ยทE-4) | ยง6 ์„ 4๋‹จ๊ณ„ ๊ฒ€์ฆ์œผ๋กœ ์žฌ์ž‘์„ฑ | ๐Ÿ”„ **Step 2 ๋ช…๋ น์„ ยง1.4 ํ™•์ •๋ณธ์œผ๋กœ ๊ต์ฒด**(ID ์บก์ฒ˜ยท`--registry-dir` ์œ„์น˜ยท์ •๋ฆฌ ๋‹จ๊ณ„). Step 1 ์— **`/jsz` JetStream ํ™•์ธ** ์ถ”๊ฐ€(ยง2.1 ๋‹จ์„œ) | | **A-4** | ยง6 Step 2 ์˜ "๊ฐœ์ธ ๋ธŒ๋กœ์ปค ํ™˜๊ฒฝ์—์„œ๋„ 100% ํ†ต๊ณผ" โ†’ "๋ธŒ๋กœ์ปค์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ํ†ต๊ณผ, ์—ฐ๋™ ๊ฒ€์ฆ์€ Step 1~3 ๋‹ด๋‹น". ํ…Œ์ŠคํŠธ ๊ฑด์ˆ˜ ๊ณ ์ • ํ‘œ๊ธฐ ํšŒํ”ผ | ๋ถˆ๋ณ€ | **ยง6 ์ตœ์ข… 4๋‹จ๊ณ„** | Step | ๋‚ด์šฉ | ํ†ต๊ณผ ๊ธฐ์ค€ | ๊ฒ€์ถœ ๋Œ€์ƒ | |---|---|---|---| | 1 | `curl -s http://:8222/varz` (MQTT ๋ฆฌ์Šค๋„ˆ) + `/jsz` (JetStream) | ๋‘˜ ๋‹ค ํ™œ์„ฑ ๋ณด๊ณ  | **E-2**, ๋ณผ๋ฅจ ์†Œ์œ ๊ถŒ ๋ฌธ์ œ | | 2 | ยง1.4 ์˜ ์žก ๋“ฑ๋ก โ†’ ๋ฐœํ–‰ | **rc=0** | **E-3**, C1 | | 3 | ์ ‘์† ๋Œ€์ƒ ๋‹จ์–ธ โ€” ๋กœ๊ทธ์— ๊ฐœ์ธ ์„œ๋ฒ„ IP, `broker.hivemq.com` **๋ถ€์žฌ** | ๋‹จ์–ธ ์„ฑ๋ฆฝ | **E-1** | | 4 | `pytest tests/ -q` + "๋ธŒ๋กœ์ปค ๋ฌด๊ด€ ๊ฒ€์ฆ" ๋ช…์‹œ | ๋ฒ ์ด์Šค๋ผ์ธ ํ†ต๊ณผ | (E-4 ์˜คํ•ด ๋ฐฉ์ง€) | --- ## 6. Phase B โ€” ๋‹ค๋Šฅ์„ฑ ์ ˆ (Rev.1 ๋Œ€๋น„ ๋ถˆ๋ณ€) ยง4 ์™€ ยง5 ์‚ฌ์ด์— ์‹ ์„ค. **์„ค๊ณ„ ๊ฒฐ์ • "ํ•˜๋‚˜์˜ ์„œ๋ฒ„, ๋‘ ๊ฐœ์˜ ์†Œ๋น„ ํ‰๋ฉด"**(Rev.1 ยง2)์€ Challenge ๊ฐ€ ์ „๋ฉด ์Šน์ธํ–ˆ์œผ๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. | ์†Œ์ ˆ | ๋‚ด์šฉ | ํ•„์ˆ˜ ์ œ์•ฝ | |---|---|---| | 5.1 ๋‘ ์†Œ๋น„ ํ‰๋ฉด | ํ‰๋ฉด A(MAM/MQTT, ๋ณ€๊ฒฝ ์—†์Œ) vs ํ‰๋ฉด B(NATSยทWSยทKVยทObject). **"๋‹ค๋Šฅ์„ฑ์€ ์ด๊ด€ํ•  ์ด์œ ๊ฐ€ ์•„๋‹ˆ๋ผ ์ด๊ด€ํ•˜์ง€ ์•Š๊ณ ๋„ ์–ป๋Š” ์ด๋“"** ์„ ์ฒซ ๋ฌธ์žฅ์œผ๋กœ | `NATS_REPORT.md` ์ •ํ•ฉ์„ฑ ์ž๊ธฐ์„ ์–ธ | | 5.2 ๊ต์ฐจ ํ”„๋กœํ† ์ฝœ ๋ธŒ๋ฆฌ์ง• | MQTT `python/mqtt/jobs//events` โ†” NATS `python.mqtt.jobs..events`. MAM ์ฝ”๋“œ 0์ค„๋กœ ๋Œ€์‹œ๋ณด๋“œ ๋ถ€์ฐฉ | โ‘  **๋™์ผ ๊ณ„์ • ๋‚ด์—์„œ๋งŒ** โ‘ก ํ† ํ”ฝ ๋ ˆ๋ฒจ์— `.` ๊ธˆ์ง€(MAM์€ hex๋ผ ์•ˆ์ „) | | 5.3 JetStream ๋ฆฌํ”Œ๋ ˆ์ด | `python.mqtt.jobs.>` ์บก์ฒ˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์‚ฌํ›„ ์žฌ์ƒ | โ‘  ์˜ตํŠธ์ธ โ‘ก `$MQTT_*` ๋‚ด๋ถ€ ์ŠคํŠธ๋ฆผ๊ณผ ๋ณ„๊ฐœ โ‘ข **`max_age`/`max_bytes` ํ•„์ˆ˜** | | 5.4 KV / Object Store | ํ™ˆ๋žฉ ์„ค์ •ยทํ”ผ์ฒ˜ํ”Œ๋ž˜๊ทธยท์‚ฐ์ถœ๋ฌผ ์ €์žฅ | **MAM ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ KV๋กœ ๋Œ€์ฒด ๊ธˆ์ง€**(`wait_for_job` ํด๋ง ๊ณ„์•ฝ) | | 5.5 ๋ฉ€ํ‹ฐํ…Œ๋„ŒํŠธ ๊ณ„์ • | `MAM`/`HOME` ๊ณ„์ • ๋ถ„๋ฆฌ, ๊ณ„์ •๋ณ„ ์ฟผํ„ฐยทsubject ๊ถŒํ•œ โ†’ A-2 ACL ์ถฉ์กฑ | โ‘  **MQTT ์ ‘์† ๊ณ„์ •์€ JetStream ํ™œ์„ฑ ํ•„์ˆ˜** โ‘ก ๊ฒฉ๋ฆฌโ†”๊ด€์ธก ์ƒ์ถฉ๊ณผ ๊ถŒ๊ณ  ๋ฐฐ์น˜(Rev.1 ยง2.1) | | 5.6 ์šด์˜ ์ด์  | ๋‹จ์ผ ์ •์  ๋ฐ”์ด๋„ˆ๋ฆฌ, `/varz`ยท`/jsz`, ์ปจํ…Œ์ด๋„ˆ 1๊ฐœ | โ€” | **์„œ์ˆ  ์›์น™ 3๊ฐ€์ง€ ์œ ์ง€**: โ‘  ๊ธฐ๋Šฅ๋งˆ๋‹ค "MAM์— ์“ฐ๋Š”๊ฐ€" ๋ช…์‹œ โ‘ก Track 1 ์ด์ „์ด๋ฏ€๋กœ **๋ฏธ๊ฒ€์ฆ ํ•ญ๋ชฉ์€ ํ™•์ •ํ˜• ๊ธˆ์ง€**(ํŠนํžˆ S-3 retained) โ‘ข ์ œ์•ฝ์„ ์žฅ์ ๊ณผ ๊ฐ™์€ ๋น„์ค‘์œผ๋กœ ๊ธฐ์ˆ . --- ## 7. Phase C โ€” `implementation_plan.md` (Rev.1 ๊ตฌ์กฐ ์œ ์ง€ + ๊ฐฑ์‹ ) **ํŒŒ์ผ๋ช…**: ๋ธŒ๋ฆฌํ•‘๋Œ€๋กœ `implementation_plan.md` ๋กœ ์ง„ํ–‰ํ•˜๋˜, ์ €์žฅ์†Œ ๋Œ€๋ฌธ์ž ๊ทœ์•ฝ(`README.md`ยท`NATS_REPORT.md`ยท`PRIVATE_SERVER.md` ๋“ฑ)๊ณผ์˜ ๋ถˆ์ผ์น˜๋ฅผ Creator ๊ฐ€ 1์ค„ ํ™•์ธ๋ฐ›์Šต๋‹ˆ๋‹ค. Challenge ๋„ ์ด ํ•ญ๋ชฉ์€ ์ด์˜ ์—†์ด ํ†ต๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. **๋งˆ์ผ์Šคํ†ค (M0 ๊ฒŒ์ดํŠธ๋งŒ ๊ฐฑ์‹ )** | M | ์ด๋ฆ„ | DoD | ๊ฒŒ์ดํŠธ | |---|---|---|---| | **M0** | ๋ฌธ์„œ ์ •ํ•ฉ์„ฑ | E-1~E-4 ๊ต์ • + ๋‹ค๋Šฅ์„ฑ ์ ˆ + ๋กœ๋“œ๋งต | ๐Ÿ”„ **G-D1~G-D4** green (G-D4 ์‹ ์„ค) | | **M1** | ๋‚ด๊ฒฐํ•จ์„ฑ (Track 0) | B-14ยทB-15, **286 passed** | G-1~G-10 + mutation ์ „๊ฑด FAIL ํ™•์ธ | | **M2** | ๋ธŒ๋กœ์ปค ์‹ค์ฆ (Track 1) | ๊ฒฉ๋ฆฌ ํด๋ก  S-1~S-9 | **S-3(retained) ํ†ต๊ณผ** โ† ๋ฏธํ†ต๊ณผ ์‹œ mosquitto ๋ถ„๊ธฐ | | **M3** | ๋ณด์•ˆ ์ข…๊ฒฐ (Track 2) | A-2 ํ•ด์†Œ, B-16 ์™„๊ฒฐ | ์ง€๋ฌธ ํ† ํ”ฝ ์ „ํ™˜ ํ™•์ธ **ํ›„** legacy ๊ตฌ๋… ์ œ๊ฑฐ | | **M4** | ๋™๊ธฐํ™” (Track 3) | ๋ฌธ์„œยท`.mam.env`ยท`deploy/*` ์ •ํ•ฉ | ์ „์ฒด ์Šค์œ„ํŠธ green | **์˜์กด์„ฑ**: `M0 โ†’ M1 โ†’ M2 โ†’ M3 โ†’ M4` (์ง๋ ฌ). **M0 ์˜ A-1 ์€ M2 ์˜ ์„ ํ–‰์กฐ๊ฑด์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค** โ€” ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ด๋ฆ„์ด ํ‹€๋ฆฐ ์ฑ„ ์ŠคํŒŒ์ดํฌ๋ฅผ ๋Œ๋ฆฌ๋ฉด **๊ณต๊ฐœ ๋ธŒ๋กœ์ปค์— ๋ถ™์€ ๊ฒฐ๊ณผ๋ฅผ ๊ฐœ์ธ ๋ธŒ๋กœ์ปค ์„ฑ๊ณต์œผ๋กœ ์˜ค๋…**ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ •์„ ๋กœ๋“œ๋งต์— ๊ฒฝ๊ณ ๋กœ ๋ช…์‹œ. **๋ณธ๋ฌธ ๊ตฌ์„ฑ** (Rev.1 ยง5.2 ์œ ์ง€): ๊ฐœ์š” / ๋งˆ์ผ์Šคํ†ค / Track 0(3-Step ์ˆœ์„œ ์˜์กด์„ฑ + G-1~G-10 + ํ†ตํ•ฉ ๊ฒ€์ฆ) / Track 1(S-1~S-9, ๊ฒฉ๋ฆฌ ํด๋ก  ์›์น™) / Track 2(๋ฌด์กฐ๊ฑด ํ† ํฐ ๋ฐœ๊ธ‰ G-11, ์ง€๋ฌธ ํ† ํ”ฝ 3๋‹จ๊ณ„ ์ˆœ์„œ) / Track 3(๋ฌธ์„œ ๋™๊ธฐํ™”ํ‘œ โ€” **`PRIVATE_SERVER.md` ์ž์‹ ๋„ ๋Œ€์ƒ**) / ์˜์กด์„ฑยท๋กค๋ฐฑ / ์ง„ํ–‰ ์ถ”์ ํ‘œ. **์—ญํ•  ๋ถ„๋ฆฌ ๋ช…์‹œ**: `IMPROVEMENTS.md` = ๊ณผ์ œ ๋ฐฑ๋กœ๊ทธ(๋ฌด์—‡์„/์™œ), `implementation_plan.md` = ์‹คํ–‰ ๋กœ๋“œ๋งต(์–ธ์ œ/์–ด๋–ค ์ˆœ์„œ๋กœ/์™„๋ฃŒ ํŒ์ •). ์ƒํ˜ธ ๋งํฌํ•˜๋˜ ์‚ฌ์‹ค์„ ๋ณต์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. --- ## 8. ์œ„ํ—˜ ยท ๋น„-๋ชฉํ‘œ (Rev.2 ๊ฐฑ์‹ ๋ถ„) | ์œ„ํ—˜ | ์™„ํ™” | ๋น„๊ณ  | |---|---|---| | ๋ฌธ์„œ์— ์‹ค๋ฆฐ ๋ช…๋ น์ด ๋˜ ๊ฒ€์ฆ ์—†์ด ๋“ค์–ด๊ฐ | **G-D4** ๊ฐ€ ํŒŒ์„œ ๋Œ€์กฐ๋กœ ์ฐจ๋‹จ | ๐Ÿ†• C1-b ๋Œ€์‘ | | macOS ์‚ฌ์šฉ์ž๊ฐ€ ยง4.1 ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋‹ค ์‹คํŒจ | ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ๊ธฐ๋ณธ๊ฐ’ + `/jsz` ํ™•์ธ ์ ˆ์ฐจ | ๐Ÿ†• C2 ๋Œ€์‘ | | ์ •์ • ๊ฐ์ฃผ๊ฐ€ G-D2 ์— ๊ฑธ๋ฆผ | ํŽœ์Šค ์Šค์ฝ”ํ•‘ ํ™•์ • + ์˜คํƒ ๋ฐฉ์ง€ ํšŒ๊ท€ ๋‹จ์–ธ | ๐Ÿ†• C3 ๋Œ€์‘ | | ๋‹ค๋Šฅ์„ฑ ์ ˆ์ด `NATS_REPORT.md` ์™€ ๋ชจ์ˆœ๋˜๊ฒŒ ์ฝํž˜ | ํ‰๋ฉด ๋ถ„๋ฆฌ๋ฅผ ์ ˆ ๋„์ž…๋ถ€ ์ฒซ ๋ฌธ์žฅ์œผ๋กœ ๊ณ ์ • | ๋ถˆ๋ณ€ | | Track 1 ์ด์ „ ํ™•์ •ํ˜• ์„œ์ˆ  | ๋ฏธ๊ฒ€์ฆ "๊ฒ€์ฆ ๋Œ€์ƒ" ํ‘œ๊ธฐ, ํŠนํžˆ S-3 | ๋ถˆ๋ณ€ | | ํ…Œ์ŠคํŠธ ์žก ์ž”์กด์œผ๋กœ `--wait-any` ์˜ค์—ผ | ยง1.4 Step 4 ์ •๋ฆฌ ๋ช…๋ น ํ•„์ˆ˜ํ™” | ๐Ÿ†• C1-c | **๋น„-๋ชฉํ‘œ** (๋ถˆ๋ณ€): ์ €์žฅ์†Œ ์ฝ”๋“œ ์ˆ˜์ • / Track 0~3 ์‹ค์ œ ๊ตฌํ˜„ / `nats-py` ๋„์ž… / ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ KV ๋Œ€์ฒด / client_id ์•ˆ์ •ํ™” / ์‹ค์ œ ๋ธŒ๋กœ์ปค ๊ธฐ๋™ ๋ฐ S-1~S-9 ์‹คํ–‰. --- ## 9. ์‚ฐ์ถœ๋ฌผ ๋ฐ Reviewer ํ™•์ธ ์š”์ฒญ **Creator ์‚ฐ์ถœ๋ฌผ 2์ข…** 1. `PRIVATE_SERVER.md` โ€” Phase A ๊ต์ •(ยง1.4 ๋ช…๋ นยทยง2.1 ๊ฒฝ๋กœ ํฌํ•จ) + Phase B ์‹ ์„ค ยง5 + ยง7 Phase 2 ๋ช…๋ น ๋™์‹œ ๊ต์ • 2. `implementation_plan.md` โ€” M0~M4, 4ํŠธ๋ž™ ๋ณธ๋ฌธ, ์˜์กด์„ฑ/๋กค๋ฐฑ, ์ง„ํ–‰ ์ถ”์ ํ‘œ 3. (M0 ๊ฒŒ์ดํŠธ) `tests/test_deploy_freshness.py` ์— **G-D1~G-D4** โ€” ๋‹จ, ์ด๋Š” **Creator ์˜ ๊ตฌํ˜„ ๋ฒ”์œ„**์ด๋ฉฐ ๋ณธ ๊ณ„ํš์„œ๋Š” ์ŠคํŽ™๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค **Reviewer ์žฌํ˜„ ๊ฒ€์ฆ ์š”์ฒญ 4๊ฑด** 1. **C1-b ๋ฐ˜์ฆ**: `registry.py โ€ฆ register --job-id X --prompt Y` โ†’ `error: unrecognized arguments: --job-id X` ์ธ๊ฐ€ 2. **C1-c**: `--registry-dir` ์„ `register` **๋’ค**์— ๋‘๋ฉด ์˜ค๋ฅ˜์ธ๊ฐ€ / `register` ๊ฐ€ `status:"pending"` ์„ ๋งŒ๋“ค๊ณ  `--wait-any` ๊ฐ€ ์ด๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š”๊ฐ€ 3. **C2**: `mkdir -p /data` โ†’ `Read-only file system` ์ด๋ฉฐ `/` ๊ฐ€ `sealed โ€ฆ read-only` ์ธ๊ฐ€ 4. **C3**: Rev.1 ยง5.5 ์— ํŽœ์Šค ์Šค์ฝ”ํ•‘ ์กฐํ•ญ์ด ์ด๋ฏธ ์žˆ์—ˆ๋Š”๊ฐ€ (๊ธฐ์—ฌ์˜ ๋ฒ”์œ„ ํ™•์ธ) **๋ฏธํ•ด๊ฒฐ ํ™•์ธ ์š”์ฒญ 1๊ฑด**: `implementation_plan.md` vs `IMPLEMENTATION_PLAN.md` ํŒŒ์ผ๋ช… โ€” ๊ธฐ๋ณธ์€ ๋ธŒ๋ฆฌํ•‘๋Œ€๋กœ ์†Œ๋ฌธ์ž.