Files
company-haness/.claude/tests/test_p1_lens.py
T

93 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""P1-A: lens 다양성 ≠ domain/sub-specialty 커버리지 (리뷰 finding #12).
lens_cap이 2축(lens 다양성 × sub-specialty 커버리지)으로 판정하는지 검증한다.
- 아키텍트 7명(전부 LENS-TECH지만 distinct sub-specialty)이 standard에서 통과(정확한 회귀).
- 같은 role 2회는 여전히 위반(같은/미분화 sub-specialty 중복).
- tier distinct-sub-specialty 상한 초과는 위반(fan-out 폭 가드).
- heavy는 permissive.
- case-insensitive (registry는 UPPER, 호출은 어느 case든).
실행: CLAUDE_PROJECT_DIR="$PWD" python3 .claude/tests/test_p1_lens.py
"""
import os
import subprocess
import sys
ROOT = os.environ.get("CLAUDE_PROJECT_DIR") or os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)
HOOK = os.path.join(ROOT, ".claude", "hooks", "lens_cap.py")
_fail = 0
def check(name, cond):
global _fail
print(("ok " if cond else "FAIL ") + "- " + name)
if not cond:
_fail += 1
def rc(tier, roles):
return subprocess.run(
[sys.executable, HOOK, "--tier", tier, "--roles", roles],
capture_output=True, text=True,
).returncode
print("== P1-A lens_cap 2축(lens × sub-specialty) ==")
ARCH7 = "arch-ea,arch-solution,arch-app,arch-tech,arch-it,arch-sysanalyst,arch-swat"
# 1) 정확한 회귀: 아키텍트 7명(전부 LENS-TECH, 서로 다른 sub-specialty) → standard 통과.
check("7 distinct architects @ standard -> 0 (finding #12 회귀, was 2)",
rc("standard", ARCH7) == 0)
# case-insensitive: 대문자 role-id도 동일하게 통과.
check("7 distinct architects (UPPER) @ standard -> 0 (case-insensitive)",
rc("standard", ARCH7.upper()) == 0)
# 2) 같은 role 2회 → 같은 sub-specialty 중복 → 여전히 위반.
check("same role twice @ standard -> 2 (undifferentiated duplicate)",
rc("standard", "arch-app,arch-app") == 2)
check("distinct pair + one dup role @ standard -> 2",
rc("standard", "arch-app,arch-tech,arch-app") == 2)
# 3) tier distinct-sub-specialty 상한 초과 → 위반 (light 상한=3, standard 상한=8).
check("3 distinct sub-specialties @ light (cap 3) -> 0 (경계 이내)",
rc("light", "arch-ea,arch-solution,arch-app") == 0)
check("4 distinct sub-specialties @ light (cap 3) -> 2 (상한 초과)",
rc("light", "arch-ea,arch-solution,arch-app,arch-tech") == 2)
check("9 distinct LENS-TECH sub-specialties @ standard (cap 8) -> 2",
rc("standard", ARCH7 + ",arch-data,data-engineer") == 2)
# 4) heavy → permissive(무엇이든 통과).
check("heavy same role twice -> 0 (permissive)",
rc("heavy", "arch-app,arch-app") == 0)
check("heavy 9 distinct LENS-TECH -> 0 (permissive)",
rc("heavy", ARCH7 + ",arch-data,data-engineer") == 0)
# 5) 서로 다른 lens는 서로 영향 없음.
check("distinct lenses (PROD-PM + UX-RESEARCHER) @ standard -> 0",
rc("standard", "prod-pm,ux-researcher") == 0)
# 6) 같은 lens라도 서로 다른 sub-specialty 2명은 통과(진짜 중복 아님).
# (이 케이스가 test_enforcement.py의 'standard dup-lens SEC-ENGINEER,SEC-APPSEC->2'를 뒤집는다: 이제 0.)
check("2 distinct security sub-specialties @ standard -> 0 (진짜 중복 아님)",
rc("standard", "sec-engineer,sec-appsec") == 0)
check("2 distinct product sub-specialties (PM vs TPO) @ standard -> 0",
rc("standard", "prod-pm,prod-tpo") == 0)
check("2 distinct design sub-specialties (product vs platform) @ standard -> 0",
rc("standard", "des-prod,des-platform") == 0)
# 7) 미등록 role은 lens 판별 불가·무시 → 위반 아님(위반 전용은 아님).
check("unknown role ignored @ standard -> 0",
rc("standard", "not-a-real-role,arch-app") == 0)
print()
if _fail:
print(f"FAILED: {_fail}")
sys.exit(1)
print("ALL PASS")
sys.exit(0)