governance: require approval evidence for READ-ONLY file changes (#356) #361
Reference in New Issue
Block a user
Delete Branch "feature/issue-356-readonly-approval"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
READ-ONLY 파일(
src/core/risk_manager.py) 변경 시, PR 본문에 인간 승인 증적과 테스트 증적 2건을 의무화하는 거버넌스 검증을 추가했습니다.Changes
.gitea/PULL_REQUEST_TEMPLATE.mdREAD-ONLY Approval섹션 추가Touched READ-ONLY filesHuman approvalTest suite 1Test suite 2scripts/validate_governance_assets.pyREAD_ONLY_FILES도입 (src/core/risk_manager.py)tests/test_validate_governance_assets.pyValidation
ruff check scripts/validate_governance_assets.py tests/test_validate_governance_assets.pypytest -q tests/test_validate_governance_assets.py(11 passed)python3 scripts/validate_governance_assets.py origin/feature/v3-session-policy-stream...HEADScope
REQ-OPS-002,REQ-OPS-003TASK-OPS-002,TASK-OPS-003TEST-ACC-008,TEST-ACC-009Closes #356
PR #361 코드 리뷰
변경 요약: READ-ONLY 파일 변경 시 PR body에 승인 증적 2건을 강제하는 거버넌스 검증 추가
✅ 잘 된 점
GOVERNANCE_PR_BODY 주입이 CI에 이미 반영돼 있다.
PR 맥락에서는 실제 PR body가 주입되고, push 이벤트에서는 빈 문자열이 돼 warning으로 처리되는 흐름이 의도에 맞다.
_is_placeholder대소문자 처리가 정확하다.PLACEHOLDER_VALUES는 소문자 집합이고,normalized.strip().lower()후 비교하므로TBD,tbd,N/A,<link>등을 모두 잡는다._parse_pr_evidence_line엣지케이스 처리가 올바르다.None→_is_placeholder(None)=True→ 에러- Human approval:) →''→_is_placeholder('')=True→ 에러must_contain 연동이 일관적이다.
PR 템플릿에 READ-ONLY Approval 섹션을 추가하고,
must_contain목록에도 동일 토큰을 등록해 템플릿 완전성까지 CI로 보장한다.11 passed 직접 확인.
🟡
READ_ONLY_FILES에src/core/order_policy.py누락PR #354에서
src/core/order_policy.py도 함께 변경됐다(OrderPolicyRejected→OrderPolicyRejectedError). 이슈 #356이 해당 PR 리뷰에서 발생했음에도 현재READ_ONLY_FILES는risk_manager.py만 포함한다.공식 정책(
CLAUDE.md,docs/agents.md)에 명시된 READ-ONLY 파일은src/core/risk_manager.py뿐이므로 현재 구현이 정책과 일치하는 건 맞다. 다만order_policy.py도 세션 매매 금지 판단에 직접 관여하므로 정책에 포함시킬지 의사결정이 필요하다.포함 원할 시:
이번 PR 범위를 벗어나는 정책 결정이므로 블로커는 아니다.
CLAUDE.md와docs/agents.md를 먼저 업데이트하고 별도 PR로 추가하는 편이 적절하다.🔵 push 이벤트에서 READ-ONLY 파일 변경이 warning만 발생
push: branches: [main]으로 CI가 트리거될 때GOVERNANCE_PR_BODY가 빈 문자열이 되어 warning만 내고 체크를 skip한다. main에 직접 push하는 경우 승인 검증이 우회된다.실질적 리스크는 낮다 — main 직접 push는 이미 브랜치 보호로 막혀야 하고, PR flow를 거치면 검증된다. 단, 브랜치 보호가 설정돼 있지 않다면 잠재적 우회 경로가 된다.
🔵 테스트 커버리지 갭 1개
changed_files에 READ-ONLY 파일이 없는 경우(early return) 테스트가 없다. 함수가 silently 통과해야 하는 정상 경로인데 검증이 빠져 있다.✅ 최종 판정
order_policy.py정책 결정 필요기능 목적 달성. Merge 가능 상태.
order_policy.py는 정책에 포함시키지 않겠다.
main 브랜치는 보호 설정되어 있다.
리뷰 minor 항목 반영 완료했습니다.
검증:
반영 커밋:
c431d82팔로업 리뷰 — commit
c431d82반영 확인✅ 지적사항 반영 확인
🔵 non-READ-ONLY 파일 early return 테스트 → 추가됨
12 passed 직접 확인.
잔여 항목 현황
order_policy.py정책 결정✅ 최종 판정
이전 리뷰 지적사항 중 이번 PR 범위 내 항목은 모두 처리됐다. Merge 가능 상태.