Files
multi-agent-mux/.agents/reports/planner-reviewer-claude-01/report-5e43d80f.md
T
Godopu 97fb1d254b docs(layout): add 2xK layout improvement plan and multi-agent review reports
- Add Rev.2 authoritative plan detailing root causes and 2xK decision table
- Add Phase 1 & 2 review reports from Claude (planner/reviewer) and Cline (reviewer)
2026-08-26 15:10:08 +09:00

9.7 KiB
Raw Blame History

🔍 Cross Review — Job 5e43d80f: Layout Engine 2×K 구현

  • Reviewer: planner-reviewer-claude-01
  • 대상: W1~W5 (layout.py, lib.sh:435, .mam.env.example, 테스트 3파일)
  • 검증: BSP 시뮬레이터 실행 + 헤드리스 궤적 실행 + pytest 전체 393건 실행

이해충돌 고지: 본 구현의 사양(layout_engine_improvement_plan.md Rev.2)은 제가 Planner 로 작성했습니다. 아래는 타인이 작성한 코드가 그 사양을 충족하는가에 대한 검증이며, 사양 자체의 타당성에 대한 독립 검증이 아닙니다. §4 의 F-1 은 실제로 제 사양의 결함이며 그렇게 명시합니다.


1. 핵심 목표 달성 — 실측 확인

BSP 세분할 시뮬레이터로 N=1→5 궤적을 실행했습니다.

N=1  [p1 277x78]
N=2  split right on p1  (new_column_right)
     p1 138x78 / p2 139x78                      widths=[138,139] heights=[78]  balanced=True
N=3  split down  on p1  (fill_column)
     p1 138x39 / p3 138x39 / p2 139x78          (전이 상태 — 정상)
N=4  split down  on p2  (fill_column)
     p1 138x39 / p3 138x39 / p2 139x39 / p4 139x39
     widths=[138,139] heights=[39]              balanced=True   ← 🎯 깨끗한 2×2
N=5  OVERFLOW (grid_capacity_reached) → 새 워크스페이스

4 에이전트 2×2 목표 달성. Rev.1 이 진단한 R-1 왜곡(N=4 에서 widths {138,139,277}, heights {19,20,39})이 완전히 해소되었습니다.

1.1 GUI ↔ 헤드리스 패리티 (C-1 처방 검증)

headless n=1: right    target=p1  reason=new_column_right
headless n=2: down     target=p1  reason=fill_column
headless n=3: down     target=p2  reason=fill_column
headless n=4: overflow target=p4  reason=grid_capacity_reached

GUI 와 방향·순서가 완전히 일치하며, 타깃도 p1 → p2열을 번갈아 갑니다(§4.2 panes[n - max_columns] 명세대로). 홀짝(n % 2) 로직은 완전히 제거되었습니다. creator-grok-01 이 제기했던 "n=3 갈라짐"이 원천 차단되었습니다.


2. W1~W5 항목별 검증

W 항목 상태
W1 단일 결정표 공유 _decide / _decide_headless 분리, compute_2xk_layout 은 관측→위임 2단
W2 N=1 → right _full_height_pane 경유 new_column_right
W3 _full_height_pane len(col)!=1 → None, area_h<=0 폴백, tol=2
W4 캡 3중 배선 전부 — 아래 §2.1
W5 테스트 사양의 8개 테스트 전건 구현

2.1 W4 — Rev.2 가 지적한 이중 누락이 모두 해소됨

# layout.py:235-236  ← _env_int 에 default 부여 (이전엔 None 반환)
--max-cols  default=_env_int("MAM_MAX_COLS", "MAM_MAX_PANE_COLS", default=2)
--max-rows  default=_env_int("MAM_MAX_ROWS", "MAM_MAX_PANE_ROWS", default=2)
# lib.sh:435  ← 이전엔 --max-cols 를 아예 넘기지 않았음
--max-cols "${MAM_MAX_PANE_COLS:-2}" --max-rows "${MAM_MAX_PANE_ROWS:-2}"
# .mam.env.example:147-153  ← C-5 문서 자체 불일치("unset -> no cap" vs "=3")도 정정
#default: 2  /  MAM_MAX_PANE_COLS=2  +  MAM_MAX_PANE_ROWS=2 신규 블록

추가로 compute_2xk_layout 진입부에 max_columns is None → 2 방어가 들어가 네 번째 경로까지 막았습니다. 사양보다 견고합니다.

test_max_cols_default_reaches_cli_pathtest_lib_sh_passes_max_cols_and_rows 가 이 배선을 계약으로 고정합니다 — Rev.2 가 "이게 없으면 전체가 프로덕션에서 무효"라고 경고한 지점이라 특히 중요합니다.

2.2 기존 테스트 갱신 처리

테스트 처리
test_1_pane_split_downtest_1_pane_split_right 개명 + 계약 갱신
test_2_panes_to_3_panes_new_column_righttest_2_panes_fill_left_column_down
test_4_panes_to_5_panes_new_column..._overflows_at_capacity
test_headless_max_columns_growth_guard 옛 홀짝 단언(n=2→right, headless_odd_down) 전면 재작성
test_b19_headless_layout_does_not_overflow tall 케이스 재해석 + wide-tall 케이스 신설로 커버리지 보존

test_b19 처리가 특히 좋습니다 — 단언만 뒤집지 않고 비오버플로 경로를 검증하는 새 픽스처를 추가해 커버리지를 유지했습니다.

2.3 테스트 실행

pytest tests/ -q  →  393 passed in 511.60s

실패 0건. (직전 리뷰에서 관측된 test_d23 nats 태그 불일치도 해소되었습니다.)


3. 🟡 F-2 — MAX_*=0 이 "무제한"이 아니라 "전면 차단"입니다

_env_int 는 J-1 계약에 따라 명시적 0 을 보존합니다. 그 결과:

설정 실측 결과
max_columns=0, max_rows=2 down / fill_column
max_columns=2, max_rows=0 right → 이후 overflow
max_columns=0, max_rows=0 overflow / grid_capacity_reached (즉시)
헤드리스, 둘 중 하나라도 0 n >= 0 이 항상 참 → 영구 overflow

문제는 같은 설정 파일 안의 의미 충돌입니다:

# .mam.env.example
# MAM_MIN_PANE_ROWS=0     ← "Set to 0 to disable vertical row constraints"
# MAM_MAX_PANE_ROWS=2     ← 0 을 넣으면 "용량 0" = 모든 세션이 새 워크스페이스

MIN_*=0 이 "제약 해제"를 뜻하므로, 운영자가 MAX_*=0 을 "상한 없음"으로 읽는 것은 자연스럽습니다. 그러나 실제로는 에이전트마다 워크스페이스가 무한 생성됩니다.

개선 방향:

if max_columns is None or max_columns <= 0:
    max_columns = 2          # 또는 '무제한' 의도라면 sys.maxsize
if max_rows is None or max_rows <= 0:
    max_rows = 2

.mam.env.example 에도 0 은 허용되지 않습니다(최솟값 1) 한 줄을 덧붙이십시오. 비차단이나 오설정 시 피해가 크고 되돌리기 어렵습니다(생성된 워크스페이스가 남음).


4. 🟠 F-1 — 세로 전용 적층 능력이 사라졌습니다 (제 사양의 결함)

현상 (실측)

min_cols=60 에서 단일 페인 폭별 결정:

× 높이 결과
80×60 overflow / column_width_overflow
100×60 overflow
119×60 overflow
120×60 right

폭 120 미만이면 N=1 에서 즉시 오버플로합니다. 그러나 80×60 을 세로로 쌓으면 80×30 페인 2개가 되고, 두 페인 모두 폭 80 ≥ min_cols 60 을 만족합니다. 즉 사용 가능한 배치를 거부하고 새 워크스페이스를 만듭니다.

원인 — 폭 게이트가 폴스루하지 않음

if len(cols) < max_columns:
    fh = _full_height_pane(cols[-1], area_h)
    if fh is not None:
        if fh.width > 0 and fh.width // 2 < min_cols:
            return _overflow("column_width_overflow", fh)   # ← 즉시 반환
        return _right("new_column_right", fh)
# ② 세로 채우기에 도달하지 못함

새 엔진은 1열 × K행 배치를 구조적으로 만들 수 없습니다. 구 엔진의 single_pane_split_down 이 담당하던 경로가 사라졌습니다.

책임 소재

이것은 구현 결함이 아니라 제 사양의 결함입니다. Rev.2 §4.1 의사코드가 정확히 return OVERFLOW("column_width_overflow", fh) 로 적혀 있었고, 구현은 그대로 따랐습니다. 폭 부족 시 세로 폴백을 명시하지 않은 것은 제 누락입니다.

실무 영향

기본값 min_cols=15 에서는 폭 30 미만이어야 발동하므로 사실상 도달 불가합니다. 다만 MAM_MIN_PANE_COLS 기본값은 60 → 40 → 15 로 변해 왔고, .mam.envgitignore 대상이라 자동 마이그레이션되지 않습니다. 구 설정(=60)을 지닌 기존 설치는 120칸 미만 터미널에서 에이전트마다 워크스페이스가 하나씩 생기게 됩니다.

개선 방향 (구체)

폭 게이트를 폴스루로 바꿉니다:

if len(cols) < max_columns:
    fh = _full_height_pane(cols[-1], area_h)
    if fh is not None and not (fh.width > 0 and fh.width // 2 < min_cols):
        return _right("new_column_right", fh)
    # 폭이 새 열을 감당하지 못하면 ②(세로 채우기)로 내려간다

이렇게 하면 80×60/min_cols=60 은 down / fill_column80×30 2개가 되고, 폭·행이 모두 소진된 뒤에야 ③에서 오버플로합니다. 회귀 가드:

def test_narrow_terminal_falls_back_to_vertical_stacking():
    d = compute_2xk_layout(_one(80, 60), min_cols=60)
    assert d.direction == "down" and not d.is_overflow

주의: 이 변경은 test_b19 의 tall 케이스 단언을 다시 뒤집습니다(현재 overflowdown). 원래 그 테스트가 지키던 계약이 바로 이 세로 폴백이었으므로, 사실상 원복입니다.


5. 판정

항목 판정
W1~W5 사양 충족 전건. W4 는 사양보다 견고
4 에이전트 2×2 시뮬레이터 실측
GUI/헤드리스 패리티 방향·타깃 모두 일치
전체 테스트 393 passed, 0 failed
F-1 세로 폴백 상실 🟠 제 사양 누락 — 후속 수정
F-2 MAX_*=0 함정 🟡 후속 수정

구현은 승인된 사양을 정확히, 그리고 일부는 더 견고하게 충족했으며 핵심 목표가 실측으로 증명되었습니다. F-1·F-2 는 이번 변경이 만든 새 결함이 아니라 사양의 미비로, 각각 3~5줄 수정으로 해소됩니다. 설계 재작업 사유가 아니므로 [ESCALATE: PLANNER] 는 부여하지 않습니다.

후속 잡 권고: F-1(세로 폴백) + F-2(0 값 클램프) 를 묶어 한 커밋으로. F-1 은 구 .mam.env 를 지닌 기존 설치에 실제 영향이 있으므로 우선순위가 높습니다.

[VERDICT: PASS]