# task-1431.1 완료 보고서: Phase 2 — 모듈화 린터/훅 + module-registry 완성

## SCQA

**S**: Phase 0에서 config 단일 소스(SSoT) 기반이 구축되고, Phase 1~1.5에서 dispatch.py와 scripts/tests/ 54개 파일의 하드코딩이 config/env 참조로 전환되었다.

**C**: 전환 완료 후에도 새로운 코드에서 하드코딩이 재발하는 것을 방지할 수 없었다. module-registry도 Phase 0의 초기 5개 소스만 등록된 상태로 Phase 1~1.5 결과가 반영되지 않았다.

**Q**: 자동 감지/차단 방어 체계(pre-commit hook + 수동 검증 도구)와 정확한 registry로 하드코딩 재발을 시스템 차원에서 방지할 수 있는가?

**A**: 4개 파일 생성/업데이트 완료. pre-commit hook은 staged diff의 추가 라인만 검사하여 4가지 하드코딩 패턴을 감지하고, 오탐 방지 규칙(주석/docstring/config 제외, tests/ WARNING 처리)을 적용한다. modularity-check.py는 scan(전체 스캔)과 verify(registry 정합성 검증) 2개 커맨드를 지원하며, verify 11 sources 전체 통과(실패 0건). module-registry는 v2.0으로 11개 소스 등록 완료. bash 문법 검증 통과, pyright 에러 0건.

---

## 산출물

- `/home/jay/workspace/hooks/modularity-lint.sh` (신규, 306행)
- `/home/jay/workspace/tools/modularity-check.py` (신규, 527행)
- `/home/jay/workspace/config/module-registry.json` (업데이트, v1.0 → v2.0)
- `/home/jay/workspace/.pre-commit-config.yaml` (업데이트, modularity-lint 추가)

## 작업 내용

### 1. hooks/modularity-lint.sh (pre-commit hook)
- `git diff --cached`에서 staged 변경 라인만 검사 (파일 전체 아닌 추가 라인만)
- 4가지 하드코딩 패턴 감지:
  - ChatID `6937032012` → `os.environ.get("COKACDIR_CHAT_ID")` 제안
  - 절대경로 `/home/jay/workspace` → `config.get_path()` 또는 `WORKSPACE_ROOT` 제안
  - DQ 폰트 사이즈 `84px/64px/40px` → `from tools.dq_rules import DQ_RULES` 제안
  - 팀명 `dev[N]-team` → `config.get_constant("teams")` 제안
- 오탐 방지: 주석/docstring/noqa 제외, config/hooks/memory 디렉토리 제외, .md/.json/.yaml 제외
- tests/ 파일은 WARNING만 (커밋 차단 안함)
- 위반 시 exit 1 (차단), WARNING만이면 exit 0 (통과)

### 2. tools/modularity-check.py (수동 검증 도구)
- `scan` 커맨드: 전체 코드베이스에서 하드코딩된 값 스캔, `--json` 옵션 지원
- `verify` 커맨드: module-registry.json의 used_by vs 실제 코드 참조 대조 검증
- Python 3 표준 라이브러리만 사용 (외부 의존성 없음)
- ast.parse로 docstring 범위 정확 감지 (SyntaxError 시 triple-quote fallback)
- 디렉토리 패턴 (`scripts/*.py (27 files)`) 형식 지원

### 3. config/module-registry.json (v1.0 → v2.0)
- 6개 신규 소스 추가: thresholds, cokacdir_key, team_to_bot, bots, work_levels, font_sizes
- 기존 소스 used_by 업데이트: chat_id (5→12개), workspace_root (4→패턴 포함), dq_rules 참조 수정
- 부정확한 used_by 제거: CampaignSections.js(palette 미참조), dispatch.py(work_levels 미참조)
- used_by_convention 규칙 추가 (10개 이상 → 디렉토리 패턴)

### 4. .pre-commit-config.yaml
- `local` repo 엔트리로 modularity-lint hook 추가
- `types: [python]`, `pass_filenames: false` 설정

## 셀프 QC

- [x] 1. 영향 파일: 신규 4개 파일 생성/수정만. 기존 코드 수정 없음
- [x] 2. 엣지 케이스: git repo 아닌 환경에서 lint hook graceful 종료, ast parse 실패 시 triple-quote fallback, 빈 diff 시 즉시 exit 0
- [x] 3. 작업 지시 일치: 4개 산출물 모두 지시서대로 구현
- [x] 4. 에러 처리/보안: UnicodeDecodeError try/except, 파일 미존재 처리, 민감 정보 없음
- [x] 5. 테스트: verify 11 sources 전체 통과 (실패 0건), scan 정상 동작 확인, bash -n 문법 통과, pyright 에러 0건
- [x] 6. 이슈 해결: 5건 발견 및 해결 (아래 상세)
- [x] 7. 아키텍처 원칙: DRY (패턴 정의 중앙 집중), 단일 책임 (scan/verify 분리)
- [x] 8. 인터페이스 변경: 없음 (신규 도구만)

## 발견 이슈 및 해결

### 자체 해결 (5건)
1. **Pyright: end_lineno Optional 타입** — `ds_node.end_lineno or ds_node.lineno` fallback 추가
2. **Pyright: total_checks 미사용 변수** — 불필요한 변수 제거
3. **자기참조 오탐** — hooks/와 modularity-check.py 자체에 패턴 문자열이 포함되어 자기 자신 감지 → hooks/ EXCLUDE_DIRS 추가 + noqa 주석
4. **registry glob 패턴 처리** — `scripts/*.py (27 files)` 형식을 verify에서 인식하도록 패턴 처리 로직 추가
5. **SOURCE_REF_PATTERNS 불충분** — Phase 1.5에서 os.environ.get() 패턴으로 전환한 파일들이 미감지 → 환경변수명, 직접 참조 등 패턴 확장 + generic fallback 제거(오탐 방지)

### 범위 외 미해결 (1건)
1. **scan 3146건 위반** — Phase 1~1.5가 dispatch.py/scripts/tests만 전환. 나머지 파일(dashboard/, utils/, tools/ 등)의 하드코딩은 향후 Phase에서 전환 예정. 범위 외 사유: 본 작업은 방어 체계 구축이며, 기존 하드코딩 전환은 별도 Phase.

## 검증 결과

- bash -n (lint hook 문법): 통과
- JSON 검증 (registry): 통과
- pyright (modularity-check.py): 에러 0건, 경고 0건
- modularity-check.py verify: 11 sources, 정상 26, 경고 0, 실패 0
- modularity-check.py scan: 3146건 (기존 미전환 코드 — Phase 2 범위 외)

## 모델 사용 기록

- 불칸(백엔드): hooks/modularity-lint.sh + .pre-commit-config.yaml / sonnet / -
- 아르고스(테스터): tools/modularity-check.py / sonnet / -
- 이리스(프론트엔드): config/module-registry.json 업데이트 / haiku / 단순 JSON 데이터 작업 (판단 불필요)
