178 lines
36 KiB
Markdown
178 lines
36 KiB
Markdown
---
|
|
name: gitea-code-review
|
|
description: Spec pass된 Gitea PR의 코드 품질과 안전성을 검토한다.
|
|
version: 0.1.5
|
|
author: genichin, Hermes Agent
|
|
license: MIT
|
|
platforms: [linux]
|
|
metadata:
|
|
hermes:
|
|
tags: [gitea, review, security, testing]
|
|
related_skills: [gitea-implementation-spec-review, gitea-issue-rework]
|
|
---
|
|
|
|
# Gitea Code Review
|
|
|
|
`구현 → spec pass → code review`의 독립 2차 리뷰를 수행한다. 승인된 요구사항을 바꾸거나 직접 구현하지 않고, 코드 결함과 검증 부족을 근거로 판정한다.
|
|
|
|
|
|
## Test inventory source-binding gate
|
|
|
|
Baseline/current inventory를 생성·전달·채택할 때 `check-tests 이전`에 `harness/lib/test_inventory_binding.py`를 실행한다. Inventory의 자기 선언을 신뢰하지 않고 독립적으로 고정한 revision과 stage를 expected 입력으로 제공한다. Exact Git blob의 파일 존재·SHA-256 및 collection scope 결속을 [공통 source-binding 정본](../../../../operations/repository-cache.md#test-inventory-git-source-binding-preflight)에 따라 확인하고, 통과한 ID/source가 이후 구조 guard 입력과 같은지도 대조한다. 불일치 증빙을 채택하거나 현재 collection을 baseline으로 재명명하지 않는다. PASS가 named test의 존재·collection 실행·의미 보존을 인증하지는 않으며 main의 실제 실행 provenance 검토와 기존 revision evidence 영향 평가를 유지한다. 이 gate는 제품 실행·별도 checkout 권한이나 자동 제품 변경 요청을 추가하지 않는다.
|
|
|
|
## Delegation evidence acceptance gate
|
|
|
|
위임 결과 채택 이전에 `harness/lib/delegation_evidence.py`를 [공통 증빙 채택 정본](../../../../operations/repository-cache.md#delegation-evidence-acceptance-preflight)에 따라 실행한다. main이 독립적으로 고정한 context에 source/bundle digest, 허용 작업, 검증 항목과 독립 실행 catalog를 넣으며 worker 자기 선언으로 context를 만들지 않는다. Source line/named test anchor와 실제 보존된 회귀 테스트·RED/GREEN 기록을 대조하고, bundle 추출 범위 밖 부재 주장은 authoritative Git 조회 없이 채택하지 않는다. Import·환경 오류를 RED로 취급하거나 확인되지 않은 위임 주장을 최종 판정·delivery·publication 근거로 옮기지 않는다. Static-only worker가 기존 독립 실행 근거를 인용하는 것과 직접 실행하는 것을 구분한다. BLOCK/입력 거부이면 해당 증빙 채택을 중단하고 main이 실제 기록과 의미를 재검증한다. Gate는 sandbox, 실행 인증 또는 assertion 의미 판정기가 아니며 기존 compare-source/check-tests와 role의 제품 실행 제한을 대체하지 않는다.
|
|
|
|
실제 소비 함수에서도 [runtime consumption 정본](../../../../operations/repository-cache.md#delegation-adoption-runtime-consumption)의 `require_adoption`을 통과한다. main은 위임 근거 비사용을 `{"mode":"none"}`, 사용을 `mode=delegated` exact 선언으로 명시하며 누락이나 이전 PASS receipt를 허용하지 않는다. 판정/render, delivery artifact, native publication마다 새 검증을 수행하고 소비 source/stage에 결속한다. 최초 구현 delivery는 `gitea-issue-implementation/scripts/implementation_delivery.py`의 `deliver_implementation(adapter, head=final_head, declaration=main_declaration)`에서 main-owned push/PR adapter를 호출한다. Adapter는 push/read_remote_head/create_or_reuse_pr/read_pr를 제공하고 기존 인증·repository/Issue scope·non-force explicit refspec·remote readback 계약을 지킨다. 새 진입점을 쓰지 않는 직접 push/PR 생성은 이 workflow를 우회하는 것으로 금지한다. Gate 밖 직접 Git/API 실행을 sandbox로 차단한다고 주장하지 않는다. 기존 semantic/source/identity/lease 검증과 외부 readback은 그대로 유지한다.
|
|
|
|
## Managed-lock broker gate
|
|
|
|
Bootstrap 이후 code review는 canonical [Repository cache 운영 지침](../../../../operations/repository-cache.md)의 공통 managed-lock broker 하나를 사용한다. Canonical Issue identity, role, workflow run-id와 TTL로 broker-generated runtime을 요청하고 ready JSON의 `handle`/`socket`을 사용한다. Runtime은 `<issue>/runtime/<workflow-run-id>/`이며 verification run-id와 독립적이다. Runtime 생성은 approval이나 worktree admission을 대신하지 않는다. Cache bootstrap 이후 broker가 Issue lock 아래 runtime을 준비하고, ready 이후 각 workflow의 진입 검증·승인 조건을 확인한다. Client는 raw token을 inspect/log하지 않으며 public `request` API가 token을 캡슐화한다. Nested repository lease는 같은 handle의 `acquire_repository`/`release_repository` request로만 관리하고 TTL 전에 `renew`한다. 정상·오류·cancel에서 repository release(보유 시) → Issue `release` → broker wait/reap → `probe` `free=true` 확인을 검증하기 전에는 완료·로그·보고하지 않는다. Raw `flock ... sleep`, lock-file unlink와 client-side lock holder는 금지한다. Native publication은 이 broker lease를 사용하며 adapter의 compatibility bridge는 canonical protocol을 우회하지 않는다. Reviewer의 persistent harness/.runtime repository-local storage는 role/workflow runtime 경로와 별개이며 이 예외를 유지한다.
|
|
|
|
## 사용 시점과 정본
|
|
|
|
- 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에는 사용하지 않는다.
|
|
|
|
## 진입 조건
|
|
|
|
1. 식별자와 review role의 인증 출처·stable account ID를 검증한다. Impl 및 spec role과 다른 identity여야 하며 다른 role credential로 fallback하지 않는다.
|
|
2. PR이 open이고 source Issue에 exact `Closes #<issue-number>` 하나로 연결되며 default branch를 base로 하는지 확인한다.
|
|
3. 현재 계약 digest와 PR full head SHA에 결합된 spec-agent의 `approve/APPROVED` native review를 확인한다. Author, body binding, stale·dismissed 상태를 검증한다. 이전 head의 pass나 구현자의 pass 주장은 인정하지 않는다.
|
|
4. Issue 계약, PR base·head, 전체 changed files·diff·reviews·review comments와 CI/status를 snapshot으로 보존한다. Pagination 누락, truncated diff, 계약 모순 또는 identity 불명은 차단한다.
|
|
|
|
완료 조건: 현재 head와 계약에 대한 유효한 spec pass 및 완전한 리뷰 입력이 있다. 실패하면 read-only blocker를 보고하고 native review를 게시하지 않는다.
|
|
|
|
## 리뷰 관점
|
|
|
|
읽기 전용 위임과 최종 결과 채택에는 [공통 workflow guard 계약](../../../../operations/repository-cache.md#shared-workflow-guard-gates)을 적용한다. 사용이 허용된 source에서 위임 전 보호 범위를 snapshot하고 채택 전 compare-source를 완료한다. 최종 독립 검토 중 보호 범위 mutator를 병렬 실행하지 않는다. `check-tests --input JSON`으로 기존 ID·status·finding 연결을 확인하고 변경된 assertion·fixture·mock의 의미 검출력을 직접 검토한다. API·CLI·필드·상태·cleanup 보존과 실제 public-response 관찰을 대조한다. 기록은 제품 checkout 밖 허용된 정본 artifact에 보존하고 시작 baseline 누락·source drift이면 PASS를 채택하거나 자동 복구하지 않는다. 운영 근거 실패와 제품 finding을 구분한다.
|
|
|
|
- **정확성·회귀:** 조건 분기, 경계값, 상태 전이, 데이터 처리와 기존 호출자에 대한 부작용.
|
|
- **보안:** 인증·인가, 입력 검증, injection·경로 탈출, secret 노출, cookie·origin·proxy trust와 fail-closed/no-call/no-write 경계.
|
|
- **동시성·복구:** race, 원자성, 잠금 순서, timeout·retry·중복 처리, 부분 실패와 자원 정리.
|
|
- **테스트·근거:** 정상·실패·경계·회귀 검출력, mock의 한계, 실제 runtime 경로와 실행 provenance.
|
|
- **성능·구조:** 과도한 I/O·반복 호출·무제한 자원 사용, 책임·의존 방향, dependency·lockfile·설치 설정과 문서 정합성.
|
|
|
|
`terminal`로 Git diff를 확인하고 `read_file`로 모든 변경 파일과 필요한 주변 코드·테스트를 읽는다. 스타일 취향이나 승인 범위 밖의 기능을 필수 변경 요청으로 만들지 않는다. 계약 위반과 명세 자체의 결함을 구분한다.
|
|
|
|
**위험·검증 matrix:** 실행 검증 전에 승인된 계약과 변경·영향 경계에서 위험·검증 matrix를 작성한다. 파일 목록을 완료 checklist로 대신하지 않는다. 각 행에는 다음을 기록하며, 검토 중 새로 확인한 중요한 경계는 추가한다.
|
|
|
|
- **경계:** 관련 요구사항과 변경 로직·호출자.
|
|
- **위험·기대 동작:** 무엇이 잘못될 수 있고 무엇을 보장해야 하는가.
|
|
- **검증:** 필요한 정상·실패·경계·상태 전이 사례와 확인 방법.
|
|
- **승인 전 필수 여부:** 승인 전에 확인해야 하는지와 그 이유. 승인된 계약과 위험 분석으로 정하며, 결과가 불편하다는 이유로 사후에 필수 여부를 낮추지 않는다.
|
|
- **상태:** `통과 / 실패 / 미검증 / 비적용` 중 하나.
|
|
- **근거:** 코드 위치, 테스트·probe 결과 또는 재사용 근거의 참조. 정적 확인, CI·구현자 실행, reviewer 직접 실행과 재사용 근거를 구분하고 reviewed head·계약에 대한 적용 가능성과 한계를 명시한다.
|
|
|
|
`통과`는 기대 동작을 뒷받침하는 충분한 근거가 있음, `실패`는 기대 동작 위반이 확인됨, `미검증`은 미실행 또는 환경 오류·timeout 등으로 근거가 불충분함, `비적용`은 해당 경계가 적용되지 않는 구체적 이유가 있음을 뜻한다. 모든 행에 runtime test를 강제하지 않으며 위험에 따라 정적 확인이나 검증된 기존 근거를 사용할 수 있다. 환경·runner 오류를 제품 결함인 `실패`로 세지 않는다.
|
|
|
|
## 실행 검증과 기존 워크트리 사용
|
|
|
|
전체 테스트를 매번 재실행할 필요는 없다. Exact-head CI와 신뢰 가능한 실행 기록을 평가하고, 위험하거나 근거가 부족한 부분을 직접 검증한다. Command evidence에는 명령, exit code, 관련 출력, 환경과 source revision이 있어야 한다. 다른 revision의 기록은 전체 후속 diff와 실행 입력의 동일성을 증명한 경우에만 재사용하며 독립 실행과 구분한다.
|
|
|
|
**영속 데이터의 의미적 호환성:** 변경이 지원 대상 구버전 데이터의 저장 형식·해석·조회·소비 동작에 영향을 줄 수 있으면, 프로젝트의 승인된 계약에서 지원 범위와 기대 동작을 먼저 식별한다. 승인된 migration은 동작을 의도적으로 바꿀 수 있으므로, 구버전 출력의 무조건적인 동일성이나 새로운 불변성·호환성 요구를 추가하지 않는다. 행·schema 보존만으로 동작 호환성을 인정하지 않는다.
|
|
|
|
검증에는 위험에 맞게 대표적인 구버전 데이터를 사용한다. 실제 구버전 API·CLI 생성 데이터, 출처가 검증된 기존 fixture 등에서 적절한 방법을 선택하고 source revision·환경·데이터 출처·대표성과 한계를 기록한다. 특정 생성 방법을 모든 프로젝트에 강제하지 않는다. 영향을 받는 조회·소비자의 결과를 승인된 기대 동작과 대조하고, 필요한 검증·근거와 통과·실패·미검증·비적용 상태를 위험·검증 matrix에 연결한다. 프로젝트별 도메인 규칙과 전용 fixture·회귀 테스트는 해당 프로젝트에 둔다.
|
|
|
|
별도 워크트리는 만들지 않는다. 기존 impl Issue 워크트리는 다음 조건을 모두 만족할 때 **검증 전용으로 대여**한다. 구현 재개가 아니므로 `state.json`의 `created_by_role`은 canonical producer literal `gitea-impl-agent` 또는 bounded read-only legacy literal `impl`로만 확인·보존하고 review role로 바꾸지 않는다. 이 두 exact 값 외의 missing/null/non-string/bool/list/dict/whitespace/case variant/role name은 거부하며, legacy literal은 login/authentication alias나 permission grant가 아니다. Admission은 state bytes/mode/mtime/inode를 rewrite/migrate하지 않는다.
|
|
|
|
1. Workflow 동안 broker가 관리하는 exact Issue lease를 유지한다. Cache·registration 검증에는 같은 handle의 `acquire_repository` request를 사용하고, 테스트 전에 `release_repository` request를 보낸다.
|
|
2. Canonical path·권한·state identity·common Git directory·detached/locked registration을 검증한다. HEAD는 현재 PR head와 같고 미완료 Git operation과 tracked 변경이 없어야 한다.
|
|
3. Untracked 파일, dependency 환경과 설정이 검증을 오염시키지 않는지 확인한다. 설명할 수 없는 상태는 reset·clean·stash·checkout으로 복구하지 않고 중단한다.
|
|
4. Source·test·Git refs·state는 수정하지 않는다. 테스트 출력·fixture·DB는 격리된 임시 경로를 사용하고 운영 데이터·credential을 사용하지 않는다. 파일 수정이나 위험한 외부 쓰기가 필요한 명령은 실행하지 않는다.
|
|
5. 실행 전후 HEAD와 tracked/untracked 상태를 비교한다. 정상 종료 시 source에 영향을 줄 수 있는 실행 작업의 실제 종료를 확인하고, 유효한 Issue lease 아래 필요한 최종 HEAD·Git 상태·source digest 검증을 끝내어 기존 결과 artifact에 근거를 보존한 뒤 canonical broker cleanup(보유한 `release_repository` → `release` → tracked broker wait/reap → Issue `probe` `free=true`)을 수행한다. 최종 검증과 Issue `release`를 독립 병렬 작업으로 배치하지 않는다. 검증 실패·취소에서도 현재 실행이 만든 자원만 정리하고 cleanup을 시도하되 검증 성공이나 workflow 완료로 기록하지 않는다.
|
|
|
|
Cleanup이 미확인이라는 이유로 완료한 검토·전체 테스트·Native POST를 자동 반복하지 않는다. 추가 자동 재시도 루프나 heartbeat를 도입하지 않고 기존 명령 timeout과 tracked process의 유한한 wait를 사용한다. Cleanup이 끝나지 않으면 기존 결과 artifact에 마지막 확인 단계와 미확인 원인을 남기고 workflow를 `partial`로 보고한다. 재개 시 이미 확인된 `release`를 다시 강제하지 않고, 보존된 근거와 현재 프로세스 상태를 대조하여 미완료 cleanup 확인만 수행한다. Issue probe `busy`만으로 현재 실행의 lock 누수를 단정하지 않으며, 현행 `free=true` 완료 조건은 유지한다. 정상 해제 뒤 terminal handle 상태가 `released`로 남아 있어야 한다는 조건을 추가하지 않는다. 재개가 source 검증이나 게시 작업으로 확장되면 기존 유효 lease·head·계약 검사를 다시 적용한다.
|
|
|
|
안전한 대여가 불가능하면 CI·기존 근거를 사용하고 직접 실행 불가 사유를 보고한다. 필수 검증 근거가 부족하면 승인하지 않는다. 독립성은 reviewer의 판단과 직접 확인에 있으며 별도 checkout 자체가 필수는 아니다.
|
|
|
|
### 장시간 suite의 timeout evidence recipe
|
|
|
|
이미 승인된 reviewer 직접 실행 중 장시간 suite가 필요한 경우에만 다음 recipe를 기존 bounded execution·artifact 계약에 연결한다. 새 runner·streaming framework·자동 retry·schema를 추가하지 않으며 pytest를 강제하지 않는다.
|
|
|
|
- 실행 시작부터 승인된 artifact 경로에 해당 run-id·source revision·명령·실행 환경·유한한 deadline과 연결된 로그를 보존한다. 기존 승인된 capture/file-output 수단을 사용하고 redaction·권한·출력 한도·deadline을 유지한다. 단순 stdout 파일 redirect만으로 이 보호가 구현됐다고 주장하지 않는다. 안전한 보존을 확인할 수 없으면 실행을 시작하지 않고 evidence_gap으로 보고한다. 기존 source·plan·output binding과 no-clobber 계약을 유지한다.
|
|
- 결과에는 exit status, timeout·출력 잘림, 관측 시간, 실제 종료·reap·process-group cleanup과 미확인 상태를 구분한다. Tool timeout이나 로그 마지막 행은 process 종료의 증거가 아니다. Running/unknown이면 suite를 자동 재실행하지 않는다. 기존 bounded termination·cleanup 절차를 적용하고 필수 검증 미완료는 미검증/partial로 남긴다. 중간 PASS 출력이나 일부 JUnit을 전체 suite 성공으로 승격하지 않는다.
|
|
- Timeout 로그·실패 결과를 덮어쓰지 않는다. 필요한 재실행은 이전 실행과 관련 작업의 실제 종료·cleanup을 확인하고 기존 승인 범위 및 lease·head·source 검사를 다시 통과한 뒤 새 run-id로 수행한다. 종료·cleanup을 확인할 수 없으면 재실행하지 않는다. 무조건적인 전체 재실행이나 자동 retry 권한을 추가하지 않는다.
|
|
- 다음 유한한 budget은 동일 입력 또는 비교 가능한 source·환경·fixture의 관측 시간과 명시한 여유 근거로 설정한다. Timeout 시점은 완료 소요시간이 아니라 하한임을 기록하고, 필요하면 기존 승인 범위의 bounded 진단 근거를 사용한다. 비교가 불가능하면 불확실성을 명시하고 임의의 시간 증가를 측정된 개선이라고 보고하지 않는다. Budget 증가로 원래 timeout 기록을 삭제하거나 pass/fail을 바꾸지 않는다.
|
|
- JUnit은 test runner가 이미 지원하고 이번 검증에 필요한 경우에만 run별 승인된 artifact 경로로 보존한다. Timeout 중 완성된 JUnit이 생성된다고 가정하지 않는다. 누락·malformed·truncation은 증거 한계로 기록하며 JUnit 유무가 실제 exit·종료·전체 collection 검증을 대신하지 않는다. 제품 설정·plugin·dependency를 바꾸거나 JUnit을 필수 공통 format으로 강제하지 않는다.
|
|
|
|
이 문서 계약은 실행 계획과 보고의 지침이며 실제 streaming·JUnit 생성·process cleanup 또는 agent 준수를 검증하지 않는다. 원래 후보의 범용 실행 자동화·suite별 streaming/JUnit 구현 전체가 완료됐다고 주장하지 않고 부분 완료로 유지한다.
|
|
|
|
### Dependency provenance와 probe JSON framing
|
|
|
|
기존 승인 환경을 사용할 수 없고 별도로 승인된 환경 준비가 필요한 경우, 실제 interpreter 경로·버전, 검증에 관련된 실제 resolved dependency 버전, source revision과 dependency/lockfile·설정 출처를 기존 evidence의 환경·command·확인 한계 기록에 결합한다. 실제 설치 상태를 조회한 값과 요구사항의 버전 범위를 구분하고, 실패한 resolution·collection의 command·exit code·안전한 bounded output을 보존한다. Baseline API/dependency 호환성은 기존 승인 환경·검증된 기록 또는 승인된 read-only 근거로 비교하며 제품 회귀, upstream/baseline drift와 reviewer 환경 오류를 구분한다. 비교할 수 없으면 확인 한계를 보고하고 필수 검증 부족은 기존 미검증/blocked 기준을 적용한다. 이 지침은 새 venv·checkout 생성이나 임의 설치·pinning 권한을 부여하지 않으며 source·requirements·lockfile을 바꾸거나 새 dependency manager·claim schema를 만들지 않는다.
|
|
|
|
JSON probe는 실행 전에 producer와 consumer가 고유 marker와 record 경계를 합의한다. 예를 들어 합의한 marker prefix 뒤에 single-line JSON을 쓰는 경우, consumer는 정확한 prefix를 가진 행이 하나뿐인지 확인하고 그 행의 전체 payload를 strict JSON decode한다. 정확히 하나의 완전한 JSON record만 채택하고 누락·중복·malformed·truncation은 차단한다. 전체 stdout이 순수 JSON이라고 가정하거나 임의의 brace 구간·마지막 JSON 비슷한 행을 골라 복구하지 않는다. 합의된 framing이 없는 기존 출력은 자동 추정으로 성공 처리하지 않는다.
|
|
|
|
Marker 밖의 warning과 exit status, timeout·출력 한도·termination 상태는 안전한 bounded context로 별도 보존·검토한다. 유효 JSON 한 개만으로 실패 exit 또는 미완료 실행을 성공으로 바꾸지 않는다. Parser/framing·환경 오류는 제품 assertion 실패나 TDD RED로 보고하지 않고 필수 근거 부족은 기존 판정 기준으로 처리한다. 모든 capture/artifact에는 기존 credential redaction·유출 fail-closed 규칙을 적용하며 marker가 인증·provenance·secret 안전성을 보장한다고 주장하지 않는다. 새 generic parser나 manifest schema는 추가하지 않는다.
|
|
|
|
### Programmatic read control response와 script 준비
|
|
|
|
Programmatic reader는 첫 content-bearing 응답의 실제 내용을 exact 경로, source revision(적용 가능한 경우) 또는 독립 확인한 byte hash, 읽은 범위·완전성과 함께 보존한다. `content` 접근 전에 응답 shape와 content 반환 여부·타입을 확인한다. 본문 없는 `unchanged/dedup` 응답은 control response이지 빈 파일이나 새 source 내용이 아니다. 현재 입력의 identity·revision/hash·필요 범위와 보존된 내용의 binding이 확인된 경우에만 재사용하고, tool의 unchanged 표시만으로 다른 process의 cache나 미보존 내용을 추정하지 않는다. Paginated 일부 내용은 전체 파일 근거로 승격하지 않는다.
|
|
|
|
보존된 내용이 없거나 binding이 불명확하면 현재 허용된 bounded read-only 조회로 exact 입력을 다시 확인한다. 조회 수단·범위·출처를 검증할 수 없으면 `evidence_gap`으로 중단하며 missing content를 빈 문자열이나 fabricated 내용으로 대체하지 않는다. 지원하지 않는 force-read parameter를 만들거나 전역 dedup을 해제하지 않고 stale cache를 재사용하지 않는다. 이 규칙은 새로운 read wrapper·cache subsystem을 요구하지 않는다.
|
|
|
|
Script 준비에는 검증된 source 파일과 typed JSON 입력을 우선하고 다중 quoted Python command로 내용을 재조립하지 않는다. 필요한 Python을 준비한 경우 그 exact bytes를 실행·로그 append·외부 action 전에 side-effect 없는 compile로 확인한다. Compile은 문법 검사일 뿐 안전성·인증·실행 성공의 증거가 아니므로 기존 scope·source·deadline·redaction·실행 provenance 검증은 별도로 유지한다. 문법 오류는 준비 실패로 보존하고 제품 assertion 실패나 TDD RED로 분류하지 않는다. Credential 값은 source·입력 artifact·오류·log에 저장하지 않는다. 이 절차는 review role의 commit/push·credential·새 transport 권한을 확장하지 않는다. 기존 reviewer의 source 수정·commit/push 금지는 유지하며, 검증 통과 자체가 외부 write 승인을 의미하지 않는다.
|
|
|
|
## 판정과 기록
|
|
|
|
- `approve`: 전체 diff, 관련 코드·테스트와 필요한 실행 근거를 검토했고 미해결 중요 결함이나 필수 검증 공백이 없다. 승인 전 필수로 분류한 matrix 행은 모두 통과하거나 근거 있는 비적용이어야 한다. 필수 행에 실패·미검증 또는 설명 없는 비적용이 남으면 승인하지 않는다. 전체 파일 열람이나 전체 테스트 통과만으로 이 조건을 충족했다고 간주하지 않는다. 선택적 검증의 미완료는 한계로 보고하며 자동으로 변경 요청하지 않는다.
|
|
- `request_changes`: 승인된 범위 안의 미해결 중요 결함 또는 승인에 필요한 필수 검증 공백이 있다. 경미한 비차단 결함·무관한 기존 기술부채·선택적 개선만으로는 변경 요청하지 않는다.
|
|
- `blocked`: spec pass 부재·drift, 명세 모순 또는 안전한 검토를 막는 조건이 있다. 승인하지 않고 blocker를 보고한다.
|
|
|
|
Finding마다 `F-001` 같은 ID, 파일·행, 발생 조건, 영향·심각도, 확인 근거, 계약과의 관계 및 제한된 수정·재검증 방향을 기록한다. 확정 결함, 질문, 잔여 위험과 비차단 제안은 분리한다. 위임 시 exact head·계약 subset·파일 범위와 read-only 조건을 주고, main reviewer가 중요 지적을 직접 검증하며 최종 판정을 책임진다.
|
|
|
|
결과는 checkout 밖의 trusted workflow artifact에 한국어로 보존한다. Target, reviewed head, contract digest, spec review ID, findings, 실행 결과·한계와 verdict를 포함한다. 기존 결과 artifact에 위험·검증 matrix와 미검증 범위를 포함하며 별도 파일은 필수가 아니다. 최종 findings 게시 전에 계획된 검토 결과와 판정에 필요한 worker 결과를 main reviewer가 대조·통합하고 각 행의 상태를 확정한다. 일부 검토가 중단됐다면 partial/blocked 범위를 명시하고 전체 검토 완료로 표현하지 않는다. SHA·path·명령은 원문을 유지하고 secret은 기록하지 않는다.
|
|
|
|
## Native review 게시와 재검토
|
|
|
|
게시 단계는 [공통 Native review adapter](references/native-review.md)와 canonical `scripts/native_review.py`의 검증된 API를 사용한다. 매 실행마다 gate·게시·검증 bootstrap을 다시 생성하거나 지원하지 않는 CLI·legacy JSON schema를 추정하지 않는다. 기존 role-authenticated transport와 현재 보유한 Issue lease를 연결하고, durable journal을 유지해 timeout·partial 이후에는 POST 재시도 없이 readback만 수행한다. 정상적인 같은 작성자의 자동 supersession/retouch는 별도 opt-in 없이 기본 인정하되, exact before/after/new-review 대조로 정해진 `official`·`dismissed` 전이와 새 리뷰의 시각만 허용한다. 이전 작성자·본문·commit·판정·댓글과 다른 필드는 보존해야 하며 다른 작성자의 변경은 거부한다. `supersede_same_author`와 `retouch_dismissed`는 v1 호환 필드이지 이 정상 전이의 허가 스위치가 아니다. Commit `files` 순서 정규화만 `unordered_commit_files`와 별도 근거가 필요한 예외로 유지한다. 기존 plan의 bytes/fingerprint와 journal을 변경하지 않는다. Snapshot/plan schema, 실제 지원 interface 및 read-only replay와 live 게시의 차이는 참조 문서대로 확인한다.
|
|
|
|
1. Exact PR 리뷰 요청은 진입 조건을 충족한 native review 하나의 게시만 승인한다. 단순 조사·역할 보고 요청은 write를 승인하지 않는다. `approve → APPROVED`, `request_changes → REQUEST_CHANGES`로 매핑하고 `blocked`는 게시 없이 보고한다.
|
|
2. 게시 직전 Issue 계약, PR base·head, spec pass와 review baseline을 재확인한다. Drift면 중단한다. Body에는 결과 artifact의 요약과 아래 marker를 넣는다.
|
|
`<!-- gitea-agent:code-review/v1 owner=<owner> repository=<repository> issue=<issue-number> pr=<pull-number> head=<full-head-sha> contract-sha256=<digest> -->`
|
|
3. 같은 author·head·계약의 canonical review가 하나 있고 body·최종 state가 같으면 readback 후 write 없는 no-op으로 종료한다. 중복·상충 결과 또는 PENDING이면 추가 게시하지 않는다.
|
|
4. 실제 adapter schema를 확인하고 exact head의 `commit_id`, body, verdict-compatible state/event와 `comments: []`를 명시해 한 번 게시한다. Exact review와 complete collection을 다시 읽어 ID·author·body·head·state·stale/dismissed·inline comments 부재를 검증한다. Timeout·오류는 blind retry하지 않고 readback으로 조정하며 불확실하면 partial로 보고한다.
|
|
5. 게시 후 계약·PR head·source Issue 내용이 보존됐는지 확인한다. Native review에 인과가 확인되는 provider 파생 변경과 무관한 mutation을 구분한다. 검증 실패를 성공으로 보고하지 않는다.
|
|
6. 변경 요청은 기존 PR의 `gitea-issue-rework`로 전달한다. 새 head가 생성되면 **재작업 → 새 head의 spec pass → code 재리뷰**를 수행한다. 이전 지적과 근거는 활용하되 해결 여부·영향·회귀를 새 snapshot에서 확인한다. 동일 현재 head와 계약의 두 pass가 최종 승인 조건이며 merge 승인은 아니다.
|
|
|
|
재리뷰에서 새 차단 finding을 추가할 때는 계약·변경 경로와의 관계 및 이번 승인 전에 해결해야 하는 이유를 입증한다. 발견 시점이나 severity만으로 차단하지 않는다.
|
|
|
|
### 재리뷰 수렴과 에스컬레이션
|
|
|
|
재리뷰는 이전 finding의 수정 matrix, source delta와 영향 경로를 중심으로 진행한다. 미변경 evidence는 이전 source와 현재 head와 실행 입력(코드·설정·fixture·dependency·실행 도구)의 관계를 확인한 유효 범위에서만 재사용하고, 과거 실행을 현재 head의 새 실행으로 표현하지 않는다. Delta 밖의 실제 승인 계약 위반도 무시하지 않으며 새 blocker에는 위 late-finding 근거 규칙을 적용한다.
|
|
|
|
Main reviewer는 이전 review/finding과 현재 exact head를 대조해, 미변경 코드의 첫 리뷰 누락 blocker가 재검토 회차에서 재차 반복되는지 확인한다. 이는 단순히 같은 finding이 아직 미해결인 경우나 새 변경이 만든 결함과 구분한다. 반복이 확인되면 자동 rework handoff를 중단하고 소유자에게 exact head·계약, 관련 review/finding ID와 영향 경로, 남은 findings·확인 한계 및 최소 closure plan을 묶어 보고한다. 근거가 확인 불가이면 반복이 입증됐다고 단정하지 말고 수렴 판단의 불확실성을 보고하며 자동 handoff 재개 결정을 소유자에게 요청한다.
|
|
|
|
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는 검토 범위에서 중요 결함을 발견하지 못했다는 의미이며 무결함의 증명은 아니다.
|
|
|
|
|
|
## Canonical native-review journal
|
|
|
|
Native publication의 정본 root는 `<harness-root>/harness/.runtime/native-review-journals`이며 authenticated origin/repository/Issue/PR/head/contract/reviewer binding으로 결정한다. `canonical_journal_path(plan)`은 표시용 계산일 뿐 인증 증명이 아니다. 임의 caller 경로·alias는 거절하고 같은 binding의 body/verdict 변경, 삭제된 기록, interrupted bootstrap/import는 fail-closed한다.
|
|
|
|
이전 durable intent가 있으면 read-only reconciliation만 수행하고 자동 POST 재시도는 금지한다. Legacy는 현재 role/lease/adoption과 사전 exact digest를 검증하는 명시적 `register_legacy_journal` 절차만 허용한다. 기존 journal을 자동 이동·삭제하지 않으며 등록도 외부 write를 하지 않는다. Same-install retained registry/cooperative filesystem 범위이며 cross-host 또는 malicious same-UID 보호를 주장하지 않는다.
|
|
|
|
Binding/permission/atomic-bootstrap/legacy pending receipt와 보장 한계의 정본 계약은 [native review reference](references/native-review.md#canonical-native-review-journal)를 따른다. `verified.json`은 publication 확인이며 최종 source 검증·lease release·cleanup 완료를 대체하지 않는다.
|