[verified] docs: harden Gitea access and release contracts

This commit is contained in:
2026-09-30 16:39:33 +09:00
parent c05b4226bf
commit c50440b81b
8 changed files with 191 additions and 61 deletions
@@ -1,7 +1,7 @@
---
name: gitea-issue-implementation
description: 승인된 Gitea Issue를 구현·검증하고 Gitea PR로 전달한다.
version: 0.2.0
version: 0.3.0
author: genichin, Hermes Agent
license: MIT
platforms: [linux]
@@ -13,7 +13,7 @@ metadata:
# Gitea Issue Implementation
승인된 Gitea Discovery와 pinned repository revision을 근거로 Issue별 persistent worktree에서 요구 문서, source와 test를 구현하고 검증한 뒤 Issue 전용 branch와 Gitea PR로 전달한다. Repository cache와 worktree 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md), 문서 형식은 `docs/` 아래 각 문서 유형의 README와 TEMPLATE만 정본으로 사용한다. Exact Issue 구현 요청은 승인된 범위의 commit, 일반 push와 PR 생성을 승인하지만 merge, force-push, Issue close, release 또는 deployment를 승인하지 않는다.
승인된 Gitea Discovery와 pinned repository revision을 근거로 Issue별 persistent worktree에서 요구 문서, source와 test를 구현하고 검증한 뒤 Issue 전용 branch와 Gitea PR로 전달한다. Gitea 인증과 readback은 [Gitea authenticated access 운영 지침](../../../../operations/gitea-access.md), repository cache와 worktree 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md), 문서 형식은 `docs/` 아래 각 문서 유형의 README와 TEMPLATE만 정본으로 사용한다. Exact Issue 구현 요청은 승인된 범위의 commit, 일반 push와 PR 생성을 승인하지만 merge, force-push, Issue close, release 또는 deployment를 승인하지 않는다.
## 사용 시점
@@ -77,8 +77,8 @@ Issue body와 `updated_at`을 immutable approval snapshot으로 보존한다. bo
1. 요청에서 exact `owner`, `repository`와 Issue 번호를 추출하고 각각 canonical identifier 규칙으로 검증한다.
2. Issue lock을 획득한다.
3. Gitea MCP `get_me`로 현재 impl role identity를 확인한다.
4. Gitea MCP로 exact repository metadata, default branch와 SHA, Issue 전체 필드와 전체 comment baseline을 읽는다.
3. Canonical authenticated Gitea API adapter로 현재 impl role의 stable account identity를 확인한다.
4. 같은 adapter로 exact repository metadata, default branch와 SHA, Issue 전체 필드와 전체 comment baseline을 읽는다.
5. title, body, state, labels, assignees, milestone, `updated_at`, comment cardinality와 body digest를 immutable approval snapshot으로 기록한다.
완료 조건: authenticated identity, exact target과 재현 가능한 approval snapshot이 모두 존재한다.
@@ -1,7 +1,7 @@
---
name: gitea-release
description: 승인된 Gitea 버전을 준비·태깅하고 산출물을 게시한다.
version: 0.1.0
version: 0.3.0
author: genichin, Hermes Agent
license: MIT
platforms: [linux]
@@ -13,7 +13,7 @@ metadata:
# Gitea Release
Gitea repository cache를 사용해 버전 준비, 검증, 태깅과 프로젝트별 산출물 게시를 수행한다. Cache 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md)을 정본으로 사용한다.
Gitea repository cache를 사용해 버전 준비, 검증, 태깅과 프로젝트별 산출물 게시를 수행한다. Gitea 인증과 readback은 [Gitea authenticated access 운영 지침](../../../../operations/gitea-access.md), cache 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md)을 정본으로 사용한다.
## 사용 시점
@@ -41,7 +41,7 @@ Issue 구현, PR merge, 임의 버전 선택, 기존 tag 이동, artifact 덮어
### 프로젝트별 처리
Target repository의 release contract가 담당한다.
Target repository의 `.gitea/release.yaml` contract가 담당한다.
- version source와 함께 변경할 lockfile
- test, lint와 build 명령
@@ -51,7 +51,37 @@ Target repository의 release contract가 담당한다.
- smoke test와 게시 명령
- digest, checksum 또는 provenance 검증
Release contract가 없거나 모호하면 기존 workflow, build metadata와 문서를 읽어 확인된 사실만 보고한다. 이미지 이름, registry, credential, 명령 또는 artifact를 추측하지 않는다.
기존 workflow, build metadata와 문서는 contract 작성·검토의 근거일 뿐 게시 정본이 아니다. Contract가 없거나 모호하면 확인된 사실만 보고하고 준비 commit 또는 게시를 시작하지 않는다. 이미지 이름, registry, credential, 명령 또는 artifact를 추측하지 않는다.
## Repository release contract
Repository root의 `.gitea/release.yaml`을 프로젝트별 릴리즈 정본으로 사용한다. Safe YAML mapping으로 읽고 duplicate key, alias·custom tag, 알 수 없는 schema·field·adapter·artifact type을 거부한다. 현재 지원 schema는 exact `gitea-agent/release/v1`이다.
### 공통 계약
- `version.sources`는 version을 읽고 변경할 repository-relative path, format과 selector를 선언한다. 현재 지원 format은 dotted key를 지정하는 `toml`과 top-level 문자열 대입 이름을 지정하는 `python-assignment`다.
- `version.lockfiles`는 version source와 함께 갱신·검증할 lockfile을 선언한다. 현재는 `uv.lock`의 exact package entry만 지원한다.
- `version.tag_template`은 `{version}`으로 exact tag를 만든다.
- `prepare.runtime`은 검증 runtime을, `prepare.commands[].argv`는 순서대로 실행할 명령과 인수를 선언한다.
- `artifacts[]`는 `type`, build 또는 source 처리, smoke, publish와 authoritative verify 항목을 선언한다.
- Credential에는 secret 값이 아니라 active profile에서 읽을 환경변수 이름만 기록한다.
`argv`는 shell command가 아니다. 각 항목을 argument 배열로 직접 실행하고 glob, command substitution, redirection, pipe, shell variable expansion을 적용하지 않는다. 빈 argument, 문자열이 아닌 argument 또는 실행 파일이 repository 계약과 무관하면 거부한다.
지원 placeholder는 `{version}`, `{tag}`, `{commit}`, `{run_id}`뿐이다. `{commit}`은 prepared full SHA, `{run_id}`는 이번 local 실행에만 사용하는 비밀이 아닌 충돌 방지 식별자다. 다른 placeholder, 재귀 치환 또는 치환 결과의 shell 재해석을 금지한다.
Contract의 모든 path와 build context는 release worktree 내부의 non-symlink 경로로 해석돼야 한다. `..`, absolute path, symlink escape와 worktree 밖 script를 거부한다. Contract 자체가 symlink이면 중단한다.
### Artifact adapter
- `type: container`는 build adapter, exact platform·context·Dockerfile, smoke checks, registry·repository, credential 이름, tags, overwrite 정책과 readback 항목을 요구한다. Build한 하나의 local image를 smoke test하고 그 동일 image digest만 게시한다. 재빌드 결과를 대신 게시하지 않는다.
- `type: source`는 container build를 실행하지 않는다. Tag만으로 제공되는 source archive 또는 별도 승인된 Gitea Release·attachment를 `publish`에 명시하고 checksum readback을 요구한다.
지원하지 않는 artifact type이나 adapter는 구현을 추측하지 않고 중단한다. `latest`, 암묵적 channel, 계약에 없는 tag·attachment 또는 default registry를 추가하지 않는다.
### Contract 고정
Contract를 읽은 exact bytes의 SHA-256, schema와 path를 `state.json`에 기록한다. `.gitea/release.yaml`은 prepared commit tree에 포함돼야 한다. 준비 검증, tag 생성, build와 publish 직전에 prepared tree의 contract hash를 다시 계산해 기록값과 비교한다. 차이가 있으면 이전 검증과 prepared 상태를 무효화한다.
## 승인 계약
@@ -81,7 +111,7 @@ Tag 또는 artifact를 외부에 게시하려면 다음이 필요하다.
Repository마다 동시에 하나의 release workflow만 허용한다.
```text
/opt/data/gitea-agent/repositories/<owner>/<repository>/
<harness-root>/repositories/<owner>/<repository>/
├── locks/release.lock
└── worktrees/release/
├── state.json
@@ -94,15 +124,15 @@ Repository마다 동시에 하나의 release workflow만 허용한다.
- 기존 release worktree를 reset, clean, rebase, checkout, force-remove 또는 덮어쓰지 않는다.
- 실패한 release worktree는 증거 보존을 위해 자동 제거하지 않는다.
`state.json`에는 최소한 schema `gitea-agent.release-worktree/v1`, repository identity, base SHA, requested version·tag, prepared commit SHA와 단계 상태를 기록한다. Credential, PID 또는 secret 값은 기록하지 않는다.
`state.json`에는 최소한 schema `gitea-agent.release-worktree/v1`, repository identity, base SHA, requested version·tag, prepared commit SHA, contract path·schema·SHA-256과 단계 상태를 기록한다. Credential 이름은 기록할 수 있지만 credential 값, PID 또는 secret 값은 기록하지 않는다.
## 절차
### 1. Target과 cache 확인
1. 요청의 repository, version, tag와 승인 범위를 추출한다.
2. Gitea MCP로 authenticated identity, repository metadata, default branch와 SHA를 읽는다.
3. `operations/repository-cache.md`에 따라 cache를 검증하거나 초기화한다.
2. Canonical authenticated Gitea API adapter로 identity, repository metadata, default branch와 SHA를 읽는다.
3. `operations/repository-cache.md`를 새로 읽고 실제 문서 경로에서 `<harness-root>`와 repository cache root를 계산·검증한 뒤 cache를 검증하거나 초기화한다.
4. Release lock 아래 repository lock을 획득해 exact origin을 prune/fetch한다.
5. Gitea default-branch SHA와 local mirror ref 일치를 확인한다.
@@ -119,23 +149,29 @@ Repository마다 동시에 하나의 release workflow만 허용한다.
### 3. 프로젝트 계약 조사
1. `search_files`와 `read_file`로 version metadata, lockfile, test, build, 기존 workflow와 release 문서를 읽는다.
2. Version 변경 파일, 준비 검증과 게시 adapter를 구분한다.
3. 정확한 게시 대상이나 credential 가용성을 확인할 수 없으면 수정 전에 중단한다.
1. Release worktree root의 exact `.gitea/release.yaml` 존재, regular-file 유형과 경로 경계를 확인한다.
2. Safe YAML로 읽고 exact schema, 허용 field, argument 배열, placeholder와 path를 검증한다.
3. `version.sources`와 `version.lockfiles`를 `read_file`로 읽어 현재 선언 version이 서로 일치하는지 확인한다. 요청된 exact version과 다르면 stage 4에서 변경할 exact path와 selector를 version allowlist로 고정한다.
4. `tag_template` 결과가 요청된 exact tag와 일치하는지 확인한다.
5. `prepare.commands`, artifact type, build·smoke·publish adapter, exact target과 verify 항목을 분리한다.
6. Contract bytes의 SHA-256을 계산해 path·schema와 함께 `state.json`에 기록한다.
7. Credential 값은 읽거나 출력하지 않은 채 선언된 이름이 active profile에 존재하고 exact target에 사용할 수 있는지만 확인한다.
8. 기존 workflow, build metadata와 release 문서는 contract와 충돌하는 stale 지시가 없는지 검토한다. 충돌하면 contract를 임의 해석하지 않고 중단한다.
완료 조건: 변경 파일 allowlist, 준비 검증 명령과 프로젝트별 게시 절차가 명확하다.
완료 조건: 검증된 contract hash에 변경 파일 allowlist, exact 준비 명령, artifact adapter, 게시 대상과 authoritative readback이 모두 고정돼 있다.
### 4. 버전 변경과 준비 commit
1. 승인된 exact version만 allowlist 파일에 반영한다.
2. Project-defined 준비 test와 정적 검사를 실행한다.
3. 수정·미추적 파일 전체를 검사하고 allowlist 밖의 변경이 있으면 중단한다.
4. Exact path만 stage하고 staged diff, secret, 삭제와 whitespace 오류를 검토한다.
5. Non-amended local commit을 생성한다.
6. Commit의 parent, tree, version·tag 일치와 clean worktree를 검증한다.
7. `state.json`에 prepared full SHA와 검증 결과를 기록한다.
1. 승인된 exact version만 contract의 `version.sources`와 `version.lockfiles` allowlist에 반영한다.
2. Contract 변경이나 다른 non-version 변경은 사용자에게 명시적으로 승인된 exact path만 별도 allowlist에 포함한다.
3. `prepare.commands`를 선언 순서대로, worktree root에서 shell 없이 exact `argv`로 실행한다. Exit code와 비민감 결과를 기록한다.
4. 수정·미추적 파일 전체를 검사하고 두 allowlist 밖의 변경이 있으면 중단한다.
5. Exact path만 stage하고 staged diff, secret, 삭제와 whitespace 오류를 검토한다.
6. Non-amended local commit을 생성한다.
7. Commit의 parent, tree, version·tag, contract hash 일치와 clean worktree를 검증한다.
8. `state.json`에 prepared full SHA, contract hash와 검증 결과를 원자적으로 기록한다.
완료 조건: 승인된 버전 변경만 포함한 하나의 검증된 local commit이 존재한다.
완료 조건: 승인된 exact 변경만 포함하고 contract와 준비 검증이 고정된 local prepared commit이 존재한다.
### 5. 게시 gate
@@ -147,6 +183,8 @@ Repository마다 동시에 하나의 release workflow만 허용한다.
- 필요한 credential과 target이 확인됐다.
- 필수 test와 check가 exact prepared commit에서 성공했다.
- Worktree HEAD와 tree가 준비 검증 이후 바뀌지 않았다.
- Prepared tree의 `.gitea/release.yaml` hash가 `state.json`과 일치한다.
- Contract의 모든 adapter, target, tag와 verify 항목이 지원된다.
하나라도 불명확하면 외부 상태를 변경하지 않는다.
@@ -155,15 +193,21 @@ Repository마다 동시에 하나의 release workflow만 허용한다.
1. 승인된 exact tag를 prepared commit에 생성한다.
2. Explicit remote URL과 refspec으로 신규 tag만 non-force push한다.
3. Gitea readback으로 remote tag target이 prepared SHA와 일치하는지 확인한다.
4. Project release contract의 build, smoke test와 publish 절차를 그대로 실행한다.
5. 승인된 artifact와 immutable commit-derived tag만 게시한다.
4. Prepared tree에서 contract hash를 다시 검증한다.
5. `type: container`이면 contract의 exact platform·context·Dockerfile과 label로 한 번 build하고 선언된 smoke checks를 같은 local image에 실행한다.
6. Registry credential은 선언된 환경변수에서만 읽고 URL, argv, Git config, state 또는 로그에 넣지 않는다. Redirect를 거부하고 exact registry origin에만 보낸다.
7. `overwrite: false`이면 모든 선언 remote image tag의 부재를 확인한 뒤 검증한 동일 local image를 선언된 tag로 게시한다.
8. `type: source`이면 container 명령을 건너뛰고 contract와 별도 게시 승인에 선언된 Gitea Release 또는 attachment만 게시한다.
9. 승인된 artifact와 immutable commit-derived tag만 게시한다.
`latest`, 추가 channel, 추정 artifact 또는 기존 tag를 게시·이동·덮어쓰지 않는다.
### 7. 권위 있는 검증
- Gitea remote tag target을 다시 읽는다.
- 게시 artifact의 version, digest 또는 checksum을 authoritative target에서 읽는다.
- Contract의 `verify` 항목을 모두 authoritative target에서 읽는다.
- Container는 최소 digest, platform과 prepared SHA revision label을 검증한다.
- Source attachment는 exact filename, size와 checksum을 검증한다.
- Artifact provenance가 prepared SHA와 일치하는지 확인한다.
- 여러 tag를 게시했다면 모두 같은 승인 artifact를 가리키는지 확인한다.
- Gitea Release가 별도 승인됐다면 target, metadata와 attachments를 다시 읽는다.
@@ -184,6 +228,8 @@ Partial failure, dirty state, 미게시 commit 또는 불확실한 readback에
## 실패 처리
- Version, tag, commit, artifact 또는 target을 추측하지 않는다.
- `.gitea/release.yaml`이 없거나 schema·hash·path·adapter 검증에 실패하면 준비 commit과 게시를 시작하지 않는다.
- Workflow나 README를 contract의 대체 정본으로 사용하지 않는다.
- 기존 tag를 force-update, 삭제 또는 재생성하지 않는다.
- 기존 artifact를 덮어쓰거나 삭제하지 않는다.
- 실패한 build를 임의 변경으로 수리하지 않는다.
@@ -1,7 +1,7 @@
---
name: gitea-discovery-authoring
description: Gitea Issue의 Discovery 초안을 작성하고 게시한다.
version: 0.3.4
version: 0.4.0
author: genichin, Hermes Agent
license: MIT
platforms: [linux]
@@ -13,7 +13,7 @@ metadata:
# Gitea Discovery Authoring
Gitea Issue 원본과 저장소 근거를 조사해 Discovery 초안을 작성하고 Issue 본문에 게시한다. 작성 규칙은 [Discovery 작성 방법](../../../../docs/discovery/README.md), 문서 구조는 [Discovery 템플릿](../../../../docs/discovery/TEMPLATE.md)만 정본으로 사용하며 이 스킬에 복제하거나 임의로 확장하지 않는다.
Gitea Issue 원본과 저장소 근거를 조사해 Discovery 초안을 작성하고 Issue 본문에 게시한다. Gitea 인증과 readback은 [Gitea authenticated access 운영 지침](../../../../operations/gitea-access.md), 작성 규칙은 [Discovery 작성 방법](../../../../docs/discovery/README.md), 문서 구조는 [Discovery 템플릿](../../../../docs/discovery/TEMPLATE.md)만 정본으로 사용하며 이 스킬에 복제하거나 임의로 확장하지 않는다.
## 사용 시점
@@ -36,8 +36,8 @@ Discovery 초안을 작성하기 전에 repository cache admission gate를 반
## 절차
1. 요청에서 exact `owner`, `repository`, Issue 번호를 추출하고 형식을 검증한다.
2. Issue lock을 획득한 상태에서 Gitea MCP `get_me`로 spec-agent identity를 확인한다.
3. Gitea MCP로 exact repository metadata, Issue 전체 내용과 전체 comment baseline을 읽는다. Issue title, body, state, labels, assignees, milestone과 `updated_at`을 immutable pre-write snapshot으로 보존한다.
2. Issue lock을 획득한 상태에서 canonical authenticated Gitea API adapter로 spec-agent의 stable account identity를 확인한다.
3. 같은 adapter로 exact repository metadata, Issue 전체 내용과 전체 comment baseline을 읽는다. Issue title, body, state, labels, assignees, milestone과 `updated_at`을 immutable pre-write snapshot으로 보존한다.
4. `operations/repository-cache.md`를 새로 읽는다. Issue lock을 유지한 채 대상 cache가 없거나 초기화되지 않았다면 `gitea-repository-cache-bootstrap` 스킬을 사용한다.
5. bootstrap 완료 여부와 관계없이 canonical 순서에 따라 repository lock을 획득한다. path, bare 상태와 remote identity를 검증한 뒤 authoritative origin에서 prune/fetch한다. fetch 후 Gitea default branch와 SHA를 다시 읽고 local ref가 exact SHA와 일치하는지 확인하여 pinned source revision으로 기록한다. 어느 단계든 실패하면 repository lock을 해제하고 외부 write와 Discovery 작성을 수행하지 않는다.
6. `read_file`로 `docs/discovery/README.md`와 `docs/discovery/TEMPLATE.md`를 새로 읽는다.
@@ -65,7 +65,7 @@ comment는 다음 형식을 사용한다. `<original-body>`에는 write 직전 G
`body-sha256`은 Gitea가 반환한 원본 body의 UTF-8 bytes에 대해 `terminal`로 계산한다. 게시 후 comment의 author, target marker, body digest와 `<original-body>` exact bytes를 모두 검증한다. 이 comment metadata를 Issue body에 포함하지 않는다.
- 원본 comment와 Discovery body는 trusted workflow directory에 artifact로 먼저 작성하고 실제 write payload와 exact-match하는지 확인한다.
- Discovery body는 TEMPLATE에서 만든 artifact의 exact bytes를 전송하고 즉시 Gitea MCP readback으로 검증한다.
- Discovery body는 TEMPLATE에서 만든 artifact의 exact bytes를 전송하고 즉시 같은 authenticated adapter의 readback으로 검증한다.
- 다른 checkout, workspace, installed package 또는 외부 renderer를 import하지 않는다.
- credential 값은 출력하거나 artifact에 기록하지 않는다.
@@ -92,7 +92,7 @@ comment는 다음 형식을 사용한다. `<original-body>`에는 write 직전 G
완료 전에 다음을 모두 확인하고 구분해 보고한다.
- authenticated MCP identity
- authenticated stable account identity와 adapter provenance
- repository cache 경로, 신규 초기화 또는 기존 재사용 여부, fetch 결과, bare 상태, pinned branch와 Gitea/local SHA 일치
- 원본 Issue snapshot과 comment baseline
- 조사한 repository evidence
@@ -103,4 +103,4 @@ comment는 다음 형식을 사용한다. `<original-body>`에는 write 직전 G
- 최종 comment cardinality와 중복 원본 comment 부재
- dry-run/local 검증과 실제 Gitea write 결과
프로세스 exit나 MCP write 응답만으로 성공을 주장하지 않는다. authoritative readback이 하나라도 실패하면 partial 또는 failure로 보고한다.
프로세스 exit나 API write 응답만으로 성공을 주장하지 않는다. Authoritative readback이 하나라도 실패하면 partial 또는 failure로 보고한다.
@@ -1,7 +1,7 @@
---
name: gitea-discovery-review
description: 수정된 Gitea Discovery를 검토하고 정규화한다.
version: 0.2.0
version: 0.3.0
author: genichin, Hermes Agent
license: MIT
platforms: [linux]
@@ -15,7 +15,7 @@ metadata:
사용자가 Gitea Issue의 Discovery body에서 OQ를 선택하거나 본문을 수정한 뒤 그 수정본을 검토해 달라고 요청할 때 사용한다. 현재 Issue body를 review candidate의 정본으로 삼아 결정 전파, 모순 제거, 후속 OQ와 문서 영향 재평가를 수행한다. Discovery 승인, label·assignee 변경, 구현 handoff 또는 후속 문서·source 작성은 수행하지 않는다.
작성 규칙은 [Discovery 작성 방법](../../../../docs/discovery/README.md), visible 구조는 [Discovery 템플릿](../../../../docs/discovery/TEMPLATE.md), cache와 lock 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md)만 정본으로 사용한다.
Gitea 인증과 readback은 [Gitea authenticated access 운영 지침](../../../../operations/gitea-access.md), 작성 규칙은 [Discovery 작성 방법](../../../../docs/discovery/README.md), visible 구조는 [Discovery 템플릿](../../../../docs/discovery/TEMPLATE.md), cache와 lock 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md)만 정본으로 사용한다.
## 사용 시점
@@ -50,7 +50,7 @@ metadata:
## 절차
1. 요청에서 exact `owner`, `repository`, Issue 번호를 추출하고 단일 안전 경로 요소인지 검증한다.
2. canonical 순서로 Issue lock을 획득하고 Gitea MCP `get_me`로 review role identity를 확인한다.
2. canonical 순서로 Issue lock을 획득하고 authenticated Gitea API adapter로 review role의 stable account identity를 확인한다.
3. exact Issue와 전체 comments를 읽어 body, `updated_at`, title, state, labels, assignees, milestone과 comment baseline을 immutable snapshot으로 보존한다.
4. 이 스킬의 입력 승인 gate로 current body와 최초 authoring의 원본 provenance comment를 검증한다. 실패하면 comment와 body를 쓰지 않는다.
5. `operations/repository-cache.md`를 새로 읽고 Issue lock을 유지한 채 기존 cache를 검증한다. cache가 없으면 `gitea-repository-cache-bootstrap`을 사용한다.
@@ -92,4 +92,4 @@ metadata:
- comment baseline 완전 불변과 replay no-op 결과
- partial 또는 fail-closed 상태
프로세스 exit나 MCP write 응답만으로 성공을 주장하지 않는다. authoritative readback 또는 replay 검증이 하나라도 실패하면 completed로 보고하지 않는다.
프로세스 exit나 API write 응답만으로 성공을 주장하지 않는다. Authoritative readback 또는 replay 검증이 하나라도 실패하면 completed로 보고하지 않는다.
@@ -1,7 +1,7 @@
---
name: gitea-implementation-spec-review
description: 승인된 계약에 대해 Gitea 구현 PR 적합성을 검토한다.
version: 0.1.0
version: 0.2.0
author: genichin, Hermes Agent
license: MIT
platforms: [linux]
@@ -13,7 +13,7 @@ metadata:
# 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로 기록한다. 일반 코드 품질·보안 검토, source 수정, Discovery 변경과 merge는 수행하지 않는다.
`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는 수행하지 않는다.
## 사용 시점
@@ -38,15 +38,15 @@ Issue comment·body·title·state·label·assignee·milestone, repository file,
- 일반적인 코드 스타일, 광범위한 보안 탐색, 성능 최적화와 유지보수성은 독립 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 전용 Gitea MCP connection으로만 작성한다. 해당 connection의 `get_me` stable account ID를 snapshot에 기록하고 ambient REST token, impl-agent credential 또는 다른 profile credential로 fallback하지 않는다.
- 전용 MCP connection이나 expected stable account identity를 검증할 수 없으면 read-only 분석과 native review write를 모두 완료로 보고하지 않는다.
- 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다.
- Gitea MCP `get_me`로 확인한 stable account ID가 spec review role이며 PR author·implementation role의 stable account ID와 다르다. Transport별 login 표시가 달라도 account ID가 같으면 같은 identity로 판정한다.
- 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 #<issue-number>`가 하나만 있고 다른 close directive가 없다.
- Source Issue body 첫 줄이 exact `<!-- gitea-agent:discovery-draft/v2 -->`이며 canonical H2 구조를 만족한다.
@@ -188,7 +188,7 @@ Canonical body를 렌더링하기 전에 trusted workflow directory에 JSON obje
1. Exact target identifiers를 검증하고 `operations/repository-cache.md`를 새로 읽는다.
2. Canonical path와 mode를 검증한 source Issue lock을 획득한다.
3. Gitea MCP `get_me`로 spec-agent stable account ID를 확인하고 PR author와 분리됐는지 검증한다.
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을 획득한다.
@@ -202,7 +202,7 @@ Canonical body를 렌더링하기 전에 trusted workflow directory에 JSON obje
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. Gitea MCP `pull_request_review_write(method=create)`를 `body=<canonical body>`, `comments=[]`, `commit_id=<exact head SHA>`, `state=<APPROVED|REQUEST_CHANGES|COMMENT>`로 정확히 한 번 호출한다. `state`는 verdict mapping과 exact-match해야 한다.
17. Authenticated adapter의 native review create operation을 `body=<canonical body>`, `comments=[]`, `commit_id=<exact head SHA>`, `state=<APPROVED|REQUEST_CHANGES|COMMENT>`로 정확히 한 번 호출한다. 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한다.
@@ -1,7 +1,7 @@
---
name: gitea-repository-cache-bootstrap
description: 새 Gitea repository cache를 안전하게 초기화한다.
version: 0.1.0
version: 0.2.0
author: genichin, Hermes Agent
license: MIT
platforms: [linux]
@@ -13,11 +13,11 @@ metadata:
# Gitea Repository Cache Bootstrap
새 Gitea repository cache를 생성하거나 기존 cache가 초기화됐는지 검증한다. 모든 경로, lock, Git 및 credential 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md)만 정본으로 사용하며 이 스킬에 복제하거나 완화하지 않는다.
새 Gitea repository cache를 생성하거나 기존 cache가 초기화됐는지 검증한다. Gitea 인증과 readback은 [Gitea authenticated access 운영 지침](../../../../operations/gitea-access.md), 모든 경로, lock과 Git 규칙은 [Repository cache 운영 지침](../../../../operations/repository-cache.md)만 정본으로 사용하며 이 스킬에 복제하거나 완화하지 않는다.
## 사용 시점
- `/opt/data/gitea-agent/repositories/<owner>/<repository>/repository.git`이 없을 때
- canonical 문서에서 계산한 `<harness-root>/repositories/<owner>/<repository>/repository.git`이 없을 때
- 정확한 `owner/repository`의 cache 초기화를 요청받았을 때
- 기존 cache가 해당 Gitea repository의 유효한 bare mirror인지 확인할 때
@@ -25,9 +25,9 @@ Issue 본문 변경, comment 작성, checkout, worktree 생성 또는 source 수
## 절차
1. `read_file`로 linked canonical 문서 `operations/repository-cache.md`를 새로 읽는다.
1. `read_file`로 linked canonical 문서 `operations/repository-cache.md`를 새로 읽고 실제 문서 경로에서 `<harness-root>`와 repository cache root를 계산·검증한다.
2. 요청에서 exact `owner/repository`를 추출하고 canonical 지침의 identifier·path 검증을 수행한다.
3. Gitea MCP로 authenticated role, exact repository metadata, clone URL, default branch와 SHA를 읽는다.
3. Canonical authenticated Gitea API adapter로 role identity, exact repository metadata, clone URL, default branch와 SHA를 읽는다.
4. canonical bootstrap lock을 획득하고 target 상태를 다시 확인한다.
5. target이 없으면 canonical 신규 cache 초기화 절차를 그대로 수행한다. target이 있으면 삭제하거나 덮어쓰지 않고 canonical 기존 cache 검증 절차를 수행한다.
6. final target을 새로 읽어 path safety, bare 상태, remote identity, default branch와 SHA를 검증한다.
+73
View File
@@ -0,0 +1,73 @@
# Gitea authenticated access 운영 지침
이 문서는 Gitea Agent harness가 Gitea의 authoritative state를 읽고 승인된 mutation을 수행할 때 사용하는 canonical access 계약이다. 모든 agent와 skill은 특정 transport를 정본으로 취급하지 않고, 이 문서의 identity·credential·readback 조건을 충족하는 authenticated API adapter를 사용한다.
## 고정 origin과 transport
- 허용된 Gitea origin은 exact `https://gitea.jsfamily.quest`다.
- Authenticated API adapter는 전용 Gitea MCP connection 또는 release/spec/impl 등 현재 role의 credential을 사용하는 직접 Gitea REST client일 수 있다.
- MCP method 이름, REST client 구현과 command 성공은 정본이 아니다. 위 origin이 반환한 authenticated response와 fresh readback이 정본이다.
- 다른 origin, mirror API, public web page, unauthenticated response 또는 다른 role의 adapter로 fallback하지 않는다.
- Redirect는 자동 추적하지 않는다. 특히 credential을 다른 origin에 전달하지 않는다.
## Identity gate
1. 모든 workflow는 첫 authoritative read 전에 authenticated adapter로 현재 사용자를 읽는다. REST adapter는 exact `GET /api/v1/user`를 사용한다.
2. Stable numeric account ID, login과 현재 workflow role을 기록한다. Transport에 따라 login 표시가 달라도 stable account ID가 같으면 같은 identity다.
3. 예상 role identity를 확인할 수 없거나 API가 `401`, `403`, redirect, malformed response 또는 anonymous identity를 반환하면 fail-closed한다.
4. Workflow 동안 adapter와 credential source를 바꾸지 않는다. 재인증이 필요하면 현재 operation을 중단하고 snapshot부터 다시 시작한다.
## 직접 REST adapter
- Base URL은 exact `https://gitea.jsfamily.quest/api/v1`로 고정하고 TLS certificate 검증을 끄지 않는다.
- Token은 현재 role profile의 exact `$HERMES_HOME/.env`에 `GITEA_TOKEN`으로 저장하고 해당 파일의 mode를 `0600`으로 유지한다. Named profile에서는 `$HERMES_HOME`이 `~/.hermes/profiles/<profile>`이므로 같은 변수 이름을 사용해도 role별 token이 격리된다. 승인된 external secret manager를 사용하면 같은 profile scope에 `GITEA_TOKEN`으로 주입한다. 다른 profile, inherited ambient token, interactive prompt 또는 public access로 fallback하지 않는다.
- Token을 URL, command argv, Git config, remote URL, log, exception text, state, artifact 또는 repository file에 기록하지 않는다.
- Client는 token을 process 내부에서 읽어 `Authorization` header에 넣거나 보호된 file descriptor·stdin과 동등한 mechanism으로 전달한다. Secret이 shell expansion 후 argv에 나타나는 호출은 금지한다.
- Response status와 JSON shape를 검증한다. Collection endpoint는 Gitea pagination metadata에 따라 마지막 page까지 읽고 cardinality를 기록한다.
- `429`와 일시 오류는 read operation에서만 bounded retry할 수 있다. Mutation timeout·오류는 blind retry하지 않고 authoritative reconciliation을 먼저 수행한다.
## Repository와 Git
- Repository metadata, default branch와 branch full SHA는 authenticated adapter로 exact target에서 읽는다.
- Git clone/fetch/push credential은 API token을 credential-bearing URL에 넣지 않고 short-lived askpass 또는 동등한 child-process mechanism으로 전달한다.
- Git command 성공만으로 remote state를 확정하지 않는다. Fetch 후 default-branch ref를 API SHA와 비교하고, push 후 exact remote ref를 authenticated adapter로 다시 읽는다.
## Mutation과 readback
- Direct REST와 MCP에 동일한 승인 gate, exact payload, idempotency, drift 검사와 readback 규칙을 적용한다.
- Mutation 직전에 target identity, approval snapshot과 baseline을 다시 읽는다.
- 승인된 exact endpoint와 payload만 한 번 호출한다. Unstated default field에 의존하지 않는다.
- 성공 response만으로 완료를 주장하지 않는다. Exact target을 fresh readback하고 author stable account ID, payload, timestamp, commit/ref와 collection cardinality를 baseline과 비교한다.
- Timeout, malformed response 또는 connection loss 뒤에는 같은 mutation을 재호출하기 전에 complete collection을 한 번 읽어 결과를 reconciliation한다. 결과가 없거나 여러 개이거나 경쟁 mutation과 구분할 수 없으면 uncertain/partial로 중단한다.
## Credential 안전
- Credential 값은 role profile의 secret store에만 저장하고 repository, harness 문서와 workflow artifact에는 저장하지 않는다.
- Child process에 credential이 필요하면 최소 범위 environment 또는 보호된 descriptor로 전달하고 종료 시 helper와 temporary file을 제거한다.
- Credential의 존재 여부, source와 cleanup 결과만 보고하며 값을 출력하지 않는다.
- Read-only 단계에는 필요한 최소 scope를, tag push·review·Issue mutation에는 승인된 작업에 필요한 scope만 사용한다.
## Fail-closed 조건
다음 중 하나라도 발생하면 authenticated operation을 완료로 보고하지 않는다.
- 허용 origin 또는 target repository 불일치
- Authenticated stable account identity 확인 실패
- Role credential source 불명확 또는 다른 role credential 사용
- Redirect, TLS 검증 실패, `401`, `403` 또는 malformed API response
- Pagination 미완료 또는 baseline cardinality 불명확
- Mutation 결과와 fresh readback 불일치
- Credential 노출 또는 helper cleanup 결과 불확실
## 보고
완료 보고에는 adapter 종류 자체보다 다음 검증 결과를 포함한다.
- exact Gitea origin
- authenticated stable account ID와 login
- exact repository와 authoritative default branch full SHA
- 사용한 transport 종류와 role credential source의 이름만 표시한 provenance
- 수행한 mutation의 exact target과 fresh readback 결과
- pagination, drift, reconciliation과 partial/fail-closed 상태
Token 값, authorization header와 credential-bearing URL은 보고하지 않는다.
+22 -11
View File
@@ -1,19 +1,28 @@
# Repository cache 운영 지침
이 문서는 Gitea Agent harness가 사용하는 local repository cache의 canonical 운영 규칙이다. 모든 agent와 skill은 cache를 생성·갱신·검증할 때 이 문서를 읽고 따라야 하며 별도의 완화된 규칙을 만들지 않는다.
이 문서는 Gitea Agent harness가 사용하는 local repository cache의 canonical 운영 규칙이다. 모든 agent와 skill은 cache를 생성·갱신·검증할 때 이 문서와 [Gitea authenticated access 운영 지침](gitea-access.md)을 읽고 따라야 하며 별도의 완화된 규칙을 만들지 않는다.
## 목적과 범위
Repository cache는 Gitea repository의 Git 객체와 refs를 재사용하기 위한 bare mirror다. 문서 근거 조사와 Issue별 worktree 생성의 source로 사용할 수 있지만 그 자체는 checkout, 작업 공간 또는 외부 상태의 정본이 아니다.
- Gitea MCP readback이 repository identity와 authoritative ref의 정본이다.
- Canonical access 계약을 충족하는 authenticated Gitea API readback이 repository identity와 authoritative ref의 정본이다.
- `repository.git`은 확인한 Gitea 상태와 일치할 때만 사용한다.
- cache 생성과 갱신은 local filesystem 및 Git refs만 변경한다. Gitea에는 write하지 않는다.
## Harness root 결정
Repository cache 경로는 고정된 machine-local 절대경로나 현재 작업 directory에서 추측하지 않는다. Agent가 이번 작업에서 `read_file`로 실제 읽은 이 문서의 경로가 exact `<harness-root>/harness/operations/repository-cache.md` 형식인지 확인하고, 그 경로에서 `<harness-root>`를 계산한다. 따라서 repository 전체를 다른 위치에 설치해도 cache root는 항상 `<harness-root>/repositories`다.
- 이 문서의 경로, `operations`, `harness`와 `<harness-root>`를 각각 `lstat`하고 symlink가 아닌지 확인한다.
- 문서 경로가 위 구조와 exact-match하지 않거나 `<harness-root>`를 하나로 결정할 수 없으면 fail-closed한다.
- `pwd`, shell 시작 directory, 사용자 home, 다른 checkout, 환경변수 또는 과거 session 값을 root 결정 근거로 사용하지 않는다.
- Source checkout과 runtime cache가 같은 root 아래 있더라도 repository source로 혼동하지 않는다. Runtime cache는 `<harness-root>/repositories` 아래에서만 관리한다.
## 경로 구조
```text
/opt/data/gitea-agent/repositories/
<harness-root>/repositories/
├── .locks/
│ └── <owner>/
│ └── <repository>.bootstrap.lock
@@ -40,11 +49,13 @@ Repository cache는 Gitea repository의 Git 객체와 refs를 재사용하기
1. `owner`와 `repository`는 요청에서 받은 값을 보존하되 각각 안전한 단일 경로 요소인지 검증한다.
2. 빈 값, 경로 구분자, NUL, `.`과 `..` 또는 traversal을 허용하지 않는다.
3. `/opt/data/gitea-agent`는 지정된 trusted harness root다. NFS mount root의 numeric owner가 실행 UID와 달라도 허용하지만 exact path가 directory이고 symlink가 아니며 world-writable이 아닌지 확인한다.
4. trust boundary 아래 `repositories`, `.locks`, owner, repository와 `locks`는 생성 전후 `lstat`으로 검사한다. 모두 symlink가 아닌 directory, 실행 role 소유, mode `0700`이어야 한다.
5. lock 파일과 임시 credential helper는 실행 role 소유와 mode `0600`을 요구한다.
6. `worktrees`, `issue-<issue-number>`와 `checkout`은 symlink가 아닌 directory이고 실행 role 소유여야 한다. `worktrees`와 Issue directory는 mode `0700`, `state.json`은 mode `0600`이어야 하며 checkout과 그 상위 경로는 group 또는 world-writable이면 안 된다.
7. 기존 path가 malformed 상태면 삭제, chmod, chown, reset 또는 덮어쓰기로 자동 복구하지 않고 fail-closed한다. 권한 변경은 운영자가 exact path와 mode를 명시적으로 승인한 경우에만 수행하고 즉시 재검증한다.
3. 위 규칙으로 계산하고 검증한 `<harness-root>`만 trusted harness root로 사용한다. Exact path가 symlink가 아닌 directory이고 world-writable이 아닌지 확인한다. NFS mount root의 numeric owner가 실행 UID와 달라도 허용한다.
4. 기존 `repositories`는 `lstat`으로 검사해 symlink가 아닌 directory, 실행 role 소유이며 world-writable이 아님을 확인한다. Group-writable이면 directory의 numeric GID가 현재 system에서 해석되고, 해당 GID를 primary group으로 쓰는 계정과 group member 목록을 합친 effective member가 실행 role 하나뿐임을 확인해야 한다. Group identity나 전체 membership을 확인할 수 없거나 다른 계정이 포함되면 fail-closed한다.
5. 새 `repositories`를 만들 때는 실행 role 소유와 mode `0700`으로 생성한다. 기존 directory가 4번의 검증을 통과하면 mode `0700`, `0750`, `0755`, `0770` 또는 `0775`를 자동으로 chmod하지 않고 그대로 사용할 수 있다.
6. Trust boundary 아래 `.locks`, owner, repository와 `locks`는 생성 전후 `lstat`으로 검사한다. 모두 symlink가 아닌 directory, 실행 role 소유, mode `0700`이어야 한다.
7. Lock 파일과 임시 credential helper는 실행 role 소유와 mode `0600`을 요구한다.
8. `worktrees`, `issue-<issue-number>`와 `checkout`은 symlink가 아닌 directory이고 실행 role 소유여야 한다. `worktrees`와 Issue directory는 mode `0700`, `state.json`은 mode `0600`이어야 하며 checkout과 그 상위 runtime 경로는 group 또는 world-writable이면 안 된다.
9. 기존 path가 malformed 상태면 삭제, chmod, chown, reset 또는 덮어쓰기로 자동 복구하지 않고 fail-closed한다. 권한 변경은 운영자가 exact path와 mode를 명시적으로 승인한 경우에만 수행하고 즉시 재검증한다.
## Lock 규칙
@@ -60,7 +71,7 @@ Repository cache는 Gitea repository의 Git 객체와 refs를 재사용하기
## 신규 cache 초기화
1. Gitea MCP `get_me`로 허용된 role identity를 확인한다.
1. Authenticated Gitea API adapter로 허용된 role의 stable account identity를 확인한다. MCP면 `get_me`, 직접 REST면 `GET /api/v1/user`를 사용한다.
2. exact `owner/repository` metadata, clone URL, default branch와 branch SHA를 Gitea에서 읽는다.
3. bootstrap lock을 획득한 뒤 target을 다시 검사한다. 이미 유효한 cache가 있으면 새로 만들지 않고 기존 cache 검증 절차로 전환한다.
4. trusted parent 아래 같은 filesystem에 run-unique sibling staging directory를 mode `0700`으로 만든다.
@@ -121,7 +132,7 @@ Repository cache는 Gitea repository의 Git 객체와 refs를 재사용하기
Worktree를 신규 생성하거나 기존 worktree에서 구현을 재개하기 전에 다음을 모두 확인한다.
1. exact `owner`, `repository`와 Issue 번호가 검증됐고 Issue lock을 획득했다.
2. Gitea MCP로 authenticated role, exact repository metadata, Issue body, `updated_at`과 구현 승인 상태를 읽었다.
2. Authenticated Gitea API adapter로 role identity, exact repository metadata, Issue body, `updated_at`과 구현 승인 상태를 읽었다.
3. repository cache가 이 문서의 path, ownership, permission, bare, remote identity와 authoritative ref 검증을 통과했다.
4. 구현에 사용할 exact base SHA와 그 출처를 결정했다. Discovery pinned revision과 현재 default branch SHA가 다르면 어느 한쪽을 자동 선택하지 않고 변경을 조사해 요구사항과 충돌하지 않는 base를 확정하거나 중단한다.
5. `repository.git`에 exact base SHA의 commit object가 존재한다. 문자열 형식이나 object 존재만으로 Gitea 또는 승인된 Discovery에서 유래했다는 검증을 대체하지 않는다.
@@ -195,7 +206,7 @@ Dirty worktree, untracked 파일 또는 base 이후 commit은 진행 중 구현
- worker에게 credential 값 또는 credential-bearing URL을 전달하지 않는다.
- Git 인증이 필요하면 short-lived askpass 또는 동등한 child-process mechanism을 사용하고 종료 시 제거한다.
- inherited credential, 다른 role의 credential 또는 interactive prompt로 fallback하지 않는다.
- 인증에 실패하면 public clone이나 MCP content read를 initialized mirror의 증거로 대체하지 않고 중단한다.
- 인증에 실패하면 public clone이나 unauthenticated API·content read를 initialized mirror의 증거로 대체하지 않고 중단한다.
- Worktree source, state, Git config, reflog message, commit, patch, test artifact 또는 push refspec에 credential을 기록하지 않는다.
## Fail-closed 조건