Files
multi-agent-mux/.agents/reports/planner-reviewer-codex-01/report-f275a259.md
T
GodopuandClaude Opus 5.5 65dc7fde82 release(v4.8.4): bump framework and eight skills to 4.8.4 in lockstep; archive PR #47 reviews (two rounds)
The .claude/skills check accepts both local layouts and fails on a dangling
link. Review: round 1 (@e1ed270) claude agy grok PASS, codex NOT PASS (a
dangling top-level link was skipped); fixed in 150b493; round 2 4/4 PASS.
Reports and the round-2 identity sidecars go to .agents/reports/<session>/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-04 13:54:57 +09:00

6.8 KiB
Raw Blame History

PR #47 리뷰 — f275a259

NOT PASS. 단일 링크와 스킬별 링크 디렉터리를 모두 받는 수정은 동작한다. 다만 .claude/skills 자체가 깨진 심볼릭 링크이면 부재로 오인해 skip하는 경계 사례가 남아 있다. 작은 테스트 수정으로 해결할 수 있으며 제품 코드 변경이나 재계획은 필요 없다.

Identity와 범위

  • loop: loop-20261004T043243Z-baf133
  • base: 6af4a796b1bdce3b2e929b7a45a8a22d66b36855
  • head: e1ed2708d835d712f5f3a9dfd51b8f66ca1ac447
  • tree: 2f781e0db4df9a3082b4f55e69c42118868b18a1
  • 검증 cwd: /var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261004T043243Z-baf133/1

HEAD/tree 일치, 시작·종료 시 git status clean. 변경 파일은 tests/test_issue42_skill_blocks.py 하나이며 제품 코드·버전 변경은 없다. git diff --check 6af4a79 HEAD 통과.

R1 — P2: 깨진 최상위 링크를 skip하지 말 것

근거: tests/test_issue42_skill_blocks.py:245–:248.

Path.exists()는 링크 자체가 아니라 대상을 따라 검사하므로 dangling symlink에서 False다. 따라서 .claude/skills가 존재하는 잘못된 링크여도 :245의 부재 분기가 실행돼 :247의 symlink 검증까지 도달하지 않는다. 정상적인 “이 워크트리에 로컬 배치가 없음”과 “로컬 배치가 있으나 깨짐”을 구별하지 못한다.

재현: 검증 트리의 원래 .claude/skills가 없음을 확인하고, 그 경로에 존재하지 않는 absent-skills-target을 가리키는 임시 링크를 만든 뒤 해당 pytest node를 실행했다. 실행 후 링크를 삭제했다.

PYTHONDONTWRITEBYTECODE=1 /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.venv/bin/python -m pytest -p no:cacheprovider -q --basetemp=/tmp/f275a259-broken_single tests/test_issue42_skill_blocks.py::test_claude_skills_link_resolves_to_agents_skills
  • 기대: 잘못된 로딩 경로이므로 fail, nonzero.
  • 실제: 1 skipped, rc 0. 반면 디렉터리 안 깨진 개별 링크는 정상적으로 fail한다.
  • 영향: 모든 프로젝트 스킬의 진입 경로가 끊겨도 “워크트리에 없음”으로 숨겨져 CI/검증이 성공한다.
  • 수정 방향: 부재 skip을 if not link.exists() and not link.is_symlink():로 한정하거나 symlink 검증을 부재 검사보다 먼저 수행한다. 완전 부재는 계속 skip하고, dangling root link는 실패해야 한다. 부재/정상 단일 링크/정상 개별 링크/깨진 최상위 링크를 회귀 사례로 남긴다.

메모리상으로 위 조건만 바꾼 같은 함수에 대해 완전 부재는 SKIP, 깨진 링크는 AssertionError가 되는 것을 확인했다. 체크아웃 코드는 수정하지 않았다.

이 exists() 선행 분기는 이전 버전에도 있었다. 이번 변경이 새로 만든 회귀라고 주장하지 않는다. 그러나 브리프가 명시적으로 요청한 깨진 링크 검토에서 확인된 허점이고, 이 함수가 두 배치의 경로 무결성을 검증하도록 수정되는 범위 안에서 해결할 수 있으므로 반려 사유로 남긴다.

실행 결과

원래 워크트리 배치(로컬 .claude/skills 없음)에서 지정 모듈 실행:

PYTHONDONTWRITEBYTECODE=1 /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.venv/bin/python -m pytest -p no:cacheprovider -q --basetemp=/tmp/f275a259-selected tests/test_issue42_skill_blocks.py

31 passed, 1 skipped in 0.06s, rc 0. 이 기본 실행은 로컬 링크 분기를 검증하지 않으므로 아래 임시 배치 탐침을 별도로 실행했다.

임시 배치 실제 pytest 결과 판단
.claude/skills 완전 부재 1 skipped, rc 0 정상
8개 스킬별 올바른 링크 1 passed, rc 0 정상; base 함수는 같은 배치에서 AssertionError
위 배치 + lib.sh/lib_py 링크 및 notes.txt 1 passed, rc 0 정상
개별 링크 하나가 다른 스킬을 가리킴 1 failed, rc 1 정상 거부
개별 링크 하나가 깨짐 1 failed, rc 1 정상 거부
단일 링크 → .agents/skills 1 passed, rc 0 정상
단일 링크 → 다른 기존 디렉터리 1 failed, rc 1 정상 거부
단일 링크 → 존재하지 않는 대상 1 skipped, rc 0 R1
일반 파일 1 failed, rc 1 정상 거부
빈 디렉터리 1 failed, rc 1 정상 거부

탐침 스크립트: /tmp/f275a259-layout-probes.py; 결과: /tmp/f275a259-layout-probes.log. 위 cwd에서 PYTHONDONTWRITEBYTECODE=1 <위 Python> /tmp/f275a259-layout-probes.py로 재현한다. 스크립트는 원래 경로가 없는지 먼저 확인하고 자신이 만든 임시 배치만 finally에서 정리한다. 기대한 부정 사례의 pytest 실패는 제품 스위트 실패 수치에 합산하지 않았다.

나머지 검토 항목

  • 실제 본 체크아웃: 읽기 전용 조사에서 .claude/skills는 디렉터리이며 8개 스킬 링크와 lib.sh/lib_py 링크가 있다. 8개 스킬의 resolve 결과는 각각 본 체크아웃의 .agents/skills/<skill>과 정확히 일치했다. 수정의 동기가 된 정상 배치를 지원한다.
  • 빈 SKILL_NAMES: 대상 함수만 메모리상 SKILL_NAMES=[]로 실행하면 for-loop가 비어 통과한다. 그러나 같은 모듈의 test_inventory_covers_eight_skills가 8개를 강제해 전체 모듈은 실패한다. 현재 모듈 단위 실행에는 침묵하는 성공이 없으므로 별도 반려 사유는 아니다. 대상 node를 단독 운영할 때까지 방어하려면 nonempty 단언을 추가할 수 있다.
  • 여분 항목: framework 8개를 확인하는 테스트에서 lib.sh/lib_py 등 여분 항목을 금지하지 않는 것은 적절하다. Claude Code 공식 문서는 프로젝트 스킬을 .claude/skills/<skill-name>/SKILL.md로 설명하며 스킬 폴더의 symlink를 지원한다. 일반 helper 파일·SKILL.md 없는 helper 디렉터리를 framework 스킬로 취급할 필요는 없다. 다만 이 테스트는 다른 사용자 스킬 전체를 감사하지 않으므로 docstring의 “each skill Claude Code loads”는 “each framework skill” 정도로 좁히면 더 정확하다. 공식 Claude Code 스킬 로딩 문서.
  • 과도한 엄격성: 스킬 디렉터리의 내용 복사본은 같은 resolve 대상이 아니므로 거부된다. 브리프가 두 링크 배치만 지원하려는 계약에 맞는다. 다른 추가 사용자 스킬의 존재는 허용된다.

검증 트리 안의 임시 .claude/skills는 모두 삭제했다. 본 체크아웃의 배치를 변경하지 않았으며 제품 코드·실제 .mam.env·실제 agent/herdr 상태를 건드리지 않았다. 실제 .mam 쓰기는 지시된 잡 lifecycle과 이 최종 리포트에 한정했다.

[VERDICT: NOT PASS]