From 6b7198f73c60e32dd35576f2b1c9b4336853fd1b Mon Sep 17 00:00:00 2001 From: Godopu Date: Tue, 22 Sep 2026 00:38:10 +0900 Subject: [PATCH] release(v4.7.1): bump framework and eight skills to 4.7.1 in lockstep; archive PR #32 merge-side reviews Issue #25: a promoted plan is reused only with --plan-file; the implicit newest-plan load is gone in both runners, and an empty planner report no longer passes silently. VERSIONS.md carries the entry; the four merge-side review reports and their identity sidecars (base 6fc9194 -> head 1e82651, evidence review-tree) are archived under .agents/reports//. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff --- .../report-293e905f.identity.json | 14 ++ .../report-293e905f.md | 139 ++++++++++++++++++ .../report-08808795.identity.json | 14 ++ .../report-08808795.md | 32 ++++ .../report-41f07cde.identity.json | 14 ++ .../reviewer-agy-01/report-41f07cde.md | 113 ++++++++++++++ .../report-06fb4a9e.identity.json | 14 ++ .../reviewer-grok-01/report-06fb4a9e.md | 59 ++++++++ .agents/skills/lib.sh | 2 +- .agents/skills/lib_py/loop/eager.py | 2 +- .../skills/multi-agent-mux-create/SKILL.md | 2 +- .../multi-agent-mux-delegate-job/SKILL.md | 2 +- .agents/skills/multi-agent-mux-loop/SKILL.md | 2 +- .../skills/multi-agent-mux-monitor/SKILL.md | 2 +- .../multi-agent-mux-orc-onboard/SKILL.md | 2 +- .../skills/multi-agent-mux-resume/SKILL.md | 2 +- .../skills/multi-agent-mux-status/SKILL.md | 2 +- .agents/skills/multi-agent-mux-stop/SKILL.md | 2 +- BOOTSTRAP.ko.md | 2 +- BOOTSTRAP.md | 2 +- MESSAGING.md | 2 +- README.ko.md | 2 +- README.md | 2 +- VERSIONS.md | 38 +++-- 24 files changed, 441 insertions(+), 26 deletions(-) create mode 100644 .agents/reports/planner-reviewer-claude-01/report-293e905f.identity.json create mode 100644 .agents/reports/planner-reviewer-claude-01/report-293e905f.md create mode 100644 .agents/reports/planner-reviewer-codex-01/report-08808795.identity.json create mode 100644 .agents/reports/planner-reviewer-codex-01/report-08808795.md create mode 100644 .agents/reports/reviewer-agy-01/report-41f07cde.identity.json create mode 100644 .agents/reports/reviewer-agy-01/report-41f07cde.md create mode 100644 .agents/reports/reviewer-grok-01/report-06fb4a9e.identity.json create mode 100644 .agents/reports/reviewer-grok-01/report-06fb4a9e.md diff --git a/.agents/reports/planner-reviewer-claude-01/report-293e905f.identity.json b/.agents/reports/planner-reviewer-claude-01/report-293e905f.identity.json new file mode 100644 index 0000000..ccbd7cf --- /dev/null +++ b/.agents/reports/planner-reviewer-claude-01/report-293e905f.identity.json @@ -0,0 +1,14 @@ +{ + "loop_id": "loop-20260921T150212Z-97d845", + "base_sha": "6fc9194f896eb2e13e123b8ebe7a9089b629764d", + "head_sha": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "tree_sha": "4fd82ad1c2682d12c3f5114818f97291af28a032", + "review_commit": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "reviewer": "planner-reviewer-claude-01", + "job_id": "293e905f", + "verdict": "PASS", + "transport": "herdr", + "evidence": "review-tree", + "isolation": "worktree", + "verified_at": "2026-09-21T15:25:44Z" +} \ No newline at end of file diff --git a/.agents/reports/planner-reviewer-claude-01/report-293e905f.md b/.agents/reports/planner-reviewer-claude-01/report-293e905f.md new file mode 100644 index 0000000..8319fb8 --- /dev/null +++ b/.agents/reports/planner-reviewer-claude-01/report-293e905f.md @@ -0,0 +1,139 @@ +# ๐Ÿ” Review Report โ€” PR #32 ๋ณ‘ํ•ฉ ์ „ ๋…๋ฆฝ ๋ฆฌ๋ทฐ (job `293e905f`) + +- **Reviewer**: `planner-reviewer-claude-01` (role: planner,reviewer) ยท 2026-09-22 +- **๋Œ€์ƒ**: PR #32 `fix/issue-25` **@ `1e82651`**, base `main 6fc9194` (v4.7.0). 5์ปค๋ฐ‹, 4ํŒŒ์ผ `+486/โˆ’31`. +- **๊ฒ€์ฆ ๊ฒฝ๋กœ**: `/var/folders/.../T/mam-review/loop-20260921T150212Z-97d845/1` (๋ธŒ๋ฆฌํ”„๊ฐ€ ์ง€์ •ํ•œ ๋ฆฌ๋ทฐ ์›ŒํฌํŠธ๋ฆฌ). ์‹ค์ œ๋กœ ๊ฑฐ๊ธฐ์„œ๋งŒ ๊ฒ€์ฆํ–ˆ๋‹ค. +- **identity ํ™•์ธ**: ๊ฒ€์ฆ ๊ฒฝ๋กœ์˜ `HEAD = 1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd`, `HEAD^{tree} = 4fd82ad1c2682d12c3f5114818f97291af28a032` โ€” ๋ธŒ๋ฆฌํ”„์˜ `head`ยท`tree` ์™€ **์ผ์น˜**ํ•œ๋‹ค(ํ•ญ๋ชฉ 5 identity ๊ฐ€ ์‹ค์ œ๋กœ ์ž‘๋™ํ•จ์„ ์ด ์žก ์ž์ฒด๊ฐ€ ๋ณด์—ฌ์ค€๋‹ค). +- **์•ˆ์ „ ๊ทœ์น™ ์ค€์ˆ˜**: ๊ฒ€์ฆ ๊ฒฝ๋กœยท์†Œ์Šค ์›ŒํฌํŠธ๋ฆฌ(`multi-agent-mux-wt/pr-32`)ยท๋ณธ ์ฒดํฌ์•„์›ƒ(`main 6fc9194`) ๋ชจ๋‘ ์ˆ˜์ •ยท์ปค๋ฐ‹ยทcheckout ์—†์Œ. ์‹คํ—˜์€ ์ „๋ถ€ scratchpad ์ž„์‹œ ๋””๋ ‰ํ„ฐ๋ฆฌ(uuid4 ์ด๋ฆ„)์—์„œ ํ–ˆ๊ณ , pytest ๋Š” `--basetemp` ์„ ๊ฒ€์ฆ ๊ฒฝ๋กœ ๋ฐ–์œผ๋กœ ์ฃผ์—ˆ๋‹ค. ์‹ค์ œ `.mam`ยท๋ฐ๋ชฌยท์„ธ์…˜ ์กฐ์ž‘ ์—†์Œ, pushยทmergeยทPR ์ƒํƒœ ๋ณ€๊ฒฝ ์—†์Œ, purgeยทscrub ์‹คํ–‰ ์—†์Œ. + +## ๊ฒฐ๋ก  ์š”์•ฝ + +**๋ณ‘ํ•ฉ์„ ๋ง‰์„ ๊ฒฐํ•จ์€ ์—†๋‹ค.** ํ•ต์‹ฌ ๋ณ€๊ฒฝ(์•”๋ฌต์  ๊ณ„ํš์„œ ๋กœ๋“œ ์ œ๊ฑฐ, `--plan-file` ๋ช…์‹œ ์žฌ์‚ฌ์šฉ, ๋„ค ์ง€์  ๊ณตํ†ต ๊ณ„ํš ํ…์ŠคํŠธ ๊ฒ€์‚ฌ)์€ ์ฝ”๋“œยท๋ฌธ์„œยทํ…Œ์ŠคํŠธ๊ฐ€ ์ผ์น˜ํ•˜๋ฉฐ, ์ƒˆ ํ…Œ์ŠคํŠธ 17๊ฑด ์ค‘ **13๊ฑด์ด ์ˆ˜์ • ์ „ ์†Œ์Šค์—์„œ๋Š” ์‹คํŒจ**ํ•œ๋‹ค(์ง์ ‘ ํ™•์ธ). ๋น„์ฐจ๋‹จ ์ง€์  3๊ฑด(E1โ€“E3)์„ ๋‚จ๊ธด๋‹ค. + +## 1. ์•”๋ฌต์  ๋กœ๋“œ ์ œ๊ฑฐ (ํ•ญ๋ชฉ 1) + +| ํ™•์ธ | ๊ฒฐ๊ณผ | +|---|---| +| Python ๋Ÿฌ๋„ˆ | `runner.py` ์—์„œ `glob` import ๊ฐ€ ์‚ฌ๋ผ์กŒ๊ณ , ๋‚จ์€ `glob` ์‚ฌ์šฉ์ฒ˜๋Š” `find_report` ์˜ `report-final.md` ํƒ์ƒ‰(`:568`) ํ•˜๋‚˜๋ฟ์ด๋‹ค. `.agents/reports//plan-*.md` ๋ฅผ ์ฝ๋Š” ์ฝ”๋“œ๊ฐ€ ์—†๋‹ค | +| ๋ ˆ๊ฑฐ์‹œ ์…ธ ๋Ÿฌ๋„ˆ | `run_loop.sh` ์˜ `EXISTING_PLAN_FILE`/`ls -t .../plan-*.md` ๋ธ”๋ก์ด ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ง€๊ณ  `log_info "No plan loaded; the Creator plans by itself."` ๋งŒ ๋‚จ์•˜๋‹ค | +| ๋‹ค๋ฅธ ๊ฒฝ๋กœ | ์ €์žฅ์†Œ ์ „์ฒด์—์„œ `plan-*.md` ๋ฅผ ์ฝ๋Š” ์ฝ”๋“œ๋Š” ์—†๋‹ค(์Šน๊ฒฉ ์ชฝ **์“ฐ๊ธฐ**๋งŒ `runner.py:1368-1372` ์— ๋‚จ๋Š”๋‹ค โ€” ์ •์ƒ) | +| planner ์ž๋™ ์„ ํƒ | `resolve_planner_session`(`run_loop.sh:386`)ยท`resolve_planner_session` ํŒŒ์ด์ฌ ๋Œ€์‘์€ ๋‚จ์•„ ์žˆ์œผ๋‚˜, ๊ทธ ๊ฒฐ๊ณผ๋Š” **plan ๋ชจ๋“œ์˜ ์œ„์ž„ ๋Œ€์ƒ๊ณผ ์Šน๊ฒฉ ๊ฒฝ๋กœ**์—๋งŒ ์“ฐ์ธ๋‹ค. ์ž๊ธฐ๊ณ„ํš ๋ชจ๋“œ์—์„œ planner ์ด๋ฆ„์œผ๋กœ ํŒŒ์ผ์„ ์ฐพ๋Š” ์ฝ”๋“œ๋Š” ์—†๋‹ค | + +## 2. `--plan-file` (ํ•ญ๋ชฉ 2) โ€” ์‹ค์ธก + +๊ฒ€์ฆ ๊ฒฝ๋กœ์˜ ๋Ÿฌ๋„ˆ๋ฅผ ์ž„์‹œ ์ œ์–ด ๋ฃจํŠธ(`WORKSPACE_ROOT=/ctl`)๋กœ ์ง์ ‘ ๋Œ๋ ค ํ™•์ธํ–ˆ๋‹ค. + +| ์ž…๋ ฅ | ๊ฒฐ๊ณผ | +|---|---| +| ์—†๋Š” ํŒŒ์ผ | `[โœ—] --plan-file <์ ˆ๋Œ€๊ฒฝ๋กœ>: not a readable file with plan text in it.` ยท **exit 1** | +| ๋นˆ ํŒŒ์ผ / ๊ณต๋ฐฑ๋งŒ ์žˆ๋Š” ํŒŒ์ผ | ๊ฐ™์€ ๋ฉ”์‹œ์ง€ ยท exit 1 | +| ๋””๋ ‰ํ„ฐ๋ฆฌ | ๊ฐ™์€ ๋ฉ”์‹œ์ง€ ยท exit 1 (`is_file()` ๋กœ ๊ฑธ๋ฆฐ๋‹ค) | +| ์ฝ๊ธฐ ๊ถŒํ•œ ์—†์Œ(`chmod 000`) | ๊ฐ™์€ ๋ฉ”์‹œ์ง€ ยท exit 1 (`OSError` โ†’ `None`) | +| `--plan` ๊ณผ ํ•จ๊ป˜ | `ERROR: --plan-file cannot be combined with --plan.` + ์‚ฌ์šฉ ์˜ˆ 2์ค„ ยท exit 1 | +| ์ƒ๋Œ€๊ฒฝ๋กœ | **์ œ์–ด ๋ฃจํŠธ ๊ธฐ์ค€**. ํ˜ธ์ถœ cwd(`/elsewhere`)์— `plans/p.md` ๊ฐ€ ์‹ค์ œ๋กœ ์žˆ์–ด๋„ ๋Ÿฌ๋„ˆ๋Š” `/plans/p.md` ๋ฅผ ์ฐพ๊ณ  ์‹คํŒจํ•œ๋‹ค โ€” #25 ์˜ "๋‹ค๋ฅธ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๋™๋ช… ํŒŒ์ผ์„ ์ง‘์–ด์˜ค๋Š”" ์‚ฌ๊ณ ๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ๋ง‰๋Š”๋‹ค | +| ๊ณต๋ฐฑ ์žˆ๋Š” ๊ฒฝ๋กœ(`my plans/p.md`, ์ƒ๋Œ€) | ์ •์ƒ ๋กœ๋“œ: `Using the plan given with --plan-file: /my plans/p.md (modified ... UTC)` (์…ธ์„ ๊ฑฐ์น˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ธ์šฉ ๋ฌธ์ œ ์—†์Œ) | +| ์ ˆ๋Œ€๊ฒฝ๋กœยท`~` | `Path.__truediv__` ๊ฐ€ ์ ˆ๋Œ€๊ฒฝ๋กœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  `expanduser()` ๊ฐ€ ์•ž์„œ ์ ์šฉ๋œ๋‹ค(P3d ๊ฐ€ ๊ณ ์ •) | +| `--review-only` ์™€ ํ•จ๊ป˜ | ๊ฒฝ๊ณ  ํ›„ ๋ฌด์‹œ(`log_warn`), `current_plan` ์„ ์ฑ„์šฐ์ง€ ์•Š๋Š”๋‹ค | +| ๋ ˆ๊ฑฐ์‹œ ์…ธ(`MAM_LOOP_PY=0`) | `ERROR: --worktree/--base/--review-only/--review-isolation/--remote-review/--plan-file require the Python loop (MAM_LOOP_PY=1)` ยท exit 1 โ€” **๋™๋“ฑ ๊ตฌํ˜„ ๋Œ€์‹  ๋ช…์‹œ์  ๊ฑฐ๋ถ€**์ด๋ฉฐ, ๊ธฐ๋ณธ ๊ฒฝ๋กœ(`MAM_LOOP_PY=1`)๋Š” `exec "$_py" -m lib_py.loop "${MAM_LOOP_ARGV[@]}"`(`run_loop.sh:262`)๋กœ ์›๋ณธ argv ๋ฅผ ๊ทธ๋Œ€๋กœ ๋„˜๊ธฐ๋ฏ€๋กœ ๊ณต๋ฐฑ ๊ฒฝ๋กœ๋„ ์•ˆ์ „ํ•˜๋‹ค | + +์ฝ๊ธฐ๊ฐ€ **์žก์„ ํ•˜๋‚˜๋„ ๋งŒ๋“ค๊ธฐ ์ „**(parse_args ๋‹จ๊ณ„)์— ๋๋‚˜๋Š” ๊ฒƒ๋„ ํ™•์ธํ–ˆ๋‹ค โ€” ์‹คํŒจ ์‹œ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์•„๋ฌด ํ”์ ์ด ์—†๋‹ค. + +## 3. ๊ณ„ํš ํ…์ŠคํŠธ ๊ฒ€์‚ฌ (ํ•ญ๋ชฉ 3) + +`_plan_text()`(`runner.py:303-317`)๊ฐ€ "์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ผ๋ฐ˜ ํŒŒ์ผ + ๊ณต๋ฐฑ ์ œ์™ธ ๋‚ด์šฉ ์žˆ์Œ"์„ ๋‹จ์ผ ํŒ์ •์œผ๋กœ ๋งŒ๋“ค๊ณ , **ํŒŒ์ด์ฌ ๋Ÿฌ๋„ˆ์˜ ๋„ค ์ง€์ ์ด ๋ชจ๋‘ ์ด๋ฅผ ์“ด๋‹ค**: `--plan-file`(`:265`), `--plan` ์ดˆ๊ธฐ ๊ณ„ํš์„œ(`:1025`), ๋…ผ์˜ ํ„ด refine(`:1054`), ๋ฆฌ๋ทฐ ์—์Šค์ปฌ๋ ˆ์ด์…˜ refine(`:1284`). + +- ๋นˆ ์ดˆ๊ธฐ ๊ณ„ํš์„œ โ†’ `log_error` ํ›„ **return 1**. ์ด๋•Œ ์ด๋ฏธ ๋งŒ๋“  ์žก์€ `release_guard`/์ •๋ฆฌ ๊ฒฝ๋กœ๊ฐ€ ๋‹ด๋‹นํ•˜๊ณ , ์ž๊ธฐ๊ณ„ํš์œผ๋กœ์˜ ์กฐ์šฉํ•œ ๊ฒฉํ•˜๊ฐ€ ์‚ฌ๋ผ์กŒ๋‹ค. +- ๋นˆ refine โ†’ ๊ฒฝ๊ณ  + **์ด์ „ ๊ณ„ํš ์œ ์ง€**. ๊ทธ๋ž˜์„œ "๊ฐฑ์‹ ๋œ ๋‹ค์Œ ๊ณ„ํš์„œ์— ์ž…๊ฐํ•˜์—ฌโ€ฆ" ํ”„๋กฌํ”„ํŠธ๊ฐ€ ๋นˆ ๊ณ„ํš์„ ์‹ฃ๋Š” ์ผ์ด ์—†๋‹ค. +- ์—์Šค์ปฌ๋ ˆ์ด์…˜ ๊ฒฝ๋กœ(`[ESCALATE: PLANNER]`)๋Š” `if self.plan_mode and complex_fix`(`:1275`)๋กœ **plan ๋ชจ๋“œ์—๋งŒ** ๊ฑธ๋ฆฐ๋‹ค. `--plan-file` ๋กœ ๊ณ„ํš์„ ์‹ค์€ ์‹คํ–‰์—์„œ ESCALATE ํŒ์ •์ด ๋‚˜์˜ค๋ฉด ์žฌ๊ณ„ํš ์—†์ด ์ผ๋ฐ˜ ์ˆ˜์ • ๋ผ์šด๋“œ๋กœ ๊ฐ„๋‹ค โ€” ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ ์ง์ ‘ ๊ตฌ๋™ํ•ด ํ™•์ธํ–ˆ๋‹ค(Planner ์œ„์ž„ 0๊ฑด, ์ˆ˜์ • ํ”„๋กฌํ”„ํŠธ๋Š” "๋ฆฌ๋ทฐ์–ด๋“ค์ด ์ง€์ ํ•œ ๋‹ค์Œ ํ”ผ๋“œ๋ฐฑโ€ฆ"). SKILL.md:31 ์˜ "์ˆ˜์ • ๋ผ์šด๋“œ์—๋Š” ๋ฆฌ๋ทฐ ํ”ผ๋“œ๋ฐฑ๋งŒ" ์„œ์ˆ ๊ณผ **์ผ์น˜**ํ•œ๋‹ค. ๋‹ค๋งŒ ์ด ๋™์ž‘ ์ž์ฒด๋Š” E2 ๋กœ ๋‚จ๊ธด๋‹ค. + +## 4. ์ฒดํฌํฌ์ธํŠธ (ํ•ญ๋ชฉ 4) + +`.mam/loop-checkpoint.json` ์˜ `current_plan` ์€ **์“ฐ๊ธฐ ์ „์šฉ**์ด๋‹ค. `checkpoint.load_checkpoint()` ๋Š” ์ •์˜๋˜์–ด ์žˆ์œผ๋‚˜ `runner.py` ์–ด๋””์—์„œ๋„ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค(`grep 'checkpoint\.'` โ†’ `save_checkpoint`ยท`remove_checkpoint` ๋ฟ). ๋”ฐ๋ผ์„œ ๋ณธ ์ฒดํฌ์•„์›ƒ ์ฒดํฌํฌ์ธํŠธ์— ๋‚จ์•„ ์žˆ๋Š” Issue #6 ๊ณ„ํš ํ…์ŠคํŠธ๊ฐ€ ๋‹ค์Œ ๋ฃจํ”„๋‚˜ ์žฌ๊ฐœ์—์„œ ๋˜์‚ด์•„๋‚  ๊ฒฝ๋กœ๋Š” ์—†๋‹ค. ๊ณ„ํš์€ ๋งค ์‹คํ–‰๋งˆ๋‹ค `--plan-file` ๋˜๋Š” `--plan` ์œผ๋กœ๋งŒ ๋“ค์–ด์˜จ๋‹ค. + +## 5. ์˜ต์…˜ ์—†์„ ๋•Œ์˜ ๋™์ž‘ ๋ณ€ํ™” (ํ•ญ๋ชฉ 5) + +- ์ž๊ธฐ๊ณ„ํš ํ”„๋กฌํ”„ํŠธ(`runner.py:1095`)์™€ ์Šน๊ฒฉ ๊ฒฝ๋กœ(`:1367` `if self.plan_mode and self.current_plan and self.plan_job_id`)๋Š” ๊ทธ๋Œ€๋กœ๋‹ค. ์ฆ‰ `--plan-file` ๋กœ ์‹ค์€ ๊ณ„ํš์„œ๋Š” **์Šน๊ฒฉ๋˜์ง€ ์•Š๋Š”๋‹ค**(์Šน๊ฒฉ์€ plan ๋ชจ๋“œ์˜ planner ์‚ฐ์ถœ๋ฌผ๋งŒ) โ€” ์˜ณ์€ ๊ตฌ๋ถ„์ด๋‹ค. +- ๋ฐ”๋€ ๊ฒƒ์€ "planner ๋ฆฌํฌํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ์ตœ์‹  plan-*.md ๋ฅผ ๋Œ์–ด์˜ค๋˜" ๋™์ž‘ ํ•˜๋‚˜๋ฟ์ด๋‹ค. ๊ทธ ์™ธ ํ”„๋กฌํ”„ํŠธ ๋ฌธ๊ตฌยท์˜ต์…˜ ๊ธฐ๋ณธ๊ฐ’ยท์ข…๋ฃŒ ์ฝ”๋“œ๋Š” ๋™์ผํ•˜๋‹ค. +- ๊ธฐ์กด ์Šค์œ„ํŠธ ์ •ํ•ฉ์€ ยง6 ์—์„œ ์‹ค์ธกํ–ˆ๋‹ค. + +## 6. ํ…Œ์ŠคํŠธ (ํ•ญ๋ชฉ 6) + +### 6-1. ๊ฒ€์ฆ ๊ฒฝ๋กœ์—์„œ์˜ ์‹คํ–‰ + +``` +cd <๊ฒ€์ฆ ๊ฒฝ๋กœ> && PYTHONDONTWRITEBYTECODE=1 <์ œ์–ด ๋ฃจํŠธ .venv/bin/python> -m pytest -p no:cacheprovider -q -rfEs \ + --basetemp=<๊ฒ€์ฆ ๊ฒฝ๋กœ ๋ฐ–> tests/test_issue25_plan_reuse.py tests/test_loop_cli.py tests/test_issue5_phase3_loop.py \ + tests/test_issue21_loop_b.py tests/test_issue21_phase2_loop_a.py tests/test_issue21_acceptance.py +โ†’ 2 failed, 108 passed in 220.98s (skipped 0) +``` + +**์‹คํŒจ 2๊ฑด์€ PR ํšŒ๊ท€๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฆฌ๋ทฐ ์›ŒํฌํŠธ๋ฆฌ์— `.venv` ๊ฐ€ ์—†์–ด์„œ ์ƒ๊ธด ํ™˜๊ฒฝ ๋ฌธ์ œ๋‹ค.** + +| ์‹คํŒจ | ์›์ธ | ํ™•์ธ | +|---|---|---| +| `test_loop_cli.py::test_creator_parses_and_reaches_session_check` | `run_loop.sh` ๋ฅผ ํ•˜์œ„ ํ”„๋กœ์„ธ์Šค๋กœ ๋„์šฐ๋Š”๋ฐ, `REPO_ROOT`(= ๊ฒ€์ฆ ๊ฒฝ๋กœ)์— `.venv` ๊ฐ€ ์—†์–ด `_py` ๊ฐ€ ์‹œ์Šคํ…œ python ์œผ๋กœ ๋–จ์–ด์ง€๊ณ  `RuntimeError: Failed to eager load lib_py.loop.autocomplete: No module named 'paho'` ๋กœ ์ฃฝ๋Š”๋‹ค(`run_loop.sh:253`) | `AGENT_PYTHON_BIN=<์ œ์–ด ๋ฃจํŠธ .venv/bin/python>` ๋งŒ ์ฃผ๊ณ  ๋‘˜์„ ๋‹ค์‹œ ๋Œ๋ฆฌ๋ฉด **2 passed in 0.34s** | +| `test_issue5_phase3_loop.py::test_p3_02_run_loop_wrapper_delegates_to_python_default` | ๋™์ผ | ๋™์ผ | + +๋‘ ์‹œํ—˜ ๋ชจ๋‘ PR ์ด ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์€ ํŒŒ์ผ์ด๋ฉฐ, ์‹คํŒจ ๋ฉ”์‹œ์ง€์— ๊ณ„ํš์„œยท`--plan-file` ์€ ๋“ฑ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. + +### 6-2. ์ˆ˜์ • ์—†์ด๋Š” ์‹คํŒจํ•˜๋Š”๊ฐ€ โ€” ํ™•์ธํ•จ + +๊ฒ€์ฆ ๊ฒฝ๋กœ ์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ  `runner.py`ยท`run_loop.sh`ยท`SKILL.md` **์„ธ ํŒŒ์ผ๋งŒ base `6fc9194` ํŒ์œผ๋กœ ๋˜๋Œ๋ ค** ์ƒˆ ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ๋ ธ๋‹ค(๊ฒ€์ฆ ๊ฒฝ๋กœ ์ž์ฒด๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์•˜๋‹ค). + +``` +13 failed, 4 passed in 1.51s +FAILED P1, P2, P3b, P3c, P3d, P5, P9[empty], P9[whitespace], P10, P11, P7, P7b, P8 +``` + +ํ†ต๊ณผํ•œ 4๊ฑด(P3ยทP4ยทP5bยทP6)์€ ์˜ต์…˜ ์—†๋Š” ์ผ๋ฐ˜ CLI ์˜ค๋ฅ˜ยทplan ๋ชจ๋“œ ์ •์ƒ ๊ฒฝ๋กœ๋ผ ์ˆ˜์ •๊ณผ ๋ฌด๊ด€ํ•œ ๊ฒƒ๋“ค์ด๋‹ค. ์ฆ‰ ์ƒˆ ํ…Œ์ŠคํŠธ๋Š” ์ด ๋ณ€๊ฒฝ์„ ์ •ํ™•ํžˆ ๊ฒจ๋ƒฅํ•œ๋‹ค. + +### 6-3. ๊ฒฉ๋ฆฌ + +| ํ•ญ๋ชฉ | ๊ฒฐ๊ณผ | +|---|---| +| ์‹ค์ œ `.mam/jobs` ์ „ํ›„ | **์ฐจ์ด 0** | +| ์‹ค์ œ `.agents/reports` | ์ƒˆ ํ•ญ๋ชฉ ์—†์Œ(ํ…Œ์ŠคํŠธ๋Š” ๊ฐ์ž `tmp_path` ์•ˆ์— ์ œ์–ด ๋ฃจํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค โ€” `ctl` ํ”ฝ์Šค์ฒ˜) | +| ๊ฒ€์ฆ ๊ฒฝ๋กœ tracked ํŒŒ์ผ | ๋ณ€ํ™” ์—†์Œ(`git status --short` ํด๋ฆฐ, HEAD `1e82651` ์œ ์ง€) | +| ๊ฒ€์ฆ ๊ฒฝ๋กœ ignored | ๋‚ด ์‹คํ–‰์ด `.mam/`(๋ฌด์‹œ๋จ)์„ ๋งŒ๋“ค์—ˆ๋‹ค. tracked ํŒŒ์ผยท์ปค๋ฐ‹์—๋Š” ์˜ํ–ฅ์ด ์—†์œผ๋ฉฐ, ์ง€์šฐ๋ฉด ๋ฆฌ๋ทฐ ํŠธ๋ฆฌ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ์…ˆ์ด๋ผ ๊ทธ๋Œ€๋กœ ๋‘์—ˆ๋‹ค โ†’ E3 | +| ์‹คํ–‰ ์‹œ๊ฐ„ | ์ƒˆ ํŒŒ์ผ `test_issue25_plan_reuse.py` ๋Š” ์ „์ฒด 17๊ฑด์ด **1.5 s** ์•ˆ์— ๋๋‚œ๋‹ค(๋ธŒ๋กœ์ปคยทherdr ์˜์กด ์—†์Œ, ๋ชจ๋‘ stub) | + +## 7. ๋ฌธ์„œ (ํ•ญ๋ชฉ 7) + +- ์˜› ์„œ์ˆ ("๊ธฐ์กด์— ์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด๋ฅผ ๋กœ๋“œ")์€ `.agents`ยท`docs` ์–ด๋””์—๋„ ๋‚จ์•„ ์žˆ์ง€ ์•Š๋‹ค(์ „์ˆ˜ grep). +- SKILL.md ์˜ ์‚ฌ์šฉ๋ฒ• ๋ฌธ์ž์—ดยทCLI ํ‘œยทWorkflow ์˜ˆ์‹œยทMermaid ๋‹ค์ด์–ด๊ทธ๋žจ์ด ๋ชจ๋‘ `--plan-file` ๊ธฐ์ค€์œผ๋กœ ๋งž์ถฐ์กŒ๊ณ , "๊ณ„ํš์„œ๊ฐ€ ๋น„์–ด ์žˆ์„ ๋•Œ" ์ ˆ์ด ๋„ค ์ง€์ ์˜ ํŒ์ •์„ ์ •ํ™•ํžˆ ์„ค๋ช…ํ•œ๋‹ค. +- ๋Ÿฌ๋„ˆ usage ์™€ ์…ธ usage ๋ฌธ์ž์—ด์ด ๋™์ผํ•˜๋‹ค(P7 ์ด ์ด๋ฅผ ๊ณ ์ •ํ•œ๋‹ค). +- ๋ฐฐํฌ ์‚ฌ๋ณธ: ์ €์žฅ์†Œ์˜ `.claude/skills/*` ๋Š” `../../.agents/skills/*` **์‹ฌ๋งํฌ**๋ผ ์ž๋™์œผ๋กœ ๋™๊ธฐํ™”๋œ๋‹ค. ์‚ฌ์šฉ์ž ํ™ˆ `~/.claude/skills` ์—๋Š” mux ์Šคํ‚ฌ ์‚ฌ๋ณธ์ด ์—†๋‹ค. ์˜› ๋ฌธ๊ตฌ๋ฅผ ๊ฐ€์ง„ ์‚ฌ๋ณธ์€ ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์•˜๋‹ค. + +## 8. ๋ณ‘ํ•ฉ ์ฐจ๋‹จ ์—ฌ๋ถ€ (ํ•ญ๋ชฉ 8) + +๋ฒ„์ „ ๋ฝ์Šคํ… bump ๋ถ€์žฌ(`lib.sh:32`ยท`eager.py:16`ยทloop SKILL.md ๋ชจ๋‘ `4.7.0`, ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ๊ฐ€ 4.7.1 ๋กœ ์ฒ˜๋ฆฌ ์˜ˆ์ •) ์™ธ์— **๋ณ‘ํ•ฉ์„ ๋ง‰์„ ๊ฒฐํ•จ์€ ์—†๋‹ค**. + +| # | ๋น„์ฐจ๋‹จ ์ง€์  | ๊ทผ๊ฑฐ | +|---|---|---| +| E1 | ๋ ˆ๊ฑฐ์‹œ ์…ธ ๋Ÿฌ๋„ˆ(`MAM_LOOP_PY=0`)์˜ plan ๋ชจ๋“œ ์ฝ๊ธฐ์—๋Š” ๋นˆ ๊ณ„ํš์„œ ๊ฒ€์‚ฌ๊ฐ€ ์—†๋‹ค: `CURRENT_PLAN=$(cat "$PLAN_FILE")`(`run_loop.sh:501`). D13/D14 ๊ณ„์•ฝ์€ ํŒŒ์ด์ฌ ๋Ÿฌ๋„ˆ์—๋งŒ ์„ฑ๋ฆฝํ•˜๋Š”๋ฐ SKILL.md ์˜ "๊ณ„ํš์„œ๊ฐ€ ๋น„์–ด ์žˆ์„ ๋•Œ" ์ ˆ์€ ์ด๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š๋Š”๋‹ค | ํ›„์†: ํ•œ ์ค„ ๊ฑฐ๋ถ€ ๋˜๋Š” ๋ฌธ์„œ์— "Python ๋Ÿฌ๋„ˆ ๊ธฐ์ค€" ๋ช…์‹œ | +| E2 | `--plan-file` ๋กœ ๊ณ„ํš์„ ์‹ค์€ ์‹คํ–‰์—์„œ `[ESCALATE: PLANNER]` ๋Š” ์žฌ๊ณ„ํš ์—†์ด ์ผ๋ฐ˜ ์ˆ˜์ • ๋ผ์šด๋“œ๋กœ ๋‚ด๋ ค๊ฐ„๋‹ค(`runner.py:1275` ๊ฐ€ `plan_mode` ๋กœ ๊ฒŒ์ดํŠธ). ์ƒŒ๋“œ๋ฐ•์Šค ๊ตฌ๋™์œผ๋กœ ํ™•์ธ(Planner ์œ„์ž„ 0๊ฑด). ์ด ๊ฒŒ์ดํŠธ๋Š” PR ์ด์ „๋ถ€ํ„ฐ ์žˆ๋˜ ๊ฒƒ์ด๊ณ  SKILL.md ์„œ์ˆ ๊ณผ๋„ ๋ชจ์ˆœ๋˜์ง€ ์•Š์ง€๋งŒ, "๊ณ„ํš์„œ๋ฅผ ๊ฐ–๊ณ  ๋„๋Š” ๋ฃจํ”„์ธ๋ฐ ์—์Šค์ปฌ๋ ˆ์ด์…˜์ด ๋ฌด๋ ฅํ™”๋œ๋‹ค"๋Š” ์ ์€ ๋ฌธ์„œ์— ์—†๋‹ค | ๋ฌธ์„œ ๋ณด๊ฐ• ๊ถŒ๊ณ  | +| E3 | ๋ฆฌ๋ทฐ ๊ฒฉ๋ฆฌ ์›ŒํฌํŠธ๋ฆฌ์—๋Š” `.venv` ๊ฐ€ ์—†์–ด, `run_loop.sh` ๋ฅผ ํ•˜์œ„ ํ”„๋กœ์„ธ์Šค๋กœ ๋„์šฐ๋Š” ์Šค์œ„ํŠธ๋Š” `AGENT_PYTHON_BIN` ์—†์ด๋Š” ๋ฐ˜๋“œ์‹œ ์‹คํŒจํ•œ๋‹ค(ยง6-1). ๋˜ํ•œ ๊ทธ ์›ŒํฌํŠธ๋ฆฌ์—์„œ pytest ๋ฅผ ๋Œ๋ฆฌ๋ฉด ๋ฌด์‹œ๋˜๋Š” `.mam/` ์ด ์ƒ๊ธด๋‹ค. **PR #32 ๊ฐ€ ์•„๋‹ˆ๋ผ Issue #21 ํ•ญ๋ชฉ 5 ์šด์˜ ์ชฝ ํ›„์†**์ด๋‹ค | ๋ฆฌ๋ทฐ ๋ธŒ๋ฆฌํ”„์˜ ํ…Œ์ŠคํŠธ ๋ช…๋ น์— `AGENT_PYTHON_BIN=<์ œ์–ด ๋ฃจํŠธ .venv/bin/python>` ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ๊ณ  | +| E4 | `runner.py:1070` ์˜ `os.path.getmtime(self.plan_file)` ๋Š” ํŒŒ์‹ฑ ์‹œ์ ๊ณผ Phase 1 ์‚ฌ์ด์— ํŒŒ์ผ์ด ์‚ฌ๋ผ์ง€๋ฉด ์˜ˆ์™ธ๋กœ ์ฃฝ๋Š”๋‹ค(๋ฉ”์‹œ์ง€ ์—†๋Š” ํŠธ๋ ˆ์ด์Šค๋ฐฑ). ๊ทนํžˆ ์ข์€ ๊ฒฝํ•ฉ | ์‚ฌ์†Œ | + +## 9. ๊ต์ฐจ๊ฒ€์ฆ ๊ฐ€์ด๋“œ + +```bash +RP=/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20260921T150212Z-97d845/1 +PY=/Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.venv/bin/python +git -C "$RP" rev-parse HEAD HEAD^{tree} # 1e8265... / 4fd82a... = ๋ธŒ๋ฆฌํ”„์˜ headยทtree +# --plan-file ์‹คํŒจ ๊ฒฝ๋กœ (์ž„์‹œ ์ œ์–ด ๋ฃจํŠธ์—์„œ๋งŒ) +C=$(mktemp -d); mkdir -p "$C/ctl" "$C/elsewhere/plans"; : > "$C/ctl/empty.md"; echo x > "$C/elsewhere/plans/p.md" +(cd "$C/elsewhere" && PYTHONPATH="$RP/.agents/skills" WORKSPACE_ROOT="$C/ctl" MAM_STATE_JSON='{"herdr_sessions":[]}' \ + "$PY" -m lib_py.loop --creator c --task t --plan-file plans/p.md; echo "rc=$?") # ctl ๊ธฐ์ค€ ๊ฒฝ๋กœ๋กœ ์‹คํŒจ, rc 1 +# ์ˆ˜์ • ์—†์ด๋Š” ์‹คํŒจํ•˜๋Š”์ง€ (์‚ฌ๋ณธ์—์„œ๋งŒ) +S=$(mktemp -d); rsync -a --exclude .venv --exclude .git --exclude .mam --exclude nats-docker "$RP/" "$S/" +for f in .agents/skills/lib_py/loop/runner.py .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \ + .agents/skills/multi-agent-mux-loop/SKILL.md; do git -C "$RP" show 6fc9194:"$f" > "$S/$f"; done +(cd "$S" && PYTHONDONTWRITEBYTECODE=1 "$PY" -m pytest -q -p no:cacheprovider --basetemp=/tmp/bt tests/test_issue25_plan_reuse.py) # 13 failed +# ์‹คํŒจ 2๊ฑด์ด ํ™˜๊ฒฝ ๋ฌธ์ œ์ž„์„ ํ™•์ธ +(cd "$RP" && AGENT_PYTHON_BIN="$PY" PYTHONDONTWRITEBYTECODE=1 "$PY" -m pytest -q -p no:cacheprovider --basetemp=/tmp/bt2 \ + tests/test_loop_cli.py::test_creator_parses_and_reaches_session_check \ + tests/test_issue5_phase3_loop.py::test_p3_02_run_loop_wrapper_delegates_to_python_default) # 2 passed +``` + +[VERDICT: PASS] diff --git a/.agents/reports/planner-reviewer-codex-01/report-08808795.identity.json b/.agents/reports/planner-reviewer-codex-01/report-08808795.identity.json new file mode 100644 index 0000000..e96a37b --- /dev/null +++ b/.agents/reports/planner-reviewer-codex-01/report-08808795.identity.json @@ -0,0 +1,14 @@ +{ + "loop_id": "loop-20260921T150212Z-97d845", + "base_sha": "6fc9194f896eb2e13e123b8ebe7a9089b629764d", + "head_sha": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "tree_sha": "4fd82ad1c2682d12c3f5114818f97291af28a032", + "review_commit": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "reviewer": "planner-reviewer-codex-01", + "job_id": "08808795", + "verdict": "PASS", + "transport": "herdr", + "evidence": "review-tree", + "isolation": "worktree", + "verified_at": "2026-09-21T15:25:44Z" +} \ No newline at end of file diff --git a/.agents/reports/planner-reviewer-codex-01/report-08808795.md b/.agents/reports/planner-reviewer-codex-01/report-08808795.md new file mode 100644 index 0000000..9dd95b7 --- /dev/null +++ b/.agents/reports/planner-reviewer-codex-01/report-08808795.md @@ -0,0 +1,32 @@ +# PR #32 independent review + +Reviewer: planner-reviewer-codex-01. Job: 08808795. + +Reviewed the exact detached review-identity path specified by the brief: +`/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20260921T150212Z-97d845/1`, at `1e826515`, for the five commits after base `6fc9194`. No checkout, source file, session, monitor, or real registry state was modified. + +## Findings + +The explicit plan-reuse change is coherent and closes the implicit-load defect. + +- With neither `--plan` nor `--plan-file`, Python self-planning logs that no plan is loaded and does not glob `.agents/reports//plan-*.md`. The legacy shell runner does the same. `resolve_planner_session` may still identify a planner for other loop bookkeeping, but it no longer supplies a plan through that path. +- `--plan-file` is parsed by both wrappers. Python resolves relative paths against the control root, preserves absolute and `~` paths, requires a readable regular file with non-whitespace content, and rejects bad inputs before registering jobs. It is mutually exclusive with `--plan`; `--planner` still requires `--plan`; review-only accepts a valid file but warns and ignores it because no implementation prompt is produced. The legacy shell runner rejects the option explicitly when `MAM_LOOP_PY=0`, before the loop lock. +- `_plan_text()` is the shared check for explicit files, initial planner reports, discussion refinements, and escalation refinements. An empty initial planner report stops the run rather than silently falling back to self-planning. An empty refine report preserves the existing plan. Correction prompts therefore never claim to carry an empty plan. +- Checkpoint `current_plan` is not a plan-discovery source. It is only recorded for the current run; a later no-option run starts planless, and a named `--plan-file` is read explicitly. Promotion still writes the plan only for an actual `--plan` run. +- Relative plan paths with spaces, missing paths, directories, empty/whitespace files, unreadable files, `--plan` conflicts, review-only handling, and legacy-shell rejection are covered by P1โ€“P11. The tests run in temporary control roots and use isolated reports; they do not write the real `.mam` or `.agents/reports`. +- The loop skillโ€™s old implicit-reuse wording is removed. The CLI usage, workflow examples, option table, and explicit-reuse description agree. No `.claude/skills` deployment copy exists in this checkout, so there is no second copy to synchronize. + +The known release prerequisite remains outside this PR: the orchestrator must perform the 4.7.1 lockstep version bump and release entry before merge. + +## Verification + +All tests used `PYTHONDONTWRITEBYTECODE=1`, the interpreter from the brief, pytest cache disabled, and a basetemp outside the review path. + +- `tests/test_issue25_plan_reuse.py`: **17 passed** in 1.70 s. +- `tests/test_issue25_plan_reuse.py`, `tests/test_loop_cli.py`, `tests/test_issue5_phase3_loop.py`, and `tests/test_version_consistency.py`: **39 passed, 2 failed** in 49.25 s when run exactly from the identity path. Both failures occurred before their assertions because `run_loop.sh` could not find `.venv` in the detached snapshot and fell back to system Python, which lacked `paho` (`RuntimeError: Failed to eager load lib_py.loop.autocomplete: No module named 'paho'`). This is a snapshot/setup issue, not a change in the plan-reuse code. +- Re-running the two failed compatibility cases with `AGENT_PYTHON_BIN` pinned to the briefโ€™s main interpreter: **2 passed** in 0.32 s. This reaches and verifies the expected session-registration checks. +- `git diff --check 6fc9194...HEAD`: passed. + +The focused plan tests passed without modification, and the only broader failures disappeared when the required interpreter was explicitly supplied. I found no additional merge-blocking defect beyond the known version gate. + +[VERDICT: PASS] diff --git a/.agents/reports/reviewer-agy-01/report-41f07cde.identity.json b/.agents/reports/reviewer-agy-01/report-41f07cde.identity.json new file mode 100644 index 0000000..20df469 --- /dev/null +++ b/.agents/reports/reviewer-agy-01/report-41f07cde.identity.json @@ -0,0 +1,14 @@ +{ + "loop_id": "loop-20260921T150212Z-97d845", + "base_sha": "6fc9194f896eb2e13e123b8ebe7a9089b629764d", + "head_sha": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "tree_sha": "4fd82ad1c2682d12c3f5114818f97291af28a032", + "review_commit": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "reviewer": "reviewer-agy-01", + "job_id": "41f07cde", + "verdict": "PASS", + "transport": "herdr", + "evidence": "review-tree", + "isolation": "worktree", + "verified_at": "2026-09-21T15:25:44Z" +} \ No newline at end of file diff --git a/.agents/reports/reviewer-agy-01/report-41f07cde.md b/.agents/reports/reviewer-agy-01/report-41f07cde.md new file mode 100644 index 0000000..7cfd0e7 --- /dev/null +++ b/.agents/reports/reviewer-agy-01/report-41f07cde.md @@ -0,0 +1,113 @@ +# Pre-Merge Independent Review Report: PR #32 (`fix/issue-25`) + +- **Job ID**: `41f07cde` +- **Target Agent**: `agy` (Session: `herdr:reviewer-agy-01`) +- **Role**: Reviewer +- **Target Worktree Context**: + - **Loop ID**: `loop-20260921T150212Z-97d845` + - **Base Commit**: `6fc9194f896eb2e13e123b8ebe7a9089b629764d` (v4.7.0) + - **Head Commit**: `1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd` + - **Tree SHA**: `4fd82ad1c2682d12c3f5114818f97291af28a032` + - **Verification Path**: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20260921T150212Z-97d845/1` + +--- + +## 1. Executive Summary + +PR #32 resolves Issue #25 ("์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ ์žฌ์‚ฌ์šฉ์„ --plan-file ๋กœ๋งŒ ํ—ˆ์šฉ โ€” ์•”๋ฌต์  ์ž๋™ ๋กœ๋“œ ์ œ๊ฑฐ") across 5 commits and 4 files (+486 / โˆ’31): +- `1e82651` fix(issue-25): a relative --plan-file is taken against the control root, as its usage line says +- `5fa5923` docs(issue-25): the loop skill documents --plan-file and the empty-report handling +- `a334083` test(issue-25): plan reuse is explicit only and empty plan reports are not silent (P1-P11) +- `e551e3b` fix(issue-25): one plan-text check for every load; an empty planner report stops the loop, an empty refine keeps the plan +- `a28711c` fix(issue-25): reuse a promoted plan only with --plan-file; drop the implicit newest-plan load + +All checklist criteria have been verified in the isolated verification path. All 17 new tests in `test_issue25_plan_reuse.py` and all 115 baseline regression tests passed with zero regressions. + +--- + +## 2. Detailed Verification Against Checklist Items + +### (1) Removal of Implicit Plan Loading +- **Python Runner (`lib_py/loop/runner.py`)**: + - Removed `import glob` and the directory scan `glob.glob(str(self.workspace_root / ".agents" / "reports" / planner_session / "plan-*.md"))`. + - In Phase 1 Self-Planning mode, if `--plan-file` was not supplied, `self.current_plan` remains empty and the runner logs: `"No plan loaded; the Creator plans by itself (reuse one with --plan-file )."`. +- **Legacy Shell Runner (`scripts/run_loop.sh`)**: + - Removed `EXISTING_PLAN_FILE=$(ls -t ".agents/reports/$PLANNER_SESSION"/plan-*.md 2>/dev/null | head -n 1 || true)`. + - In Self-Planning mode, logs `"No plan loaded; the Creator plans by itself."`. +- **Parity & Search Check**: + - Test `test_p8_neither_loop_implementation_globs_for_a_plan_any_more` confirms the string pattern `plan-*.md` does not appear anywhere in `runner.py` or `run_loop.sh`. + - Automatic planner resolution (`resolve_planner_session`) is not called or consulted to retrieve stored plans in Phase 1 self-planning mode. + +### (2) `--plan-file ` CLI Option Semantics +- **Control Root Resolution**: + - Relative paths are anchored against `self.workspace_root` via `(self.workspace_root / Path(self.plan_file).expanduser()).resolve()`. This guarantees identical path resolution whether the command is run from the repository root, a subdirectory, or an isolated worktree (`test_p3c`). + - Absolute paths and user home expansion (`~`) remain untouched and work as expected (`test_p3d`). +- **Fail-Closed Early Validation**: + - Evaluated in `parse_args()` before any agent delegation or job submission occurs (`test_p3`, `test_p3b`). + - If the path is non-existent, a directory, unreadable, or contains whitespace-only text, the runner logs an error naming the resolved path and immediately exits with rc=1. +- **Mutual Exclusion & Option Combinations**: + - Combining `--plan-file` with `--plan` exits 1 with a clear mutual exclusion error (`test_p4`). + - Specifying `--plan-file` without an argument exits 1 (`test_p4`). + - When combined with `--review-only`, the runner logs a warning and ignores the plan (`self.current_plan = ""`), because Phase 2 implementation is skipped (`test_p5`, `test_p5b`). +- **Legacy Shell Rejection**: + - When invoked with `MAM_LOOP_PY=0`, `run_loop.sh` explicitly detects `--plan-file` and terminates with code 1 before the loop marker/guard is created (`test_p7b`). + +### (3) Centralized Plan Text Validation (`e551e3b`) +- **Shared Validation Method**: + - `LoopRunner._plan_text(path: Path) -> Optional[str]` enforces: + 1. Regular file check (`path.is_file()`). + 2. Safe decoding with error replacement (`read_text(encoding="utf-8", errors="replace")`). + 3. Stripped text check (`text if text.strip() else None`). +- **Initial Plan Failure**: + - In `--plan` mode, if the initial planner report is empty or whitespace-only, the runner logs `the planner's report has no plan text: ` and exits with code 1 (`test_p9`). This eliminates the regression where an empty plan silently demoted the run to self-planning. +- **Refinement Retention (Debate & Review Escalation)**: + - In Phase 1 interactive debate (`--plan-talk`) and Phase 3 review escalation (`[ESCALATE: PLANNER]`), an empty refinement report logs a warning and preserves the previously valid plan (`test_p10`, `test_p11`). + - This prevents prompt corruption in `correction_prompt = f"๊ฐฑ์‹ ๋œ ๋‹ค์Œ ๊ณ„ํš์„œ์— ์ž…๊ฐํ•˜์—ฌ ... ๊ณ„ํš์„œ:\n{self.current_plan}"`. + +### (4) Checkpoint Integrity +- `LoopRunner` persists `current_plan` to `.mam/loop-checkpoint.json` for diagnostic and monitoring visibility during active loops. +- `LoopRunner` never reads `.mam/loop-checkpoint.json` at startup to populate `self.current_plan`. `self.current_plan` is always initialized cleanly (`self.current_plan = ""`). +- Existing checkpoint files in the workspace (such as unrelated historical plan text from prior issues) cannot contaminate new loop runs. + +### (5) Baseline Behavior & Creator Prompts +- In self-planning mode without `--plan-file`, the initial Creator prompt retains the exact contract: + `"๊ณ„ํš์„œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ž‘์—…์ž(Creator)์˜ ํŒ๋‹จํ•˜์— ์Šค์Šค๋กœ ๊ตฌํ˜„ ๊ณ„ํš ๋ฐ ์„ค๊ณ„๋ฅผ ์ˆ˜๋ฆฝํ•œ ๋’ค, ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋‹ค์Œ ์ž‘์—… ๋ชฉํ‘œ๋ฅผ ์™„์„ฑํ•ด์ฃผ์„ธ์š”. ์ž‘์—… ๋ชฉํ‘œ: {self.task}"`. +- With `--plan-file `, the prompt receives: + `"์ด๋ฏธ ์ˆ˜๋ฆฝ๋œ ๋‹ค์Œ ๊ณ„ํš์„œ์— ์ž…๊ฐํ•˜์—ฌ ์ž‘์—…์ž์˜ ํŒ๋‹จํ•˜์— ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์ž‘์—… ๋ชฉํ‘œ๋ฅผ ์™„์„ฑํ•ด์ฃผ์„ธ์š”. ๊ณ„ํš์„œ:\n{self.current_plan}\n\n์ž‘์—… ๋ชฉํ‘œ: {self.task}"`. +- Subsequent review corrective rounds strictly provide reviewer feedback without repeating the initial plan (`test_p2`). +- Promotion of newly planned tasks via `--plan` to `.agents/reports//plan-.md` remains operational and protected (`test_p6`). + +### (6) Test Suite Execution & Isolation (P1โ€“P11) +- All 17 test cases in `tests/test_issue25_plan_reuse.py` operate strictly within isolated `tmp_path` fixtures with stubbed delegations. +- Real `.mam/jobs`, live daemon processes, and global agent sessions remain completely untouched. +- Execution timing: 17 tests passed in 2.02 seconds. + +### (7) Documentation Integrity +- `.agents/skills/multi-agent-mux-loop/SKILL.md` was thoroughly updated: + - Completely purged the stale statement ("๊ธฐ์กด์— ์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด๋ฅผ ๋กœ๋“œ"). + - Updated Sequence Diagram and Phase 1 documentation to reflect explicit `--plan-file` reuse. + - Added a dedicated section: `### ๊ณ„ํš์„œ๊ฐ€ ๋น„์–ด ์žˆ์„ ๋•Œ (Empty plan reports)`. + - Updated CLI Option mapping table and Workflow examples. +- No dangling references to the old implicit loading mechanism exist across the repository. + +### (8) Versioning & Merge Readiness +- Version lockstep bump to `v4.7.1` is reserved for the orchestrator release commit in accordance with release procedures. +- Formatting and git diff checks (`git diff 6fc9194...HEAD --check`) reported 0 issues. +- No merge blockers, regression risks, or side-effects detected. + +--- + +## 3. Test Execution Summary + +| Test Suite | Result | Duration | Notes | +| :--- | :--- | :--- | :--- | +| `tests/test_issue25_plan_reuse.py` | **17 / 17 PASS** | 2.02s | P1โ€“P11 test matrix covering all reuse/empty-plan conditions | +| `tests/test_loop_cli.py` | **9 / 9 PASS** | 38.97s | CLI interface and argument validation regressions | +| `tests/test_issue5_phase2a_loop.py` | **91 / 91 PASS** | 2.91s | Core loop state machine, dispatching, and verdict handling | +| `tests/test_issue5_phase3_loop.py` | **12 / 12 PASS** | 0.54s | Runner orchestration, timeouts, and signal handling | +| `tests/test_version_consistency.py` | **3 / 3 PASS** | 0.21s | Version consistency checks | +| `git diff 6fc9194...HEAD --check` | **0 errors** | 0.05s | Zero trailing whitespace / formatting errors | + +--- + +[VERDICT: PASS] diff --git a/.agents/reports/reviewer-grok-01/report-06fb4a9e.identity.json b/.agents/reports/reviewer-grok-01/report-06fb4a9e.identity.json new file mode 100644 index 0000000..ff56004 --- /dev/null +++ b/.agents/reports/reviewer-grok-01/report-06fb4a9e.identity.json @@ -0,0 +1,14 @@ +{ + "loop_id": "loop-20260921T150212Z-97d845", + "base_sha": "6fc9194f896eb2e13e123b8ebe7a9089b629764d", + "head_sha": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "tree_sha": "4fd82ad1c2682d12c3f5114818f97291af28a032", + "review_commit": "1e826515cc2a07ea1f8da0ff1259e1ea4dde86fd", + "reviewer": "reviewer-grok-01", + "job_id": "06fb4a9e", + "verdict": "PASS", + "transport": "herdr", + "evidence": "review-tree", + "isolation": "worktree", + "verified_at": "2026-09-21T15:25:44Z" +} \ No newline at end of file diff --git a/.agents/reports/reviewer-grok-01/report-06fb4a9e.md b/.agents/reports/reviewer-grok-01/report-06fb4a9e.md new file mode 100644 index 0000000..24a1456 --- /dev/null +++ b/.agents/reports/reviewer-grok-01/report-06fb4a9e.md @@ -0,0 +1,59 @@ +# ๐Ÿ” Review Report โ€” Job 06fb4a9e (PR #32 @ `1e82651`) + +- **Reviewer**: `reviewer-grok-01` ยท 2026-09-22 +- **๊ฒ€์ฆ ๊ฒฝ๋กœ**: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20260921T150212Z-97d845/1` +- **identity**: base `6fc9194` head `1e82651` tree `4fd82ad` (์ผ์น˜) +- **์†Œ์Šค ์›ŒํฌํŠธ๋ฆฌยท๋ณธ ์ฒดํฌ์•„์›ƒ**: ์ฝ๊ธฐ ์ „์šฉ. ๋ณธ ์ฒดํฌ์•„์›ƒ `main` `6fc9194` ์œ ์ง€. + +`git diff --check 6fc9194...HEAD` ํด๋ฆฐ. 5์ปค๋ฐ‹. + +## (1) ์•”๋ฌต์  ๋กœ๋“œ ์ œ๊ฑฐ + +Python: Phase 1 else ๊ฐ€ glob/`plan-*.md` ๋ฅผ ์“ฐ์ง€ ์•Š์Œ (`runner.py:1064-1073`). `import glob` ์‚ญ์ œ. `resolve_planner_session` (`:990`) ์€ ์„ธ์…˜ ์ด๋ฆ„๋งŒ ๋กœ๊ทธํ•˜๊ณ  ํŒŒ์ผ์„ ์ฝ์ง€ ์•Š์Œ. `--planner` ๋Š” `--plan` ์—†์ด exit 1 (`:244-248`). + +๋ ˆ๊ฑฐ์‹œ ์…ธ (`MAM_LOOP_PY=0`): `ls -t .agents/reports/.../plan-*.md` ์ œ๊ฑฐ (`run_loop.sh` Phase 1 else). `plan-*.md` ๋ฌธ์ž์—ด์ด ๋‘ ๊ตฌํ˜„์— ์—†์Œ (`test_p8`). + +## (2) `--plan-file` + +์ƒ๋Œ€๊ฒฝ๋กœ๋Š” `workspace_root / path` (`runner.py:264`); POSIX ์—์„œ ์ ˆ๋Œ€๊ฒฝ๋กœ๋Š” `/` ๋กœ ์น˜ํ™˜๋˜์–ด ๊ทธ๋Œ€๋กœ. `~` ๋Š” `expanduser`. ์—†๋Š”/๋นˆ/๊ณต๋ฐฑ๋ฟ/๋””๋ ‰ํ„ฐ๋ฆฌ/์ฝ๊ธฐ ์‹คํŒจ โ†’ `_plan_text` None โ†’ parse_args `sys.exit(1)`, ์žก ์—†์Œ. `--plan` ๊ณผ ์ƒํ˜ธ ๋ฐฐํƒ€. `--review-only` ๋Š” ํŒŒ์ผ ๊ฒ€์‚ฌ ํ›„ ๊ฒฝ๊ณ ยท๋ฌด์‹œ(`current_plan` ๋น„์›€). `--planner` ๋Š” `--plan` ํ•„์ˆ˜๋ผ `--plan-file` ๊ณผ ํ•จ๊ป˜๋ฉด ๋จผ์ € `--planner` ๊ทœ์น™์— ๊ฑธ๋ฆฐ๋‹ค. + +๋ ˆ๊ฑฐ์‹œ ์…ธ์€ `--plan-file` ์„ Python ์ „์šฉ์œผ๋กœ **๋ช…์‹œ ๊ฑฐ๋ถ€** exit 1, ๋ฃจํ”„ ๋ฝ ์ „ (`run_loop.sh:127-134`, `test_p7b`). ๊ณต๋ฐฑ ๊ฒฝ๋กœ๋Š” pathlib ๊ฐ€ ์ฒ˜๋ฆฌ; ์ „์šฉ ํ…Œ์ŠคํŠธ๋Š” ์—†์Œ(๋น„์ฐจ๋‹จ). + +## (3) `_plan_text` (e551e3b) + +ํ•œ ํ•จ์ˆ˜ (`:304-316`)๊ฐ€ `--plan-file`, ์ดˆ๊ธฐ planner ๋ฆฌํฌํŠธ, ๋…ผ์˜ refine, ์—์Šค์ปฌ๋ ˆ์ด์…˜ refine ์— ์‚ฌ์šฉ. ๋นˆ ์ดˆ๊ธฐ ๊ณ„ํš โ†’ `return 1`, Worker ์—†์Œ (`test_p9`). ๋นˆ refine โ†’ ๊ฒฝ๊ณ ยท์ด์ „ ๊ณ„ํš ์œ ์ง€ (`test_p10`, `test_p11` ESCALATE). ์ˆ˜์ • ํ”„๋กฌํ”„ํŠธ๊ฐ€ ๋นˆ ๊ณ„ํš์„ ์‹ฃ์ง€ ์•Š์Œ. + +## (4) ์ฒดํฌํฌ์ธํŠธ + +`current_plan` ์€ ๊ธฐ๋ก๋งŒ (`_record_checkpoint`). `load_checkpoint` ๋ฅผ runner ๊ฐ€ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Œ. ์ƒˆ ์‹คํ–‰์€ `current_plan=""` ์—์„œ ์‹œ์ž‘. ๋ณธ ์ฒดํฌ์•„์›ƒ `.mam/loop-checkpoint.json` ์˜ ์˜› ๊ณ„ํš์€ ์šฐํšŒ๊ฐ€ ์•„๋‹˜. + +## (5) ์˜ต์…˜ ์—†์Œ + +์˜๋„๋œ ๋ณ€ํ™”๋งŒ: ์ž๊ธฐ๊ณ„ํš ํ”„๋กฌํ”„ํŠธ. ์Šน๊ฒฉ์€ `--plan` ์„ฑ๊ณต ์‹œ `plan-{id}.md` ๊ธฐ๋ก ์œ ์ง€ (`test_p6`). ๊ธฐ์กด ํ…Œ์ŠคํŠธ๋Š” ๊ฒ€์ฆ ๊ฒฝ๋กœ์—์„œ ์‹คํ–‰. + +## (6) ํ…Œ์ŠคํŠธ P1โ€“P11 + +์ „๋ถ€ `tmp_path`. ๊ฒ€์ฆ ๊ฒฝ๋กœ: + +``` +PYTHONDONTWRITEBYTECODE=1 -m pytest -p no:cacheprovider --basetemp=/tmp/mam-review-basetemp-... + tests/test_issue25_plan_reuse.py +``` + +**17 passed** (P1โ€“P11 + p3b/c/d, p5b, p7/p7b, p8). ์ˆ˜์ • ์ „ P1 ์€ ์˜› glob ์„ ๋‹จ์–ธํ•˜๋ฏ€๋กœ ์‹คํŒจํ–ˆ์„ ํ…Œ์ŠคํŠธ. + +๊ฐ™์€ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋กœ `test_loop_cli`ยท`test_issue5_phase3`ยท`test_issue21_worktree_prereqs`ยท`test_version_consistency` ํฌํ•จ ์‹œ ๋ž˜ํผ ์„œ๋ธŒํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ฒ€์ฆ ํŠธ๋ฆฌ์— `.venv` ๊ฐ€ ์—†์–ด `paho` ๋ฅผ ๋ชป ์ฐพ๋Š” ์‹คํŒจ 2๊ฑด์ด ๋‚ฌ๊ณ , `DELEGATE_JOB_PYTHON` ์„ ์ปจํŠธ๋กค `.venv` ๋กœ ์ฃผ๋ฉด **19 passed**. ์ œํ’ˆ ํšŒ๊ท€๊ฐ€ ์•„๋‹ˆ๋ผ ์Šค๋ƒ…์ƒท์— venv ๊ฐ€ ์—†๋Š” ํ™˜๊ฒฝ. + +## (7) ๋ฌธ์„œ + +SKILL.md ์—์„œ "๊ธฐ์กด์— ์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด๋ฅผ ๋กœ๋“œ" ์ž”์กด ์—†์Œ. usageยทCLI ํ‘œยทWorkflow ์˜ˆ์‹œ๊ฐ€ `--plan-file` ๊ณผ ์ผ์น˜. `.claude/skills` ๋Š” ์ด ์Šค๋ƒ…์ƒท์— ์—†์Œ. + +## (8) ๋ฝ์Šคํ… + +`MAM_VERSION=4.7.0`. 4.7.1 bump ๋Š” ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ ์˜ˆ์ •. ๋ณ‘ํ•ฉ ์ฐจ๋‹จ ์•„๋‹˜. + +## ์ข…ํ•ฉ + +์•”๋ฌต์  ์ตœ์‹  ๊ณ„ํš ๋กœ๋“œ๊ฐ€ Pythonยท๋ ˆ๊ฑฐ์‹œ ์–‘์ชฝ์—์„œ ์ œ๊ฑฐ๋๊ณ , ์žฌ์‚ฌ์šฉ์€ `--plan-file` ๋ฟ์ด๋‹ค. ๋นˆ ๋ฆฌํฌํŠธ๋Š” ์กฐ์šฉํžˆ ๊ณ„ํš์„ ์ง€์šฐ์ง€ ์•Š๋Š”๋‹ค. ์„ค๊ณ„ ์žฌ์ž‘์—… ๋ถˆํ•„์š”. + +[VERDICT: PASS] diff --git a/.agents/skills/lib.sh b/.agents/skills/lib.sh index d099771..1b0283a 100644 --- a/.agents/skills/lib.sh +++ b/.agents/skills/lib.sh @@ -29,7 +29,7 @@ export WORKSPACE_ROOT # Framework semantic version. Single runtime source of truth; kept in lockstep # with VERSIONS.md and the 8 SKILL.md frontmatters by tests/test_version_consistency.py. # NOTE: unlike other MAM_* variables this one is intentionally NOT env-overridable. -MAM_VERSION="4.7.0" +MAM_VERSION="4.7.1" export MAM_VERSION AGENT_SESSIONS_YAML="${AGENT_SESSIONS_YAML:-$WORKSPACE_ROOT/.mam/agent-sessions.yaml}" diff --git a/.agents/skills/lib_py/loop/eager.py b/.agents/skills/lib_py/loop/eager.py index d746479..ba73b19 100644 --- a/.agents/skills/lib_py/loop/eager.py +++ b/.agents/skills/lib_py/loop/eager.py @@ -13,7 +13,7 @@ import sys from typing import List, Sequence # Framework version locked with framework constants -FRAMEWORK_VERSION = "4.7.0" +FRAMEWORK_VERSION = "4.7.1" CORE_MODULES: Sequence[str] = ( # Standard library modules diff --git a/.agents/skills/multi-agent-mux-create/SKILL.md b/.agents/skills/multi-agent-mux-create/SKILL.md index b63c35f..e16d8f5 100644 --- a/.agents/skills/multi-agent-mux-create/SKILL.md +++ b/.agents/skills/multi-agent-mux-create/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-create description: "Create a new agent session (claude, antigravity/agy) in a dedicated herdr session for context-preserving long-running work. Always creates a herdr session โ€” never backgrounds with nohup/disown. Writes the new session to .mam/agent-sessions.yaml. Use when you want to start a fresh agent (no prior UUID) for a new project workspace." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/.agents/skills/multi-agent-mux-delegate-job/SKILL.md b/.agents/skills/multi-agent-mux-delegate-job/SKILL.md index 2da2678..52ef4b3 100644 --- a/.agents/skills/multi-agent-mux-delegate-job/SKILL.md +++ b/.agents/skills/multi-agent-mux-delegate-job/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-delegate-job description: "Delegate a unit of work to any autonomous agent (claude-code, hermes, agy, grok-build, codex, or a human) and observe it asynchronously over an MQTT event channel. Supported roles include orchestrator, worker, and reviewer." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos, windows] diff --git a/.agents/skills/multi-agent-mux-loop/SKILL.md b/.agents/skills/multi-agent-mux-loop/SKILL.md index 8d1f0a9..7d7ed24 100644 --- a/.agents/skills/multi-agent-mux-loop/SKILL.md +++ b/.agents/skills/multi-agent-mux-loop/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-loop description: "Run an autonomous planning-execution-review loop using multiple agents (Planner, Creator, Reviewers) in the workspace. Automatically orchestrates plan discussion, code changes, and peer reviews until a unanimous PASS is achieved or the maximum iteration limit is reached." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/.agents/skills/multi-agent-mux-monitor/SKILL.md b/.agents/skills/multi-agent-mux-monitor/SKILL.md index 01ca21f..1ee9a02 100644 --- a/.agents/skills/multi-agent-mux-monitor/SKILL.md +++ b/.agents/skills/multi-agent-mux-monitor/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-monitor description: "Run a long-lived reconciler that watches .mam/agent-sessions.yaml against the actual herdr/agent runtime state and reconciles them. Use when you want live visibility into which agent sessions are running, which are dead, which have stale YAML entries, and which have new session ids that haven't been recorded yet. Runs as a persistent loop (`reconcile.sh --subscribe`) that keeps going until it times out, idles out, or is interrupted." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/.agents/skills/multi-agent-mux-orc-onboard/SKILL.md b/.agents/skills/multi-agent-mux-orc-onboard/SKILL.md index 9b33333..03f3290 100644 --- a/.agents/skills/multi-agent-mux-orc-onboard/SKILL.md +++ b/.agents/skills/multi-agent-mux-orc-onboard/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-orc-onboard description: "Register current or specified orchestrator session UUID into agent-sessions.yaml orchestrator_uuids list to prevent sub-agent discovery capture." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/.agents/skills/multi-agent-mux-resume/SKILL.md b/.agents/skills/multi-agent-mux-resume/SKILL.md index ace7f82..8156922 100644 --- a/.agents/skills/multi-agent-mux-resume/SKILL.md +++ b/.agents/skills/multi-agent-mux-resume/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-resume description: "Resume an existing agent (claude, antigravity/agy) conversation by UUID into a herdr session. Reads .mam/agent-sessions.yaml for the saved session/conversation id, spawns (or reuses) a herdr session of the matching name, and runs `claude -r ` or `agy --conversation ` inside. Use when you want to reattach to a previous session's context, or revive a session whose herdr died but the agent's conversation is still on disk." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/.agents/skills/multi-agent-mux-status/SKILL.md b/.agents/skills/multi-agent-mux-status/SKILL.md index 304b52b..87e9d1d 100644 --- a/.agents/skills/multi-agent-mux-status/SKILL.md +++ b/.agents/skills/multi-agent-mux-status/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-status description: "Read-only instant snapshot of all agent herdr sessions โ€” name, YAML status, herdr alive, pane cmd/cwd, resume UUID on disk, and any drift. No mutation. Reuses reconcile.sh --dry-run for the diff logic. Use when you want to know 'what's running RIGHT NOW' without spinning up the monitor loop." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/.agents/skills/multi-agent-mux-stop/SKILL.md b/.agents/skills/multi-agent-mux-stop/SKILL.md index afbf1cf..b0184ac 100644 --- a/.agents/skills/multi-agent-mux-stop/SKILL.md +++ b/.agents/skills/multi-agent-mux-stop/SKILL.md @@ -1,7 +1,7 @@ --- name: multi-agent-mux-stop description: "Stop an agent herdr session (claude, antigravity/agy) and update .mam/agent-sessions.yaml. Default stops gracefully and marks status=stopped with conversation preserved for resume. Does NOT delete on-disk conversation artifacts (jsonl/db) โ€” those are preserved unless --purge-conversation is passed. Use when ending a work session, switching to a different one, or cleaning up before a fresh start." -version: 4.7.0 +version: 4.7.1 author: godopu license: MIT platforms: [linux, macos] diff --git a/BOOTSTRAP.ko.md b/BOOTSTRAP.ko.md index c4f866c..b1215e7 100644 --- a/BOOTSTRAP.ko.md +++ b/BOOTSTRAP.ko.md @@ -2,7 +2,7 @@ ๋ณธ ๋ฌธ์„œ๋Š” `herdr_agent_orchestration` ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ๋ฐ ๋ฉ”์‹œ์ง• ๋ฐฑํ”Œ๋ ˆ์ธ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ์— ๋„์ž…ํ•˜์—ฌ ์ด์‹ํ•˜๊ณ , ์ƒˆ๋กœ์šด ๊ฐœ๋ฐœ์ž/์—์ด์ „ํŠธ๊ฐ€ ์ดˆ๊ธฐ ๊ฐ€๋™์„ ์‹œ์ž‘ํ•  ๋•Œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ํ™˜๊ฒฝ ์„ค์ • ๋ฐ ๊ตฌ์ถ• ์ ˆ์ฐจ๋ฅผ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค. -[![Version: v4.7.0](https://img.shields.io/badge/version-v4.7.0-blue.svg)](VERSIONS.md) +[![Version: v4.7.1](https://img.shields.io/badge/version-v4.7.1-blue.svg)](VERSIONS.md) ์ƒˆ๋กœ์šด ์—์ด์ „ํŠธ๋Š” ์ด ์•ˆ๋‚ด์„œ์— ๊ธฐ์ˆ ๋œ ์ ˆ์ฐจ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•˜์—ฌ ์ดˆ๊ธฐ ํ™˜๊ฒฝ์„ ์•ˆ์ •์ ์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/BOOTSTRAP.md b/BOOTSTRAP.md index 880dead..05f6908 100644 --- a/BOOTSTRAP.md +++ b/BOOTSTRAP.md @@ -2,7 +2,7 @@ This document guides you through the setup and initialization procedures required to adopt the `herdr_agent_orchestration` orchestration and messaging backplane workflow in a new project, enabling a new developer or agent to get up and running quickly. -[![Version: v4.7.0](https://img.shields.io/badge/version-v4.7.0-blue.svg)](VERSIONS.md) +[![Version: v4.7.1](https://img.shields.io/badge/version-v4.7.1-blue.svg)](VERSIONS.md) A new agent can follow the steps in this guide sequentially to establish a stable and reliable initial environment. diff --git a/MESSAGING.md b/MESSAGING.md index ebc80c7..1125620 100644 --- a/MESSAGING.md +++ b/MESSAGING.md @@ -1,6 +1,6 @@ # Messaging System Technical Analysis & Architecture Report -Applies to: MAM v4.7.0 +Applies to: MAM v4.7.1 This report provides a comprehensive, deep-dive analysis of the messaging system implemented in the `multi-agent-mux-delegate-job` skill. It covers the MQTT broker architecture, event protocols, job lifecycles, codebase internals, cross-system integration, and a list of known limitations along with production recommendations. diff --git a/README.ko.md b/README.ko.md index 2bb889d..25a75ea 100644 --- a/README.ko.md +++ b/README.ko.md @@ -2,7 +2,7 @@ Herdr์™€ MQTT ๋ธŒ๋กœ์ปค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๊ณ ์‹ ๋ขฐ์„ฑ **๋‹ค์ค‘ ์—์ด์ „ํŠธ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ๋ฐ ๋ฉ”์‹œ์ง• ๋ฐฑํ”Œ๋ ˆ์ธ** ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. `claude`, `agy`, `hermes`, `grok`, `opencode`, `codex` ๋“ฑ ๋‹ค์ค‘ LLM ๋ฐฑ์—”๋“œ ์—์ด์ „ํŠธ ์ „๋ฐ˜์— ๊ฑธ์ณ ์žฅ์‹œ๊ฐ„ ์ˆ˜ํ–‰๋˜๋Š” ์ž‘์—…(์ฝ”๋“œ ์ƒ์„ฑ, ๋ฆฌํŒฉํ† ๋ง, ๋ณด์•ˆ ๊ฒ€ํ†  ๋“ฑ)์„ ์กฐ์ •, ๊ฒฉ๋ฆฌ ๋ฐ ๊ฐ์‚ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -[![Version: v4.7.0](https://img.shields.io/badge/version-v4.7.0-blue.svg)](VERSIONS.md) +[![Version: v4.7.1](https://img.shields.io/badge/version-v4.7.1-blue.svg)](VERSIONS.md) --- diff --git a/README.md b/README.md index 611b1f5..8bbf741 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ An advanced, high-reliability **Multi-Agent Orchestration & Messaging Backplane** framework built on Herdr and MQTT. It is designed to coordinate, isolate, and audit long-running agent tasks (such as code generation, refactoring, and security reviews) across multiple LLM backend clients (`claude`, `agy`, `hermes`, `grok`, `opencode`, `codex`). -[![Version: v4.7.0](https://img.shields.io/badge/version-v4.7.0-blue.svg)](VERSIONS.md) +[![Version: v4.7.1](https://img.shields.io/badge/version-v4.7.1-blue.svg)](VERSIONS.md) --- diff --git a/VERSIONS.md b/VERSIONS.md index 0f2c9af..67100ff 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -6,8 +6,8 @@ ## ๐Ÿ“Œ ํ˜„์žฌ ๋ฒ„์ „ ๊ฐœ์š” (Current Release) -- **ํ”„๋ ˆ์ž„์›Œํฌ ๋ฒ„์ „**: `v4.7.0` -- **์ตœ์‹  ๋ฆด๋ฆฌ์Šค ์ผ์‹œ**: 2026-09-20 (KST) +- **ํ”„๋ ˆ์ž„์›Œํฌ ๋ฒ„์ „**: `v4.7.1` +- **์ตœ์‹  ๋ฆด๋ฆฌ์Šค ์ผ์‹œ**: 2026-09-22 (KST) - **๊ธฐ์ค€ ๋ธŒ๋žœ์น˜**: `main` - **ํ•ต์‹ฌ ์•„ํ‚คํ…์ฒ˜**: - **Terminal ์ƒํƒœ ๋‹จ๋ฐฉํ–ฅ ๋ถˆ๋ณ€์„ฑ (`engine.py`, Issue #6 Phase 1)**: `completed`, `error`, `cancelled` ํ„ฐ๋ฏธ๋„ ์ƒํƒœ ์ง„์ž… ํ›„ ํ›„์† ์ด๋ฒคํŠธ๋‚˜ ์—…๋ฐ์ดํŠธ์— ์˜ํ•œ ๋ฎ์–ด์“ฐ๊ธฐ๋ฅผ ์—„๊ฒฉํžˆ ์ฐจ๋‹จ(Terminal Immutability). `registry.py close` ์„œ๋ธŒ์ปค๋งจ๋“œ ๋ฐ fail-closed ์กฐ๊ธฐ ์ข…๋ฃŒ ๋„์ž…. @@ -22,23 +22,39 @@ ## ๐Ÿงญ ์Šคํ‚ฌ ํŒจํ‚ค์ง€ ๋ฒ„์ „ ๋งคํŠธ๋ฆญ์Šค (Skills Version Matrix) -๋ชจ๋“  8๊ฐœ ์Šคํ‚ฌ์€ YAML frontmatter ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(`author`, `version`, `platforms`, `environments`) ํ‘œ์ค€ํ™”๋ฅผ ํ†ตํ•ด `v4.7.0`๋กœ ๋™๊ธฐํ™”๋˜์–ด ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. +๋ชจ๋“  8๊ฐœ ์Šคํ‚ฌ์€ YAML frontmatter ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(`author`, `version`, `platforms`, `environments`) ํ‘œ์ค€ํ™”๋ฅผ ํ†ตํ•ด `v4.7.1`๋กœ ๋™๊ธฐํ™”๋˜์–ด ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. | ์Šคํ‚ฌ๋ช… | ๋ฒ„์ „ | ์—ญํ•  ๋ฐ ์ฃผ์š” ์ฑ…์ž„ | ์ƒํƒœ | | :--- | :---: | :--- | :---: | -| **`multi-agent-mux-create`** | `4.7.0` | ์—์ด์ „ํŠธ ์„ธ์…˜ ์‹ ๊ทœ ์ƒ์„ฑ ๋ฐ Herdr ์ปจํ…Œ์ด๋„ˆ ๊ฒฉ๋ฆฌ ์Šคํฐ | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-stop`** | `4.7.0` | ๋Œ€ํ™” UUID ์›์ž์  ์บก์ฒ˜ ๋ฐ ์„ธ์…˜ ์•ˆ์ „ ์ข…๋ฃŒ (Graceful Stop) | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-resume`** | `4.7.0` | ์˜จ๋””์Šคํฌ ๋Œ€ํ™” ์ปจํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ Tier-1 ์ดˆ๊ณ ์† ์„ธ์…˜ ๋ณต์› | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-status`** | `4.7.0` | ์‹ค์‹œ๊ฐ„ Herdr ์„ธ์…˜ ๋ฐ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋“œ๋ฆฌํ”„ํŠธ ์Šค๋ƒ…์ƒท ์กฐํšŒ | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-monitor`** | `4.7.0` | YAML โ†” ๋Ÿฐํƒ€์ž„ ์ƒํƒœ ๊ฐ„ ์ž์œจ ์กฐ์ •์ž (Reconciler Loop) | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-delegate-job`** | `4.7.0` | MQTT ์ด๋ฒคํŠธ ์ฑ„๋„ ๊ธฐ๋ฐ˜ ๋น„๋™๊ธฐ ๋‹จ์œ„ ์ž‘์—… ์œ„์ž„ | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-loop`** | `4.7.0` | Planner-Creator-Reviewer 3์ž ์ž์œจ ๊ณ„ํšยท์‹คํ–‰ยทํ”ผ์–ด๋ฆฌ๋ทฐ ๋ฃจํ”„ | โœ… ๋ฐฐํฌ | -| **`multi-agent-mux-orc-onboard`** | `4.7.0` | ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ UUID ๊ฒฉ๋ฆฌ ๋“ฑ๋ก ๋ฐ ์„œ๋ธŒ ์„ธ์…˜ ์˜ค์—ผ ๋ฐฉ์ง€ | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-create`** | `4.7.1` | ์—์ด์ „ํŠธ ์„ธ์…˜ ์‹ ๊ทœ ์ƒ์„ฑ ๋ฐ Herdr ์ปจํ…Œ์ด๋„ˆ ๊ฒฉ๋ฆฌ ์Šคํฐ | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-stop`** | `4.7.1` | ๋Œ€ํ™” UUID ์›์ž์  ์บก์ฒ˜ ๋ฐ ์„ธ์…˜ ์•ˆ์ „ ์ข…๋ฃŒ (Graceful Stop) | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-resume`** | `4.7.1` | ์˜จ๋””์Šคํฌ ๋Œ€ํ™” ์ปจํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ Tier-1 ์ดˆ๊ณ ์† ์„ธ์…˜ ๋ณต์› | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-status`** | `4.7.1` | ์‹ค์‹œ๊ฐ„ Herdr ์„ธ์…˜ ๋ฐ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋“œ๋ฆฌํ”„ํŠธ ์Šค๋ƒ…์ƒท ์กฐํšŒ | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-monitor`** | `4.7.1` | YAML โ†” ๋Ÿฐํƒ€์ž„ ์ƒํƒœ ๊ฐ„ ์ž์œจ ์กฐ์ •์ž (Reconciler Loop) | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-delegate-job`** | `4.7.1` | MQTT ์ด๋ฒคํŠธ ์ฑ„๋„ ๊ธฐ๋ฐ˜ ๋น„๋™๊ธฐ ๋‹จ์œ„ ์ž‘์—… ์œ„์ž„ | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-loop`** | `4.7.1` | Planner-Creator-Reviewer 3์ž ์ž์œจ ๊ณ„ํšยท์‹คํ–‰ยทํ”ผ์–ด๋ฆฌ๋ทฐ ๋ฃจํ”„ | โœ… ๋ฐฐํฌ | +| **`multi-agent-mux-orc-onboard`** | `4.7.1` | ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ UUID ๊ฒฉ๋ฆฌ ๋“ฑ๋ก ๋ฐ ์„œ๋ธŒ ์„ธ์…˜ ์˜ค์—ผ ๋ฐฉ์ง€ | โœ… ๋ฐฐํฌ | --- ## ๐Ÿ“‹ ๋ฒ„์ „๋ณ„ ์ƒ์„ธ ๋ณ€๊ฒฝ ๋‚ด์—ญ (Changelog) +### ๐Ÿš€ `v4.7.1` โ€” Issue #25 ์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ ์žฌ์‚ฌ์šฉ์€ `--plan-file` ๋กœ๋งŒ: ์•”๋ฌต์  ์ž๋™ ๋กœ๋“œ ์ œ๊ฑฐ, ๋นˆ ๊ณ„ํš ๋ฆฌํฌํŠธ๋Š” ์กฐ์šฉํžˆ ๋„˜์–ด๊ฐ€์ง€ ์•Š์Œ (2026-09-22, PR #32) + +> **ํŒจ์น˜ ๋งˆ์ผ์Šคํ†ค (PATCH Release)**: `run_loop.sh` ๋ฅผ `--plan` ์—†์ด ์‹คํ–‰ํ•˜๋ฉด ๋Ÿฌ๋„ˆ๊ฐ€ planner ๋ฅผ ์ž๋™์œผ๋กœ ๊ณ ๋ฅด๊ณ  `.agents/reports//plan-*.md` ์ค‘ mtime ์ด ๊ฐ€์žฅ ์ตœ๊ทผ์ธ ํŒŒ์ผ์„ "์ด๋ฏธ ์ˆ˜๋ฆฝ๋œ ๊ณ„ํš์„œ"๋กœ creator ์—๊ฒŒ ๋„˜๊ธฐ๋˜ ๋ฌธ์ œ(Issue #25)๋ฅผ ๊ณ ์ณค๋‹ค. ์ €์žฅ์†Œ์—๋Š” ๋‹ค๋ฅธ ์ด์Šˆ์˜ ๊ณ„ํš์„œ๊ฐ€ ์ˆ˜์‹ญ ๊ฐœ ์ปค๋ฐ‹๋ผ ์žˆ๊ณ  ์ฒดํฌ์•„์›ƒ ์งํ›„์˜ mtime ์€ ์˜๋ฏธ๊ฐ€ ์—†์–ด, ๋ฌด๊ด€ํ•œ ๊ณ„ํš์ด ๊ตฌํ˜„ ํ”„๋กฌํ”„ํŠธ์— ์‹ค๋ ธ๋‹ค(v4.7.0 ๋ณ‘ํ•ฉ ๋ฃจํ”„์—์„œ๋„ Issue #6 ๊ณ„ํš์„œ๊ฐ€ ์‹ค๋ฆฐ ๊ฒƒ์„ ๊ด€์ธก). ์˜ต์…˜์ด ํ•˜๋‚˜ ๋Š˜์ง€๋งŒ ์ž˜๋ชป๋œ ๊ธฐ๋ณธ ๋™์ž‘์„ ์—†์• ๋Š” ์ˆ˜์ •์ด๋ผ PATCH ๋กœ ์˜ฌ๋ฆฐ๋‹ค. + +#### ๐ŸŒŸ ์ฃผ์š” ๊ฐœ์„  ์‚ฌํ•ญ +1. **์•”๋ฌต์  ๊ณ„ํš ๋กœ๋“œ ์ œ๊ฑฐ (`lib_py/loop/runner.py`, `multi-agent-mux-loop/scripts/run_loop.sh`)**: `--plan` ์—†๋Š” ์‹คํ–‰์€ ์–ด๋–ค ๊ณ„ํš์„œ๋„ ์ฝ์ง€ ์•Š๋Š”๋‹ค. Python ๋Ÿฌ๋„ˆ์™€ ๋ ˆ๊ฑฐ์‹œ ์…ธ ๋Ÿฌ๋„ˆ(`MAM_LOOP_PY=0`) ๋ชจ๋‘์—์„œ mtime ๊ธฐ๋ฐ˜ ์„ ํƒ์„ ์ง€์› ๊ณ , creator ๋Š” ์Šค์Šค๋กœ ๊ณ„ํšํ•œ๋‹ค. ์ฒดํฌํฌ์ธํŠธ์˜ `current_plan` ์€ ์“ฐ๊ธฐ ์ „์šฉ์ด๋ผ ์˜› ๊ณ„ํš์„ ๋˜์‚ด๋ฆฌ๋Š” ๊ฒฝ๋กœ๊ฐ€ ์—†๋‹ค. +2. **`--plan-file ` (Python ๋Ÿฌ๋„ˆ ์ „์šฉ)**: ์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ์˜ ์žฌ์‚ฌ์šฉ์€ ํŒŒ์ผ์„ ๋ช…์‹œํ•  ๋•Œ๋งŒ ํ•œ๋‹ค. ์ƒ๋Œ€๊ฒฝ๋กœ๋Š” **์ œ์–ด ๋ฃจํŠธ ๊ธฐ์ค€**(์›ŒํฌํŠธ๋ฆฌ์—์„œ ๋Œ๋ ค๋„ ๊ฐ™์Œ)์ด๊ณ , ์žก์ด ํ•˜๋‚˜๋„ ๋“ฑ๋ก๋˜๊ธฐ ์ „์— ์ฝ์–ด ๊ฒ€์‚ฌํ•œ๋‹ค(์—†๋Š” ํŒŒ์ผยท๋””๋ ‰ํ„ฐ๋ฆฌยท๋นˆ ํŒŒ์ผยท์ฝ๊ธฐ ์‹คํŒจ๋Š” exit 1). `--plan` ๊ณผ ํ•จ๊ป˜ ์“ธ ์ˆ˜ ์—†๊ณ , `--review-only` ์—์„œ๋Š” ๊ฒฝ๊ณ  ํ›„ ๋ฌด์‹œํ•œ๋‹ค. ๋ ˆ๊ฑฐ์‹œ ์…ธ ๋Ÿฌ๋„ˆ๋Š” ์ด ์˜ต์…˜์„ ๋ฃจํ”„ ๋ฝ ์ „์— ๋ช…์‹œ์ ์œผ๋กœ ๊ฑฐ๋ถ€ํ•œ๋‹ค. +3. **๊ณ„ํš ํ…์ŠคํŠธ ๊ฒ€์‚ฌ ํ•˜๋‚˜๋ฅผ ๋ชจ๋“  ๋กœ๋“œ ๊ฒฝ๋กœ์— (`LoopRunner._plan_text`)**: planner ์˜ ์ฒซ ๋ฆฌํฌํŠธ๊ฐ€ ๋น„์–ด ์žˆ์œผ๋ฉด ๋ฃจํ”„๋ฅผ ๋ฉˆ์ถ˜๋‹ค(๊ณ„ํš ๋‹จ๊ณ„์— ๋น„์šฉ์„ ์“ฐ๊ณ ๋„ ์กฐ์šฉํžˆ ์ž์œจ ๊ณ„ํš์œผ๋กœ ๊ฐ•๋“ฑ๋˜๋˜ ๋ฌธ์ œ). ํ† ๋ก (refine)ยท์žฌ๊ณ„ํš ๋ฆฌํฌํŠธ๊ฐ€ ๋น„์–ด ์žˆ์œผ๋ฉด ๊ฒฝ๊ณ ํ•˜๊ณ  ๊ธฐ์กด ๊ณ„ํš์„ ์œ ์ง€ํ•œ๋‹ค. +4. **๋ฌธ์„œ**: loop SKILL.md ์˜ ์˜ต์…˜ ํ‘œยทWorkflowยท"๊ณ„ํš์„œ๊ฐ€ ๋น„์–ด ์žˆ์„ ๋•Œ" ์ ˆ. + +#### โœ… ํ’ˆ์งˆ ๊ฒ€์ฆ +- **์‹ ๊ทœ ํ…Œ์ŠคํŠธ 17๊ฐœ** (`tests/test_issue25_plan_reuse.py`, P1โ€“P11): ์˜ต์…˜ ์—†๋Š” ์‹คํ–‰์ด ์Šน๊ฒฉ๋œ ๊ณ„ํš์„œ๋ฅผ ์ฝ์ง€ ์•Š์Œ(Pythonยท์…ธ), `--plan-file` ์˜ ์ œ์–ด ๋ฃจํŠธ ๊ธฐ์ค€ ํ•ด์„ยท์‹คํŒจ ๊ฒฝ๋กœยท`--plan`/`--review-only` ์กฐํ•ฉยท์…ธ ๋Ÿฌ๋„ˆ์˜ ๊ฑฐ๋ถ€, ๋นˆ planner ๋ฆฌํฌํŠธ์˜ ์ค‘๋‹จ, ๋นˆ refine ์˜ ๊ธฐ์กด ๊ณ„ํš ์œ ์ง€. ๋ณ‘ํ•ฉ ์›Œํฌ์ŠคํŽ˜์ด์Šค ๋ฆฌ๋ทฐ์—์„œ 17๊ฑด ์ค‘ 13๊ฑด์ด ์ˆ˜์ • ์ „ ์†Œ์Šค์—์„œ ์‹คํŒจํ•จ์„ ํ™•์ธ. +- **๋ฆฌ๋ทฐ**: ์ž‘์„ฑ ์›Œํฌ์ŠคํŽ˜์ด์Šค ๋ฃจํ”„(`--worktree --base --review-only`) 1ํšŒ์ฐจ @5fa5923 claudeยทagyยทopencode PASS, grokยทcodex NOT PASS(์ƒ๋Œ€๊ฒฝ๋กœ `--plan-file` ์ด ์‹คํ–‰ cwd ๊ธฐ์ค€์œผ๋กœ ํ•ด์„) โ†’ 1e82651 ๋กœ ์ •์ •, 2ํšŒ์ฐจ 5์ธ ์ „์› PASS. ๋ณ‘ํ•ฉ ์›Œํฌ์ŠคํŽ˜์ด์Šค์—์„œ PR head ๋ฅผ detached ์›ŒํฌํŠธ๋ฆฌ์— ๋ฐ›์•„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์žฌ๊ฒ€ํ† : @1e82651 claudeยทagyยทgrokยทcodex 4์ธ ์ „์› PASS(1ํšŒ์ฐจ, identity 4๊ฑด ๋ชจ๋‘ base 6fc9194 โ†’ head 1e82651, evidence review-tree). ๋ฆฌํฌํŠธ์™€ identity ์‚ฌ์ด๋“œ์นด๋Š” `.agents/reports//`. +- **์ „์ฒด ์Šค์œ„ํŠธ (๋ณ‘ํ•ฉ ์›Œํฌ์ŠคํŽ˜์ด์Šค, ์ž์ฒด venv ๊ฐ€ ์žˆ๋Š” ์›ŒํฌํŠธ๋ฆฌ @1e82651)**: 1037 ํ†ต๊ณผ / 1 skip / ์‹คํŒจ 0 (35๋ถ„ 26์ดˆ, ๋ฆฌ๋ทฐ ๋ฃจํ”„์™€ ๋ณ‘ํ–‰). +- **๋น„์ฐจ๋‹จ ํ›„์†**: ๋ ˆ๊ฑฐ์‹œ ์…ธ ๋Ÿฌ๋„ˆ์˜ plan ๋ชจ๋“œ ์ฝ๊ธฐ์—๋Š” ๋นˆ ๊ณ„ํš์„œ ๊ฒ€์‚ฌ๊ฐ€ ์—†์Œ(E1), `--plan-file` ์‹คํ–‰์—์„œ `[ESCALATE: PLANNER]` ๊ฐ€ ์žฌ๊ณ„ํš์œผ๋กœ ์ด์–ด์ง€์ง€ ์•Š์Œ(E2, ๊ธฐ์กด ๊ฒŒ์ดํŠธ), ๋ฆฌ๋ทฐ ๊ฒฉ๋ฆฌ ์›ŒํฌํŠธ๋ฆฌ์— `.venv` ๊ฐ€ ์—†์–ด `run_loop.sh` ๋ฅผ ํ•˜์œ„ ํ”„๋กœ์„ธ์Šค๋กœ ๋„์šฐ๋Š” ํ…Œ์ŠคํŠธ๋Š” `AGENT_PYTHON_BIN` ์—†์ด๋Š” ์‹คํŒจ(E3, #21 ํ•ญ๋ชฉ 5 ์šด์˜ ํ›„์†), Phase 1 ์˜ `getmtime` ๊ฒฝํ•ฉ(E4), ๊ณต๋ฐฑ์ด ๋“  ๊ฒฝ๋กœ ์ „์šฉ ํ…Œ์ŠคํŠธ ์—†์Œ. + ### ๐Ÿš€ `v4.7.0` โ€” Issue #21 ์›ŒํฌํŠธ๋ฆฌ ์šด์˜ ๋ชจ๋ธ 2๋‹จ๊ณ„: ์›ŒํฌํŠธ๋ฆฌ ํ—ฌํผ, ๋ฆฌ๋ทฐ identity, ์ˆ˜์šฉ ์‚ฌ๋ก€ A1โ€“A8, #20 ํ…Œ์ŠคํŠธ ๊ฒฉ๋ฆฌ, #27, #28 ํ˜ธ์ŠคํŠธ ์ด์‹์„ฑ (2026-09-20, PR #29) > **๋งˆ์ด๋„ˆ ๋งˆ์ผ์Šคํ†ค (MINOR Release)**: ์›ŒํฌํŠธ๋ฆฌ ์šด์˜ ๋ชจ๋ธ(#21, `docs/design/worktree-creator-model.md`)์˜ ์ž‘์—… ํ•ญ๋ชฉ 4ยท5ยท7 ์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. ์ด์Šˆ๋ณ„ ์›ŒํฌํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์ง€์šฐ๋Š” ํ—ฌํผ 2๊ฐœ, ๋ฆฌ๋ทฐ ๋ผ์šด๋“œ๋ฅผ `(loop_id, base, head, tree)` ์— ๋ฌถ๋Š” ๋ฆฌ๋ทฐ identity ์™€ ๋ฃจํ”„ ์˜ต์…˜ 2๊ฐœ(`--review-isolation`, `--remote-review`), ์ˆ˜์šฉ ์‚ฌ๋ก€ 8๊ฑด์ด ์ถ”๊ฐ€๋˜์–ด MINOR ๋กœ ์˜ฌ๋ฆฐ๋‹ค. ํ•ญ๋ชฉ 8(๋‹ค์ค‘ ๋ฃจํ”„ยท๋ฆฌ๋ทฐ์–ด ์Šค์ผ€์ค„๋Ÿฌ)์€ ๋ณด๋ฅ˜๋กœ ๋‚จ์•„ #21 ์€ ์—ด์–ด ๋‘”๋‹ค. ํ•จ๊ป˜ #20(ํ…Œ์ŠคํŠธ๊ฐ€ ์‹ค์ œ `.mam` ์„ ์˜ค์—ผ), #27(`.gitignore` ๊ด€๋ฆฌ ๋ธ”๋ก์˜ `.venv`), #28(Linux/py3.14 ํ˜ธ์ŠคํŠธ์˜ ํ…Œ์ŠคํŠธ ์‹คํŒจ 33๊ฑด)์„ ๋‹ซ๋Š”๋‹ค.