fix: governance ID check must ignore code blocks (review #415)
All checks were successful
Gitea CI / test (push) Successful in 38s
Gitea CI / test (pull_request) Successful in 38s

REQ/TASK/TEST ID 패턴 매칭을 _strip_code_segments() 결과에 적용하여
코드 펜스/인라인 코드 안에만 ID를 넣어 검증을 우회하는 케이스를 차단.

회귀 테스트 추가: test_validate_pr_body_text_rejects_governance_ids_in_code_block_only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
agentson
2026-03-04 23:37:10 +09:00
parent 4200575c8e
commit 01e4e0f43f
2 changed files with 25 additions and 3 deletions

View File

@@ -50,11 +50,13 @@ def validate_pr_body_text(text: str, *, check_governance: bool = True) -> list[s
if not LIST_ITEM_PATTERN.search(text):
errors.append("body is missing markdown list items")
if check_governance:
if not REQ_ID_PATTERN.search(text):
# Check governance IDs against code-stripped text so IDs hidden in code
# blocks or inline code are not counted (prevents spoof via code fences).
if not REQ_ID_PATTERN.search(searchable):
errors.append("body is missing REQ-ID traceability (e.g. REQ-OPS-001)")
if not TASK_ID_PATTERN.search(text):
if not TASK_ID_PATTERN.search(searchable):
errors.append("body is missing TASK-ID traceability (e.g. TASK-OPS-001)")
if not TEST_ID_PATTERN.search(text):
if not TEST_ID_PATTERN.search(searchable):
errors.append("body is missing TEST-ID traceability (e.g. TEST-OPS-001)")
return errors

View File

@@ -103,6 +103,26 @@ def test_validate_pr_body_text_skips_governance_when_disabled() -> None:
assert not any("REQ-ID" in err or "TASK-ID" in err or "TEST-ID" in err for err in errors)
def test_validate_pr_body_text_rejects_governance_ids_in_code_block_only() -> None:
"""Regression for review comment: IDs inside code fences must not count."""
module = _load_module()
text = "\n".join(
[
"## Summary",
"- no governance IDs in narrative text",
"```text",
"REQ-FAKE-999",
"TASK-FAKE-999",
"TEST-FAKE-999",
"```",
]
)
errors = module.validate_pr_body_text(text)
assert any("REQ-ID" in err for err in errors)
assert any("TASK-ID" in err for err in errors)
assert any("TEST-ID" in err for err in errors)
def test_fetch_pr_body_reads_body_from_tea_api(monkeypatch) -> None:
module = _load_module()