[verified] Connect conditional review observability checklist

This commit is contained in:
2026-10-12 15:59:57 +00:00
parent 20cc7858f6
commit a4ead04664
2 changed files with 57 additions and 0 deletions
@@ -34,6 +34,7 @@ Bootstrap 이후 code review는 canonical [Repository cache 운영 지침](../..
- Exact `owner/repository`, source Issue와 PR을 지정해 코드 리뷰 또는 재리뷰를 요청받았을 때 사용한다.
- 작업마다 `read_file`로 [Gitea access](../../../../operations/gitea-access.md)와 [Repository cache](../../../../operations/repository-cache.md)를 읽는다. 인증·경로·권한·잠금은 이 공통 지침을 따른다.
- 시작 시 아래 조건부 observability 정책 확인과 종료 기록 절차로 현재 role에 적용되는 정책 여부를 확인한다.
- 현재 Issue의 승인된 Discovery가 계약 정본이다. 필요한 문서 규칙만 harness의 `docs/`에서 읽는다.
- 구현, Discovery 수정, merge와 release에는 사용하지 않는다.
@@ -137,11 +138,21 @@ Main reviewer는 이전 review/finding과 현재 exact head를 대조해, 미변
Closure plan은 필요한 수정·검증 범위와 종료 조건을 명시하고, 소유자의 명시적 조정·승인 전에는 자동 handoff를 재개하지 않는다. 이는 임의의 N회 후 자동 승인 규칙이 아니며 blocker를 면제하거나 finding을 삭제·dismiss하는 조건도 아니다. 기존 verdict와 현재 head의 spec·code pass 조건을 유지하고, 안전한 검토가 불가능하면 기존 blocked/partial 규칙으로 보고한다. 소유자의 조정은 승인 계약의 묵시적 축소나 추가 POST 권한을 의미하지 않는다. 기존 journal, lease 및 cleanup·불확실한 publication의 readback 계약을 유지한다. 새 counter·상태 저장·자동 반복 탐지기·publisher 변경은 추가하지 않는다.
## 조건부 observability 정책 확인과 종료 기록
시작 시 현재 review role의 실제 설정과 그 설정이 참조하는 정책의 적용 범위를 확인한다. Credential이나 설정 전체 내용을 출력·복사하지 않고 필요한 정책 참조·적용 조건만 읽는다. 다른 profile의 설정·정책을 가져오거나 spec 정책을 review 정책으로 대신 적용하지 않는다. 과거 후보의 policy 경로·다른 환경의 경로를 추정하지 않고, 누락된 정책 파일을 임의 생성하거나 전역 설정을 바꾸지 않는다.
- 정책 참조가 없음을 실제 설정에서 확인하고 이번 작업이 명시적으로 현재 role에 비적용임을 확인한 경우에만 `not_applicable`과 확인 근거를 남긴다. 참조된 정책이 누락되었거나 설정·정책을 읽을 수 없거나 적용 여부가 모호하면 비적용으로 처리하지 않는다. 이는 정책 확인 실패이며 그 원인·확인 한계를 보고한다. 명시적으로 확인된 비적용은 허용되지만, missing/unreadable/ambiguous configuration or reference는 fail-closed로 처리한다. 정책이 적용되면 해당 적용 정책이 요구하는 정확한 기록 경로·필드·시점·redaction·append·lock·readback·최종 보고 조건만 따른다. 이 지침 자체가 새 logger, 공통 schema 또는 고정 policy 경로를 정의하지 않는다.
- 최종 보고 전에 적용 정책의 요구 항목을 대조하고 정책이 요구하는 보고 항목에 한정한다. run 기록·run-id, 개선 후보 수·목록, 일일 요약과 같은 항목은 적용 정책이 요구할 때만 누락 없이 기록·검증한다. 새로 append한 기록의 적용 skill·상태·evidence 참조와 요청된 run-id·후보 수를 정책이 정한 readback으로 확인한다. 후보 수를 요구하지 않으면 후보 수를 보고 항목으로 만들지 않으며, 요구된 후보 수가 실제로 0임을 검증한 경우에만 0건을 명시하고 정책 부재나 확인 불가 때문에 임의로 0건을 쓰지 않는다. Append·lock·redaction 요구가 있으면 기존 기록을 truncate하거나 credential·secret 값을 저장하지 않는다. Source skill 수정과 정책 로그 작성은 별개 절차이며 기록을 위해 source skill을 추가 수정하지 않는다.
- 기존 main 결과 artifact에 정책 확인 근거·적용 상태와 기록 완료/실패/미확인/비적용을 남기고 review verdict, publication, cleanup 상태와 분리한다. 실패·읽기 불가·부분 기록을 완료로 표현하지 않으며 source·문제 없음 판정이나 실제 native 제출 상태를 로그 성공 여부로 바꾸지 않는다. 기록 오류 때문에 테스트나 native POST를 반복하지 않는다. 적용 정책이 추가 중단 조건을 명시하면 그 조건은 따르되 새 제품 finding이나 게시 권한을 만들어내지 않는다.
- 최종 보고에는 적용 정책이 요구한 항목에 한정해 policy·skill·기록 경로·기록·readback 여부·요청된 후보 수와 실패·한계 또는 비적용 이유를 redacted 형태로 명시한다. 적용 정책이 요구하지 않은 후보 수나 세부 필드는 추정해 추가하지 않으며, 최소한의 정책 확인 상태·적용 상태·오류 보고만 허용한다. 자동 기록이 이미 있다면 이번 run과 출처·내용이 결합됐는지 확인하여 정책이 허용한 범위에서 재사용하고 중복 append하지 않는다. 확인되지 않은 자동 기록 성공은 추정하지 않는다. 이 문서 계약 테스트는 지침의 존재만 검증하며 실제 append·정책 탐색·runtime agent 준수를 입증하지 않는다.
## 주의 및 완료 보고
- Source·test·Discovery 수정, commit·push·merge, Issue 변경, review dismiss, release·deployment를 하지 않는다.
- PR의 성공 주장, delegate 요약, process exit 또는 native state만으로 완료를 주장하지 않는다. HTTP/framework test를 실제 browser 검증으로 표현하지 않는다.
- 보고에는 exact target·head·contract·spec review ID, 검토 범위, findings·verdict, 실제 실행과 재사용 근거, 미검증 범위, native review ID/state/readback 또는 미게시 이유, cleanup·partial 상태를 포함한다.
- 최종 보고에는 위 조건부 observability 절차의 정책 확인 상태·적용 여부·기록 상태·오류 또는 비적용 이유를 항상 보고하고, 세부 항목은 적용 정책이 요구한 경우에만 기록 경로·개선 후보 수 및 기타 상세 필드를 보고한다.
- clean review는 검토 범위에서 중요 결함을 발견하지 못했다는 의미이며 무결함의 증명은 아니다.
@@ -0,0 +1,46 @@
"""Documentation contracts only: no policy discovery/log append/agent execution."""
from pathlib import Path
import unittest
ROOT = Path(__file__).resolve().parents[3]
SKILL = ROOT / 'harness/agents/review/skills/gitea-code-review/SKILL.md'
HEADING = '## 조건부 observability 정책 확인과 종료 기록'
class ReviewObservabilityDocumentationTests(unittest.TestCase):
def test_documentation_contract_requires_active_role_policy_and_conditional_scope(self):
text = SKILL.read_text()
self.assertIn(HEADING, text, 'conditional observability guidance is missing')
section = text.split(HEADING, 1)[1].split('\n## ', 1)[0]
for rule in ('현재 review role', '실제 설정', '적용 범위', 'not_applicable',
'추정하지', '다른 profile', 'spec 정책', '정책 확인 실패',
'참조된 정책이 누락', '비적용으로 처리하지 않는다',
'정책 참조가 없음을 실제 설정에서 확인',
'새 logger', '전역 설정', 'schema'):
with self.subTest(rule=rule):
self.assertIn(rule, section)
self.assertNotIn('/opt/policies/', section)
startup = text.split('## 사용 시점과 정본', 1)[1].split('\n## ', 1)[0]
self.assertIn('조건부 observability 정책 확인과 종료 기록', startup)
def test_documentation_contract_requires_separate_logging_status_and_final_report(self):
text = SKILL.read_text()
section = text.split(HEADING, 1)[1].split('\n## ', 1)[0]
for rule in ('최종 보고 전에', 'run 기록', '개선 후보', '일일 요약',
'새로 append한', 'readback', 'credential', '0건',
'완료/실패/미확인/비적용', 'review verdict', 'publication', 'cleanup',
'테스트나 native POST를 반복하지', '기록 경로', '실패·한계',
'출처·내용이 결합', '문서 계약', '실제 append',
'정책이 요구하는 보고 항목에 한정',
'후보 수를 요구하지 않으면', '임의로 0건'):
with self.subTest(rule=rule):
self.assertIn(rule, section)
final = text.split('## 주의 및 완료 보고', 1)[1].split('\n## ', 1)[0]
self.assertIn('조건부 observability', final)
self.assertIn('세부 항목은 적용 정책이 요구한 경우에만', final)
self.assertNotIn('기록 상태·경로와 적용 정책', final)
if __name__ == '__main__':
unittest.main()