diff --git a/harness/agents/spec/skills/gitea-implementation-spec-review/SKILL.md b/harness/agents/spec/skills/gitea-implementation-spec-review/SKILL.md index b4faaf3..98cf310 100644 --- a/harness/agents/spec/skills/gitea-implementation-spec-review/SKILL.md +++ b/harness/agents/spec/skills/gitea-implementation-spec-review/SKILL.md @@ -83,9 +83,10 @@ reason: - 모든 changed file은 criterion, 필수 supporting change 또는 검증 evidence로 설명돼야 한다. - `영향 없음`으로 판정된 문서·schema·domain 영역의 변경은 범위 초과 후보로 조사한다. - PR의 요구사항 문서는 Discovery가 배정한 ID·경로·제목을 유지하고 `gitea-agent.requirement/v1` canonical 계약, Issue `#`와 구현 PR traceability를 만족해야 한다. +- 기존 요구사항 갱신은 pinned baseline AC별 판정 조건·검증·불변조건을 현재 AC의 보존·승인된 대체·병합·삭제에 대응하고 기존 `contract`·`evidence`·`reason`에 근거를 기록한다. 구조·AC 개수만으로 충족을 판정하거나 이전 ID·개수의 동일성을 강제하지 않으며, 승인 근거 없는 검증 의미 손실은 누락으로 판정한다. - 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`다. -- Command evidence의 source revision과 reviewed head가 다르면 trusted provenance, ancestor 관계, 전체 source-to-head diff와 실행 입력(코드·설정·test·fixture·dependency/lockfile·실행 도구)의 동일성을 검증한다. 실행 입력에 영향을 주지 않는 evidence-only 후속 변경임이 증명된 경우에만 연결을 허용하며 ancestor 또는 일부 hash 일치만으로 승인하지 않는다. 이 예외는 CI/status의 exact-head binding을 완화하지 않는다. 연결된 구현자 실행 기록과 reviewer의 독립 실행은 구분해 보고한다. +- Command evidence의 source revision과 reviewed head가 다르면 trusted provenance, ancestor 관계, 전체 source-to-head diff와 실행 입력(코드·설정·test·fixture·dependency/lockfile·실행 도구)의 동일성을 검증한다. 실행 입력에 영향을 주지 않는 evidence-only 또는 비실행 문서-only 후속 변경임이 증명된 경우에만 연결을 허용하며 ancestor 또는 일부 hash 일치만으로 승인하지 않는다. 이 예외는 CI/status의 exact-head binding을 완화하지 않는다. 연결된 구현자 실행 기록과 reviewer의 독립 실행은 구분해 보고한다. - 실패 경로, 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`로 기록한다. @@ -193,6 +194,7 @@ Canonical body를 렌더링하기 전에 trusted workflow directory에 JSON obje 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를 고정한다. + 실행 helper는 directory 종류별 canonical permission 계약과 authenticated repository metadata의 exact `clone_url`을 사용하며 bare directory에 임의 `0700` 조건을 추가하거나 `.git`을 제거하지 않는다. Close binding은 행 단위로 파싱하고 whitespace가 다음 행까지 매칭되지 않게 한다. Commit metadata의 실제 nested 필드와 collection의 declared count를 검증하며 `null` collection은 해당 wire 계약과 count가 empty를 증명할 때만 빈 배열로 처리한다. Hunk는 immutable base/head blob의 위치·내용으로 대조한다. 검증된 helper가 있으면 재사용하고, 임의 wire shape·문자열 재구성·diff 직렬화 일치로 gate를 대체하지 않는다. 6. 검증된 기존 cache에 대해 `issue lock → repository lock` 순서로 repository lock을 획득한다. Issue lock 획득 후 cache가 없어졌거나 invalid해졌으면 bootstrap 또는 자동 복구하지 않고 중단한다. 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를 대조한다. Diff 직렬화의 byte 차이만으로 실패시키지 않고 변경 경로와 exact base/head blob 및 hunk가 동일 변경을 나타내는지 검증한다. 임의 ref, checkout, clone 또는 worktree를 만들지 않는다. @@ -211,6 +213,7 @@ Canonical body를 렌더링하기 전에 trusted workflow directory에 JSON obje 19. Review create가 timeout·오류 또는 malformed response이면 blind retry하지 않는다. Complete review collection과 candidate review comments를 한 번 authoritative reconciliation해 baseline 대비 exact result가 하나이고 verdict-compatible 최종 state와 inline comment 부재가 확인될 때만 제출 완료로 판정한다. Exact owned `PENDING` review 하나가 확인되면 그 ID를 보존하고 partial publication으로 기록한다. 같은 review 제출이 승인된 경우에만, submit schema·성공 status 및 identity·Issue contract·PR base/head·changed files·review baseline·canonical body를 새로 검증하고(이미 인과가 증명된 해당 review의 파생 projection만 제외), 동일 ID를 명시적 verdict로 한 번 submit한 뒤 절차 18과 20의 readback을 적용한다. 새 create는 하지 않으며 submit 응답이 불확실하면 동일 ID를 authoritative readback해 최종 제출을 확인하거나 uncertain/partial로 중단한다. Candidate가 없거나 여러 개·경쟁 review·drift가 있으면 복구 write 없이 중단한다. 20. Source Issue와 PR을 다시 읽는다. Body·title·state·labels·assignees·milestone·comments, PR base·head·changed files·merge state와 source content는 불변이어야 한다. 새 create는 baseline 대비 신규 review record가 정확히 하나여야 하고 기존 `PENDING` 복구는 추가 record 없이 같은 ID를 유지해야 하며, record 수와 timeline event 수를 구분한다. 단, Gitea가 exact native review create 또는 승인된 동일 ID submit의 파생 projection으로만 다음을 변경한 경우는 허용한다: Issue와 PR `updated_at`이 verified review `submitted_at` 또는 동일 review ID·author의 verified create/submit timeline event timestamp로 갱신됨, PR `review_comments`가 top-level review 생성으로 baseline보다 정확히 1 증가함(동일 ID submit 복구 시 추가 증가는 확인된 provider 계약과 해당 review timeline event로 인과가 증명된 경우에만 허용), `requested_reviewers`에 verified review author stable account ID가 정확히 추가됨. `submitted_at`이 draft 생성 시각을 유지할 수 있으므로 최종 state와 submit event를 별도로 검증한다. `comments: []` 계약은 projection count와 별개로 authoritative `get_review_comments`가 0개여야 한다. 이 파생 변경과 아래의 제한된 기존 review 대체 projection은 각 write 전후 snapshot과 exact review ID·author·timestamp로 인과를 증명해야 하며 허용 목록 밖의 field 변경, 기존 reviewer 제거, 추가 account 또는 승인되지 않은 write call이 있으면 fail-closed한다. 검증된 submit은 별도 write로 기록하되 provider 파생 field 갱신을 직접 Issue/PR mutation으로 보고하지 않는다. 기존 review 대체 projection은 write 전에 authoritative provider 계약으로 대체 조건·대상·필드를 확인해 기록한 경우에만 허용한다. 동일 PR·동일 stable author의 baseline상 `official=true`, `dismissed=false`인 이전 review에서 `official: true→false`, `dismissed: false→true`, 해당 native create/submit event 시각으로의 `updated_at` 변경만 허용하며, 영향받은 모든 ID를 읽어 기존 ID·body·commit·state·author·stale와 나머지 필드 및 record 보존을 검증한다. 신규 review/event cardinality와 해당 write의 인과도 별도로 확인한다. Timestamp 일치나 과거 관측만으로 대체를 추정하지 않으며 다른 작성자·다른 필드 변경, 계약 미확인 또는 인과 불명은 `partial`/fail-closed로 기록하고 추가 write를 중단한다. 기존 flag를 직접 복원·dismiss하거나 과거 실행 결과를 소급 성공으로 바꾸지 않는다. + 별도로, 동일 PR·동일 stable author의 baseline상 이미 `dismissed=true`인 이전 approve/reject review는 서버 버전에 결합된 authoritative provider 계약으로 bulk-update 대상과 timestamp 동작을 write 전에 확인한 경우에만 해당 native create/submit event에 인과가 증명된 `updated_at` 갱신만 허용한다. 기존 `official`·`dismissed` 값과 ID·body·commit·state·author·stale 및 모든 나머지 필드·record는 그대로 보존하고 영향받은 모든 ID와 신규 review/event cardinality를 readback한다. Timestamp 일치만으로 인과를 추정하지 않으며 계약·인과가 미확인되면 write 전 차단하거나 write 후 `partial`/fail-closed로 중단한다. 21. 동일 state를 read-only replay해 stable deduplication identity의 canonical review를 재사용하며 `writes=[]`인지 확인한다. 22. Issue lock을 해제한 뒤 `repository.lock`과 `issue-.lock`을 각각 non-blocking으로 획득·해제할 수 있는지 확인한다.