harness: Issue 검증 증빙을 checkout 밖에 보관

This commit is contained in:
2026-10-08 01:06:16 +00:00
parent e7bcfef532
commit 6ae993887c
8 changed files with 590 additions and 56 deletions
+19 -2
View File
@@ -35,7 +35,9 @@ Repository cache 경로는 고정된 machine-local 절대경로나 현재 작업
└── worktrees/
└── issue-<issue-number>/
├── state.json
└── checkout/
├── checkout/
└── verification/
└── <run-id>/
```
- `.locks/<owner>/<repository>.bootstrap.lock`은 cache가 아직 없을 때도 사용할 수 있는 초기화 mutex다.
@@ -242,7 +244,7 @@ Dirty worktree, untracked 파일 또는 base 이후 commit은 진행 중 구현
정상 worktree 제거는 사용자가 exact worktree 폐기를 승인했거나, 승인된 delivery가 완료되어 remote branch SHA가 local HEAD와 일치함을 authoritative readback한 경우에만 수행한다. 제거 전 base SHA, final HEAD SHA, dirty·untracked 상태, 미전달 commit과 remote 보존 여부를 확인하고 보고한다. Dirty 상태, 미전달 commit 또는 판정 불가능한 파일이 있으면 `--force`, filesystem 재귀 삭제, reset 또는 clean으로 우회하지 않는다.
제거할 때는 broker Issue lease를 유지하고 같은 handle의 `acquire_repository` request로 repository lease를 중첩한 상태에서 worktree lock을 해제하고 Git operation으로 checkout과 registration을 먼저 제거한다. 두 대상의 부재를 확인한 뒤 exact `state.json`과 비어 있는 Issue worktree directory만 제거하며, 현재 run이 만든 state temporary file이 있으면 identity를 확인한 뒤 함께 제거한다. 다른 파일이나 하위 directory가 남아 있으면 재귀 삭제하지 않고 중단한다. 마지막으로 exact checkout, Git registration, `state.json`과 Issue worktree directory가 모두 없는지 다시 검증하고 `release_repository`를 request한다.
제거할 때는 broker Issue lease를 유지하고 같은 handle의 `acquire_repository` request로 repository lease를 중첩한 상태에서 worktree lock을 해제하고 Git operation으로 checkout과 registration을 먼저 제거한다. 제거 전에 아래 verification 계약에 따라 보존할 artifact의 identity, manifest·plan digest와 읽기 가능 여부를 확인한다. 두 대상의 부재를 확인한 뒤 exact `state.json`과 identity가 확인된 현재 run의 state temporary file만 제거한다. `verification/`이 남으면 Issue directory를 보존한다. 다른 알 수 없는 파일·directory가 남아 있으면 자동 정리하지 않고 partial로 보고한다. 비어 있는 Issue directory만 제거할 수 있다. 마지막으로 exact checkout, Git registration과 `state.json`의 부재 및 보존한 verification의 경로·digest가 제거 전과 같음을 다시 확인하고 `release_repository`를 request한다. Verification이 정상 보존돼 Issue directory가 남는 것은 checkout 제거 실패가 아니다.
## Credential 안전
@@ -301,3 +303,18 @@ Issue worktree workflow의 완료 보고에는 다음도 포함한다.
- partial 또는 fail-closed 상태
프로세스 exit와 clone/fetch 또는 worktree 명령의 성공 메시지만으로 완료를 주장하지 않는다. Cache workflow는 final cache path와 Gitea authoritative state를, Issue worktree workflow는 여기에 exact worktree registration, checkout, state와 Issue snapshot을 더해 모두 다시 읽은 경우에만 완료로 판정한다.
## Canonical external Issue verification artifacts
Issue별 검증 실행 기록의 정본은 `<harness-root>/repositories/<owner>/<repo>/worktrees/issue-<number>/verification/<run-id>`이다. `<harness-root>`는 실제로 읽은 `harness/operations/repository-cache.md`에서 결정한다. 제품 source는 형제 `checkout/`에 있고 verification은 제품 Git tree 밖에 있다. 구현·재작업의 회차별 plan, evidence manifest, command output, RED/GREEN 결과, finding matrix와 head별 provenance를 제품 `docs/verification/`에 새로 누적하거나 evidence-only commit을 만들지 않는다. 승인된 제품 요구사항이 명시적으로 요구하는 정본 문서와 지속적인 테스트·synthetic fixture·재현 스크립트는 제품에 유지할 수 있다. 기존 파일을 자동 이동·삭제하거나 광범위 `.gitignore` 변경으로 처리하지 않는다.
- 경로 identity는 인증된 exact owner, repository와 양의 Issue 번호에서 결정한다. 기존 cache identifier 규칙을 따르며 `issue-<number>`는 선행 0 없는 십진수다. `<run-id>`는 `[A-Za-z0-9][A-Za-z0-9_.-]{0,127}` 형식의 새 식별자다. Stage, source revision 또는 실행을 바꾸면 새 run-id를 사용한다. Dot segment, 절대 artifact file 경로, traversal, symlink와 임의 temporary/artifact root는 거부한다. `<owner>/<repo>`를 성공한 lookup 결과에 맞춰 자동 정규화하지 않는다.
- Caller가 인증된 Issue identity와 cache/worktree admission을 확인하고 **broker Issue lease** 아래 `verification/`과 새 run directory를 만든다. Directory는 실행 UID 소유 mode `0700`, plan·manifest·output 파일은 실행 UID 소유 mode `0600`으로 만들고 즉시 `lstat`으로 확인한다. 기존 cache bootstrap, repository lock과 lease 계약은 바꾸지 않는다. Artifact helper는 lease·Gitea identity·Git registration을 대신 인증하거나 directory를 만들고 cache/권한을 복구하지 않는다.
- `repo_root`는 canonical `checkout`, `artifact_root`는 exact `verification/<run-id>`로 분리한다. Plan의 `hash_paths`는 repository-relative source 경로이고 plan/output/manifest 인자는 run-relative artifact 경로다. 두 namespace는 이름이 같아도 서로 다른 파일이다. Source tree의 tracked·untracked·ignored 파일을 함께 검사하고 evidence 경로 exclusion을 허용하지 않는다. Python은 `-B` 또는 allowlist에 선언한 `PYTHONDONTWRITEBYTECODE=1`, pytest는 필요하면 `-p no:cacheprovider`로 checkout 안의 자동 cache 생성을 막는다. 테스트 임시 산출물·dependency environment도 checkout 밖 승인된 경로를 사용한다. Helper가 ignored cache를 자동 삭제하거나 clean 상태로 간주하지 않는다.
- 새 실행은 `evidence-manifest/v2`로 source full SHA, tracked source blob SHA·byte digest, owner/repository/Issue/run-id, plan path·digest, 실제 argv·exit code·환경·bounded output·시간과 claim pointer를 결합한다. Existing manifest는 no-clobber 원자 게시로 덮어쓰지 않는다. 완료 기록은 불변으로 취급하고 실패·재실행도 새 run-id에 보존한다. Helper의 `validate` 성공은 local artifact 정합성일 뿐 원격 PR head 또는 provider readback 검증을 대체하지 않는다.
- Baseline, integration, precommit과 remote-head 검증은 각 stage에서 검증한 **그 commit의 clean source**에 결합한다. Dirty 개발 tree는 보존하되 helper가 성공 증거로 게시하지 않는다. Final tracked 제품 산출물을 commit한 뒤 전달할 exact commit에서 검증하고, 실패하면 push하지 않는다. 모든 PR/결과 보고는 같은 immutable record의 command/result를 사용한다.
- Same-UID 배포에서는 인증된 reviewer가 producer 기록을 read-only로 읽는다. 다른 UID나 host에서는 승인된 credential-free read-only export/immutable artifact 전달 수단을 명시한다. 전달 receipt는 repository/Issue/run-id, source SHA, manifest·plan·output digest와 실제 읽기 검증을 묶는다. UID가 다르다고 chmod/chown하거나 임의 sibling path를 허용하지 않는다. 경로 문자열이나 구현자 요약만으로 reviewer-accessible이라고 판단하지 않으며, 접근/무결성/source binding 실패는 `evidence_gap`이다.
- Reviewer는 검증 source를 immutable provider/Git blob에 독립 결합한다. Producer manifest의 테스트 결과는 구현자 증거로 표시하고 reviewer 자체 실행으로 표현하지 않는다. Spec native-review snapshot/result와 운영 자료는 trusted `harness/.runtime`에 남겨도 되며 제품 실행 evidence와 혼동하지 않는다. Spec reviewer는 moving implementation checkout을 근거나 test 실행 장소로 재사용하지 않는다.
- Checkout 제거, broker release와 verification 폐기는 별개다. Checkout과 state를 제거해도 verification과 그 Issue directory는 보존한다. 보존 기간의 자동 만료나 재귀 삭제를 도입하지 않는다. Artifact 폐기는 별도의 exact 경로 승인, 활성 consumer·delivery/readback 의존성 조사와 digest 기록을 거쳐야 한다. 생성 실패의 미완성 run도 경로 identity가 입증된 현재 run 범위만 정리할 수 있고, 완료 기록은 자동 삭제하지 않는다.
- 인증정보를 사용했다는 사실은 남길 수 있지만 값·토큰·비밀번호·cookie·연결 문자열은 보존하지 않고 `[REDACTED]`로 기록한다. 새 증거를 만들기 위해 credential을 plan/argv/output에 넣지 않는다. Helper는 알려진 secret·header 유출을 fail-closed하고, 이것을 완전한 sandbox 또는 모든 비밀에 대한 자동 탐지로 과장하지 않는다.
- 기존 `evidence-manifest/v1`은 명시적 `validate-legacy --repo-root <historical-checkout> --manifest <repository-relative-manifest>`로 read-only 호환 확인만 한다. 새 `run`/`validate`에는 v1·repository-relative evidence 생성 fallback이 없다. Archived replay는 fresh source 실행·원격 head/readback 또는 새 publication 완료를 증명하지 않는다. Migration도 별도 승인 없이 기존 제품 evidence를 수정하지 않는다.