Files
gitea-agent/harness/tests/spec/test_priority_review_contracts.py
T

108 lines
6.3 KiB
Python

"""Static contract regressions; these do not prove LLM execution behavior."""
from pathlib import Path
import re
import unittest
HARNESS = Path(__file__).resolve().parents[2]
DISCOVERY = HARNESS / 'agents/spec/skills/gitea-discovery-review/SKILL.md'
IMPLEMENTATION = HARNESS / 'agents/spec/skills/gitea-implementation-spec-review/SKILL.md'
README = HARNESS / 'docs/discovery/README.md'
class PriorityReviewContracts(unittest.TestCase):
def test_scope_classification_and_optional_nonblocking(self):
text = README.read_text()
for value in ('핵심 요청:', '기존 호환성:', '선택적 확장:',
'명시적으로 채택되지 않은 선택적 확장은', 'blocking OQ로 승격하지 않는다'):
self.assertIn(value, text)
def test_all_oq_options_preserve_mandatory_contracts(self):
text = README.read_text()
oq_rules = text.split('## OQ(${open_questions}) 작성 방법', 1)[1].split('```markdown', 1)[0]
for value in ('추천안을 포함한 모든 선택지',
'원본 요청의 필수 범위, 확정된 결정과 기존 호환성 불변조건을 보존',
'미검증 전제를 확정된 사실로 취급하지 않는다',
'요구 철회나 기존 계약 변경',
'일반 구현 대안과 구분하고 변경 대상과 영향을 명시'):
with self.subTest(rule=value):
self.assertIn(value, oq_rules)
def test_compatibility_user_decisions_and_existing_oq_preserved(self):
text = DISCOVERY.read_text()
for value in ('기존 보안·호환성 제약은 선택적으로 낮추지',
'미선택 OQ를 임의 삭제·해결하지', '선택을 보존하고 사용자 판단',
'사용자 선택이 필요한 결정 공백과 구분'):
self.assertIn(value, text)
def test_experiment_verdict_boundary_and_parent_check(self):
text = DISCOVERY.read_text()
for value in ('시험한 방식의 실패:', '소스로 확인된 제약:', '요구 충족 불가능:',
'미검증 또는 판단 유보', '시험하지 않은 대안·확인 한계',
'원본 실험·공식 소스에 직접 대조', '일부 prototype 실패만으로'):
self.assertIn(value, text)
def test_document_delegate_inputs_and_fail_closed_result_adoption(self):
text = IMPLEMENTATION.read_text()
for value in ('byte parity', '실제 내용을 delegate context로 제공',
'대상 저장소 README/TEMPLATE를 작성 정책으로 대신 사용하지',
'산출물별 의무표:', 'pinned baseline 문서 및 전체 AC',
'이전 finding의 승인 근거와 최소 보완 요청',
'입력이 부족하면 main이 보완하거나 직접 검토',
'delegate의 PASS를 최종 판정으로 채택하지'):
self.assertIn(value, text)
def test_structure_semantics_and_preserved_contract_not_conflated(self):
text = IMPLEMENTATION.read_text()
for value in ('구조 적합성(', '의미 적합성(', 'exact section·line',
'구조 통과만으로 의미를 승인', '반복 기재 부재만으로 의미 누락',
'제품 저장소의 새 산출물이나 result schema 변경을 요구하지'):
self.assertIn(value, text)
def test_named_test_documentation_contract_requires_call_assertion_cross_check(self):
text = IMPLEMENTATION.read_text()
heading = '### Named test 근거와 재작업 보고'
self.assertIn(heading, text)
section = text.split(heading, 1)[1].split('\n## ', 1)[0]
for rule in ('exact reviewed head', '실제 호출 인수와 assertions',
'검증하는 경우와 검증하지 않는 경우', '정적 확인과 실제 실행',
'테스트 이름이나 PASS 수치만으로', '확인 한계'):
with self.subTest(rule=rule):
self.assertIn(rule, section)
def test_rework_report_documentation_contract_requires_categories_and_counting_rules(self):
text = IMPLEMENTATION.read_text()
section = text.split('### Named test 근거와 재작업 보고', 1)[1].split('\n## ', 1)[0]
for rule in ('해소:', '잔여:', '신규:', '문서 보완:', '해당 없음',
'같은 원인의 구현·문서 finding', '중복 집계하지 않는다',
'승인 계약 위반', 'blocker로 승격하지 않는다',
'result schema나 renderer', '자동 assertion 해석기'):
with self.subTest(rule=rule):
self.assertIn(rule, section)
def test_writer_family_documentation_contract_requires_bounded_path_evidence(self):
text = IMPLEMENTATION.read_text()
heading = '### Writer-family criterion closure checklist'
self.assertIn(heading, text)
section = text.split(heading, 1)[1].split('\n## ', 1)[0]
for rule in ('기존 승인 계약', 'monetary/current-cache', 'create/update/import',
'실제 존재', '정규화', 'unknown과 zero', 'mutation/no-write',
'downstream', 'exact reviewed head', '`evidence`·`reason`',
'family 전체', '비적용', '잔여 finding', '새 금액 정책',
'모든 입력 조합', '전체 suite 재실행', '자동 runtime checker',
'제품 실행 금지', 'legacy financial-authority'):
with self.subTest(rule=rule):
self.assertIn(rule, section)
def test_local_links_resolve_and_procedures_reference_new_rules(self):
for path in (DISCOVERY, IMPLEMENTATION, README):
text = path.read_text()
for link in re.findall(r'\]\(([^)]+)\)', text):
if not link.startswith(('http:', 'https:', '#')):
self.assertTrue((path.parent / link.split('#')[0]).exists(), link)
self.assertIn('8. 범위 분류·blocking 판단과 기술적 결론의 경계를 먼저 적용', DISCOVERY.read_text())
self.assertIn('11. 문서 검토 입력과 구조·의미 분리 절차', IMPLEMENTATION.read_text())
if __name__ == '__main__':
unittest.main()