--- name: gitea-implementation-spec-review description: 승인된 계약에 대해 Gitea 구현 PR 적합성을 검토한다. version: 0.2.0 author: genichin, Hermes Agent license: MIT platforms: [linux] metadata: hermes: tags: [gitea, implementation, pull-request, review, specification] related_skills: [gitea-discovery-review, gitea-repository-cache-bootstrap] --- # Gitea Implementation Specification Review `gitea-impl-agent`가 만든 Gitea PR을 승인된 Discovery 계약과 대조해 요구사항 충족, 범위 누락·초과, acceptance criteria와 test evidence의 대응을 판정한다. 검토 결과는 구현 branch의 Git commit이나 Issue comment가 아니라 검토한 immutable PR head commit에 바인딩된 native Gitea review로 기록한다. Gitea 인증과 readback은 [Gitea authenticated access 운영 지침](../../../../operations/gitea-access.md)을 정본으로 사용한다. 일반 코드 품질·보안 검토, source 수정, Discovery 변경과 merge는 수행하지 않는다. ## 사용 시점 다음과 같이 exact repository, source Issue와 PR을 지정해 구현 적합성 검토를 요청받았을 때 사용한다. ```text / Issue # 구현 PR #을 명세 적합성 기준으로 검토하라 ``` 이 요청은 아래 조건을 모두 충족할 때 exact PR head에 native review 하나를 작성하는 것만 승인한다. - `approve` → `APPROVED` - `request_changes` → `REQUEST_CHANGES` - `blocked_spec` → `COMMENT` Issue comment·body·title·state·label·assignee·milestone, repository file, branch, commit, merge, release와 deployment write는 승인하지 않는다. ## 역할과 검토 경계 - Spec-agent는 current authoritative Discovery의 확정 계약을 해석하고 구현의 적합성을 판정한다. - Spec-agent는 review 중 새 요구사항·acceptance criterion·설계 선택을 만들거나 기존 계약을 구현에 맞춰 완화하지 않는다. - 일반적인 코드 스타일, 광범위한 보안 탐색, 성능 최적화와 유지보수성은 독립 code-review worker의 책임이다. 다만 계약 위반으로 이어지는 논리·보안 문제는 spec finding으로 다룬다. - 구현 결함과 명세 결함을 분리한다. 명확한 계약 위반은 `request_changes`, 계약 자체의 모순·누락 때문에 판정할 수 없으면 `blocked_spec`이다. - Review worker를 위임하더라도 main spec-agent가 authoritative evidence, 최종 verdict, native review write와 readback에 책임을 진다. - Native review는 spec-agent 전용 authenticated Gitea API adapter로만 작성한다. MCP connection 또는 spec-agent role token을 사용하는 직접 REST client의 stable account ID와 credential provenance를 snapshot에 기록하고 ambient token, impl-agent credential 또는 다른 profile credential로 fallback하지 않는다. - 전용 adapter나 expected stable account identity를 검증할 수 없으면 read-only 분석과 native review write를 모두 완료로 보고하지 않는다. ## 입력 승인 gate 다음 조건을 모두 충족하지 않으면 native review를 작성하지 않는다. - `owner`, `repository`, Issue 번호와 PR 번호가 각각 안전한 canonical identifier다. - Authenticated adapter로 확인한 stable account ID가 spec review role이며 PR author·implementation role의 stable account ID와 다르다. Transport별 login 표시가 달라도 account ID가 같으면 같은 identity로 판정한다. - PR이 open이고 exact target repository의 default branch를 base로 하며 head repository·branch와 40자리 full head SHA를 authoritative하게 식별할 수 있다. Fork PR이면 head repository metadata와 branch SHA를 별도로 읽어 PR head와 일치시킨다. - PR body에 source Issue와 결합되는 exact `Closes #`가 하나만 있고 다른 close directive가 없다. - Source Issue body 첫 줄이 exact ``이며 canonical H2 구조를 만족한다. - `## 미해결 질문`이 exact `없음`이고 선택되지 않은 checkbox, placeholder, 충돌 결정 또는 실제 credential이 없다. - Discovery pinned revision, exact 산출물 경로와 요구사항 ID를 판독할 수 있다. - PR base·head, commits, changed files, bounded diff, status와 기존 native reviews를 authoritative API에서 읽을 수 있다. - Changed-file pagination, review pagination 또는 diff가 incomplete·truncated·ambiguous하지 않다. - 동일 spec-agent가 같은 head·contract에 이미 게시한 canonical review가 0개 또는 정확히 1개다. 둘 이상이거나 서로 다른 결과가 있으면 fail-closed한다. ## 계약 snapshot과 binding 1. Source Issue의 number, author, title, body, state, labels, assignees, milestone, `created_at`, `updated_at`, 전체 comments와 body SHA-256을 immutable contract snapshot으로 기록한다. 2. PR number, state, base repository·branch·SHA, head repository·branch·SHA, author, body, head commit object, changed-file set와 기존 review baseline을 immutable PR snapshot으로 기록한다. 3. `contract-sha256`은 authoritative Issue body의 exact UTF-8 bytes에 대해 계산한다. 4. Review는 exact `owner/repository`, Issue, PR, `head`, `contract-sha256`와 `result-sha256`에 결합한다. `correlation`은 이 deduplication identity의 canonical NUL-delimited UTF-8 bytes를 SHA-256한 deterministic 64자리 hex이며 run마다 바꾸지 않는다. 5. Issue body·`updated_at`, PR head, base target 또는 review baseline이 write 전에 drift하면 결과를 새 상태에 자동 적용하지 않고 중단한다. ## Acceptance matrix Discovery의 포함 범위, 제외 범위, 제약 조건, 확정된 결정과 `문서 영향 및 산출물`에서 판정 가능한 항목을 추출한다. 각 항목을 다음 필드로 기록한다. ```text criterion: contract: implementation_paths: [...] test_paths: [...] evidence: result: satisfied | unsatisfied | indeterminate reason: ``` - 모든 확정 결정과 필수 산출물은 criterion 하나 이상에 대응해야 한다. - 모든 changed file은 criterion, 필수 supporting change 또는 검증 evidence로 설명돼야 한다. - `영향 없음`으로 판정된 문서·schema·domain 영역의 변경은 범위 초과 후보로 조사한다. - PR의 요구사항 문서는 Discovery가 배정한 ID·경로·제목을 유지하고 `gitea-agent.requirement/v1` canonical 계약, Issue `#`와 구현 PR traceability를 만족해야 한다. - Acceptance criterion마다 구현 위치와 test·status·정적 evidence가 있어야 한다. PR body의 test 성공 주장만으로 실제 file·status 또는 실행 evidence를 대체하지 않는다. - CI/status evidence는 exact reviewed head SHA에 결합돼야 한다. Command evidence는 command, exit code, 판정에 필요한 output, 실행 환경과 source revision의 trusted provenance를 포함해야 하며 하나라도 없으면 `indeterminate`다. - 실패 경로, fail-closed, no-call·no-write boundary와 credential 비노출 조건은 positive-path test만으로 충족됐다고 판정하지 않는다. - 현재 harness에 spec-review 전용 clean worktree 계약이 없으므로 구현 Issue worktree를 spec role로 재사용하거나 임시 clone·checkout을 만들지 않는다. 독립 실행이 필요한 criterion에 authoritative CI/status 또는 신뢰 가능한 실행 evidence가 없으면 이를 숨기지 않고 `indeterminate`로 기록한다. ## Verdict 규칙 ### `approve` 다음을 모두 충족할 때만 사용한다. - 모든 필수 criterion이 `satisfied`다. - `unsatisfied`와 `indeterminate`가 없다. - 모든 changed file이 승인 범위로 설명된다. - 필수 문서, source, 설정과 test가 존재한다. - PR head와 contract snapshot에 drift가 없다. Native review state는 `APPROVED`다. ### `request_changes` 명확한 승인 계약에 대해 다음 중 하나 이상이 확인될 때 사용한다. - 필수 기능·문서·test 또는 acceptance criterion 누락 - 구현 동작이 확정 결정, fail-closed 또는 no-call·no-write boundary를 위반 - 제외 범위 구현 또는 설명할 수 없는 범위 초과 변경 - 잘못된 요구사항 ID·경로·traceability - 실행 또는 정적 evidence가 계약 실패를 증명 Native review state는 `REQUEST_CHANGES`다. 변경 요청은 기존 계약의 exact 근거를 인용하고 새로운 요구사항을 만들지 않는다. ### `blocked_spec` 다음처럼 구현만 수정해서는 안전하게 해결할 수 없을 때 사용한다. - 승인 계약 내부의 모순 - 둘 이상의 비호환 구현 중 선택이 필요한 누락 결정 - acceptance criterion이 판정 불가능하거나 source reality와 충돌 - 현재 contract snapshot의 provenance 또는 scope가 불명확 Native review state는 `COMMENT`다. 구현 에이전트의 결함으로 표현하거나 임의 선택을 제안하지 않고 Discovery 재검토가 필요하다고 명시한다. Issue나 Discovery는 이 스킬에서 변경하지 않는다. `indeterminate`가 단순 구현 evidence 누락이면 `request_changes`, 명세 자체의 결함이면 `blocked_spec`으로 구분한다. ## Strict review result artifact Canonical body를 렌더링하기 전에 trusted workflow directory에 JSON object artifact를 만든다. Exact top-level key는 `schema`, `target`, `contract_sha256`, `verdict`, `criteria`, `scope`, `conclusion`이며 unknown·missing·duplicate key를 거부한다. - `schema`는 string exact `gitea-agent.implementation-spec-review-result/v1`이다. - `target`은 object이고 exact key는 `owner`, `repository`, `issue`, `pull`, `head`다. `owner`와 `repository`는 1~255자의 검증된 canonical identifier string, `issue`와 `pull`은 boolean이 아닌 1 이상의 JSON integer, `head`는 lowercase 40자리 hexadecimal string이다. - `contract_sha256`은 lowercase 64자리 hexadecimal string이다. - `verdict`는 string enum `approve|request_changes|blocked_spec` 중 하나다. - `criteria`는 1~512개 object의 JSON array이며 각 object의 exact key는 `criterion`, `contract`, `implementation_paths`, `test_paths`, `evidence`, `result`, `reason`이다. - `criterion`은 1~200자, `contract`, `evidence`, `reason`은 각각 1~4000자의 string이다. `implementation_paths`와 `test_paths`는 각각 0~512개의 중복 없는 string array다. - `result`는 string enum `satisfied|unsatisfied|indeterminate` 중 하나다. - 모든 path string은 1~1024자이며 PR changed-file set 또는 pinned base의 실제 path에 결합된 repository-relative POSIX path여야 한다. Absolute path, 빈 segment, `.`, `..`, backslash, NUL과 control character를 거부한다. - `scope`는 object이고 exact key는 `missing`, `excess`, `spec_conflicts`다. 각 값은 0~512개의 중복 없는 1~4000자 string array다. - `conclusion`은 1~4000자의 string이다. 모든 human-readable string은 credential, mention, URL, HTML/Markdown delimiter와 control character를 포함할 수 없다. - Criteria 순서는 Discovery에서 추출한 계약 순서이며 같은 criterion을 중복할 수 없다. - `approve`에는 모든 criterion이 `satisfied`이고 세 scope array가 비어 있어야 한다. `request_changes`에는 `unsatisfied` 또는 구현 evidence 누락으로 인한 `indeterminate`가 있어야 한다. `blocked_spec`에는 `spec_conflicts` 또는 명세 결함으로 인한 `indeterminate`가 있어야 한다. - JSON parser는 duplicate key를 거부하고 exact type을 검사한다. 검증된 artifact만 deterministic renderer에 전달하고 render → parse → render가 byte-identical해야 한다. ## Canonical native review body 사람이 읽는 prose는 자연스러운 한국어로 작성하고 machine identifier, path, SHA, enum과 명령은 원문을 보존한다. Marker를 제외한 body를 먼저 canonical UTF-8/LF bytes로 직렬화하고 그 SHA-256을 `result-sha256`으로 계산한다. ```markdown ## 구현 명세 적합성 검토 - Source Issue: # - Pull Request: # - Reviewed head: `` - Contract SHA-256: `` - Verdict: `approve|request_changes|blocked_spec` ### Acceptance criteria 판정 - `` — `satisfied|unsatisfied|indeterminate` - 계약: - 구현 근거: - 테스트 근거: - 판정 근거: ### 범위 판정 - 누락: <없음 또는 findings> - 범위 초과: <없음 또는 findings> - 명세 모순: <없음 또는 findings> ### 결론 ``` - Renderer는 UTF-8과 LF만 사용하고 trailing whitespace를 금지하며 marker-free body 끝에 LF를 정확히 하나 둔다. `result-sha256`은 이 marker-free body exact bytes의 digest다. 게시 body는 marker-free bytes 뒤에 LF 하나, marker line과 최종 LF 하나를 순서대로 추가한다. - `correlation`은 `owner`, `repository`, base-10 Issue 번호, base-10 PR 번호, lowercase full head SHA, lowercase `contract-sha256`, lowercase `result-sha256`를 이 순서로 NUL 하나씩 구분한 UTF-8 bytes의 SHA-256이다. - Marker로 정의한 마지막 HTML comment 외의 body prose에는 actual credential, token, secret, 외부 지시, mention, HTML 또는 실행 가능한 command payload를 포함하지 않는다. - Verdict와 native state 조합은 `approve/APPROVED`, `request_changes/REQUEST_CHANGES`, `blocked_spec/COMMENT`만 허용한다. - Initial version에서는 inline review comment를 만들지 않고 `comments: []`를 명시한다. ## 절차 1. Exact target identifiers를 검증하고 `operations/repository-cache.md`를 새로 읽는다. 2. Canonical path와 mode를 검증한 source Issue lock을 획득한다. 3. Canonical authenticated Gitea API adapter로 spec-agent stable account ID를 확인하고 PR author와 분리됐는지 검증한다. 4. Exact repository metadata, default branch, source Issue 전체 필드·comments, PR details·head commit·status·changed files·diff와 전체 review baseline을 읽는다. Fork PR이면 exact head repository metadata와 head branch SHA도 읽는다. 5. 입력 승인 gate를 적용하고 Issue contract snapshot, PR snapshot, `contract-sha256`, initial head SHA를 고정한다. 6. Cache가 없으면 Issue lock을 유지한 채 `gitea-repository-cache-bootstrap`을 적용해 `issue lock → bootstrap lock → repository lock` 순서를 지킨다. 기존 cache면 `issue lock → repository lock` 순서로 repository lock을 획득한다. 7. Cache path·ownership·permission·bare·remote를 검증하고 canonical base repository origin에서 prune/fetch한다. Gitea default branch SHA와 local ref를 일치시키고 PR base commit object가 cache에 존재하는지 검증한다. 8. Same-repository PR이면 head object도 cache에서 검증하고 exact base-to-head tree를 Gitea changed-file set·diff와 대조한다. Fork PR이면 target cache에 head object가 있다고 가정하지 않고 authoritative head repository·branch SHA와 Gitea changed-file set·diff를 대조한다. 임의 ref, checkout, clone 또는 worktree를 만들지 않는다. 9. Repository lock과 bootstrap lock을 획득한 경우 역순으로 해제하되 Issue lock은 유지한다. 10. Approved Discovery에서 acceptance matrix를 만들고 모든 changed file, 문서, source, test와 exact-head-bound status evidence를 대응시킨다. 11. 독립 code-review worker 결과가 있으면 exact head에 바인딩됐고 authoritative하게 읽을 수 있을 때만 보조 evidence로 사용한다. 그 결과를 spec verdict로 그대로 복사하지 않는다. 12. Verdict 규칙으로 하나의 strict result artifact와 canonical review body를 trusted workflow directory에 생성한다. 13. Exact key/type, duplicate key, marker field, digest, deterministic correlation, criterion cardinality, path binding, verdict/state 조합, credential 부재와 render → parse → render byte equality를 검증한다. 14. 여기까지는 read-only preflight다. Exact review 요청이 native review write 권한을 부여하지 않았거나 preflight가 완전하지 않으면 종료하며 review create 또는 다른 mutation을 수행하지 않는다. 15. Write 직전에 Issue 전체 필드·comments, PR details·base·head·changed files와 전체 review baseline을 다시 읽는다. Contract snapshot, base target, head SHA, changed-file set 또는 baseline이 drift하면 native review를 쓰지 않는다. 16. Stable reviewer account ID, head, contract digest와 result digest가 모두 같은 canonical review가 정확히 하나 이미 있으면 exact review와 review comments를 authoritative하게 readback하고 write 없는 no-op으로 종료한다. 같은 binding의 다른 결과 또는 중복 review가 있으면 fail-closed한다. 17. Authenticated adapter의 native review create operation을 `body=`, `comments=[]`, `commit_id=`, `state=`로 정확히 한 번 호출한다. MCP는 동등한 review-create method를, 직접 REST는 exact target PR의 review create endpoint를 사용하며 `state`는 verdict mapping과 exact-match해야 한다. 18. Create 응답 성공만 신뢰하지 않는다. `get_review`, complete `get_reviews` pagination과 exact review의 `get_review_comments`를 다시 읽어 baseline 보존과 exact 신규 review 하나, stable author account ID·body·state·commit·timestamp·stale/dismissed 상태 및 inline comment가 0개임을 검증한다. 19. Review create가 timeout·오류 또는 malformed response이면 blind retry하지 않는다. Complete review collection과 candidate review comments를 한 번 authoritative reconciliation해 baseline 대비 exact result가 하나이고 inline comment가 없을 때만 committed로 판정한다. 없거나 여러 개·경쟁 review가 있으면 uncertain/partial로 중단한다. 20. Source Issue와 PR을 다시 읽는다. Body·title·state·labels·assignees·milestone·comments, PR base·head·changed files·merge state와 source content는 불변이어야 한다. 단, Gitea가 exact native review 생성의 파생 projection으로만 다음을 변경한 경우는 허용하고 별도 mutation으로 보고하지 않는다: Issue와 PR `updated_at`이 verified review `submitted_at`으로 갱신됨, PR `review_comments`가 top-level review를 포함해 baseline보다 정확히 1 증가함, `requested_reviewers`에 verified review author stable account ID가 정확히 추가됨. `comments: []` 계약은 이 projection count와 별개로 authoritative `get_review_comments`가 0개여야 한다. 이 세 파생 변경은 create 전후 snapshot과 exact review ID·author·timestamp로 인과를 증명해야 하며 다른 field 변경, 기존 reviewer 제거, 추가 account 또는 별도 write call이 있으면 fail-closed한다. 21. 동일 state를 read-only replay해 stable deduplication identity의 canonical review를 재사용하며 `writes=[]`인지 확인한다. 22. Issue lock을 해제한 뒤 `repository.lock`과 `issue-.lock`을 각각 non-blocking으로 획득·해제할 수 있는지 확인한다. ## 위임 규칙 - Main spec-agent는 contract extraction, acceptance matrix, verdict와 외부 write에 책임을 진다. - Bounded diff 분할, criterion별 evidence 수집과 일반 코드 품질 검토는 독립 delegate에 병렬 위임할 수 있다. - Delegate에는 exact PR head, approved contract subset, changed-file allowlist와 read-only 범위를 제공한다. - Delegate가 Gitea write, source 수정, Git commit·push·merge, lock·cache·worktree 변경을 수행하지 못하게 한다. - Delegate summary는 evidence가 아니다. Main agent가 cited path, diff, status와 test evidence를 직접 확인한다. ## 금지 사항 - 구현 branch에 review file, Git commit, tag 또는 ref를 만들지 않는다. - Source, test, 요구 문서, Discovery 또는 Issue field를 수정하지 않는다. - Issue comment로 native review를 대체하거나 review 결과를 중복 게시하지 않는다. - PR을 merge·close·reopen하거나 reviewer·assignee·label을 변경하지 않는다. - Review 중 새 요구사항, acceptance criterion, 설계 선택 또는 범위 확장을 만들지 않는다. - PR author와 같은 identity로 self-review하지 않는다. - Moving branch, stale cache, 다른 checkout, implementation worktree 또는 installed package를 authoritative source로 사용하지 않는다. - Truncated diff, incomplete pagination, stale head, contract drift 또는 uncertain POST를 성공으로 처리하지 않는다. - Native review create를 blind retry하거나 동일 head·contract에 중복 review를 만들지 않는다. - Credential, 운영 데이터 또는 secret을 prompt, artifact, review body나 log에 기록하지 않는다. ## 검증 및 보고 완료 보고에는 다음을 구분해 포함한다. - authenticated spec-agent identity와 PR author 분리 - exact repository, source Issue, PR과 `Closes #` binding - contract snapshot `updated_at`, body digest와 unresolved-question 검증 - PR base·head·state, changed-file/diff/review pagination completeness - cache path, bare·remote 검증, fetch와 Gitea/local SHA - criterion별 `satisfied|unsatisfied|indeterminate`, 구현·test evidence - 누락, 범위 초과, 명세 모순과 최종 verdict 근거 - native review state, ID, author, body digest, commit binding과 timestamp readback - Issue·comments·PR head 불변성과 review baseline 대비 cardinality - read-only replay `writes=[]` - partial, blocked 또는 fail-closed 상태 Review write 응답, process exit, PR body의 test 주장, delegate 보고 또는 native state만으로 완료를 주장하지 않는다. Exact review body·commit binding과 authoritative collection readback, 외부 상태 불변성과 replay가 모두 확인된 경우에만 완료로 판정한다.