59 KiB
name, description, version, author, license, platforms, metadata
| name | description | version | author | license | platforms | metadata | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| gitea-issue-rework | Gitea PR 검토 지적을 계약에 맞춰 재작업하고 검증한다. | 0.2.17 | genichin, Hermes Agent | MIT |
|
|
Gitea Issue Rework
gitea-issue-implementation으로 전달한 기존 Gitea PR에 대해 gitea-spec-agent 또는 승인된 gitea-review-agent가 남긴 검토 결과를 exact reviewed head와 승인된 Issue 계약에 결합해 재작업한다. 유효한 지적만 source·문서·test·evidence에 반영하고 같은 Issue 전용 branch에 non-force push한 뒤, exact final head에 결합된 bounded PR comment로 재검토 handoff를 게시한다. 새 요구사항을 만들거나 명세를 구현에 맞춰 완화하지 않으며 merge, Issue 변경과 review 작성은 수행하지 않는다.
Gitea 인증과 authoritative readback은 Gitea authenticated access 운영 지침, cache·lock·worktree 규칙은 Repository cache 운영 지침, 문서 형식은 docs/ 아래 각 문서 유형의 README와 TEMPLATE만 정본으로 사용한다.
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 정본에 따라 확인하고, 통과한 ID/source가 이후 구조 guard 입력과 같은지도 대조한다. 불일치 증빙을 채택하거나 현재 collection을 baseline으로 재명명하지 않는다. PASS가 named test의 존재·collection 실행·의미 보존을 인증하지는 않으며 main의 실제 실행 provenance 검토와 기존 revision evidence 영향 평가를 유지한다. 이 gate는 제품 실행·별도 checkout 권한이나 자동 제품 변경 요청을 추가하지 않는다.
Delegation evidence acceptance gate
위임 결과 채택 이전에 harness/lib/delegation_evidence.py를 공통 증빙 채택 정본에 따라 실행한다. 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 정본의 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 이후 이 Issue 재작업도 canonical Repository cache 운영 지침의 공통 managed-lock broker 하나만 사용한다. serve에 canonical Issue identity, role, workflow run-id와 TTL을 전달해 broker-generated runtime을 만들고 ready JSON의 handle/socket 경로만 사용한다. 경로는 <issue>/runtime/<workflow-run-id>/broker.handle과 broker.sock이며 verification run-id와 독립적이다. Runtime 생성은 approval이나 worktree admission을 대신하지 않는다. Cache bootstrap 이후 broker가 Issue lock 아래 runtime을 준비하고, ready 이후 각 workflow의 진입 검증·승인 조건을 확인한다. 같은 handle로만 public request API의 acquire_repository/release_repository를 요청하고 TTL 전에 renew한다. Client는 raw token을 inspect/log하지 않으며 broker request API가 token을 캡슐화한다. 정상·오류·cancel cleanup은 보유한 repository lease release, Issue release, broker wait/reap, probe의 free=true 확인까지 동일하며 그 전에는 completed/log/report를 주장하지 않는다. Raw flock ... sleep, lock-file unlink와 client-side lock holder는 금지한다.
사용 시점
다음처럼 exact repository, source Issue, 기존 구현 PR과 재작업할 review를 식별할 수 있는 요청에 사용한다.
<owner>/<repository> Issue #<issue-number> 구현 PR #<pull-number>의 검토 지적을 재작업하라
이 요청은 아래 작업만 승인한다.
- 기존 canonical Issue worktree 검증과 재사용
- 승인된 계약 안에서 검토 지적을 해결하는 문서, source, test, 설정과 evidence 수정
- synthetic fixture와 test-only credential을 사용한 build, test, lint, 실제 runtime·browser 검증
- 기존 Issue 전용 branch 위의 non-amended commit 생성과 non-force push
- 현재 PR 본문의 기존 의미와
Closes #<issue-number>를 보존하면서 재작업 요약과 최종 검증 결과를 갱신하는 작업 - 이 스킬의 canonical 형식과 deduplication 계약을 만족하는 재작업 결과 PR comment 하나의 생성 또는 기존 exact comment 재사용
다음 작업은 별도 요청이 없으면 승인되지 않는다.
- 새 worktree나 대체 PR 생성, 다른 branch 또는 default branch로 push
- force-push, rebase, amend, reset, clean, stash 또는 history rewrite
- PR merge·close·reopen, native review·review reply·임의 comment 작성, reviewer 지정 또는 approval
- Source Issue
#<issue-number>의 body·comment collection·title·state·label·assignee·milestone 변경. Canonical PR comment는 exact Pull Request#<pull-number>의 top-level conversation에만 쓰며, provider가 이를 PR 자체의 underlying issue record#<pull-number>comment로 저장하는 projection은 허용한다. Source Issue record와 PR underlying issue record를 identifier·object kind·pull relation으로 구분할 수 없으면 게시하지 않는다. - 승인된 Discovery의 범위·결정·acceptance criterion 변경
- release, package 또는 deployment 게시
최초 구현, 독립 review, Discovery 변경 또는 이미 반영된 지적의 재검토에는 사용하지 않는다.
입력 승인 gate
초기 review decision gate는 references/input-gate.md의 public input-gate를 no_op 또는 source edit 전에 반드시 먼저 호출한다. 이 gate는 선택된 source review나 renderer expected.json을 입력으로 요구하지 않는다. Receipt의 rework ID를 읽은 뒤 finding은 수동으로 검증하며 automatic COMMENT classification은 지원하지 않는다. Gate의 no_op은 구현 재작업을 건너뛴다는 뜻일 뿐 native review publisher의 idempotent review reuse/no-op과 다르다. Native publication, journals, lease/worktree admission, full Discovery approval semantics와 pre-write freshness는 이 receipt로 증명되지 않으며 독립적으로 수행한다.
Repository file을 수정하기 전에 다음을 모두 검증한다.
owner,repository, Issue 번호와 PR 번호가 canonical identifier다.- Impl role의 authenticated stable account identity와 credential provenance를 확인했다.
- PR은 open이고 source Issue와 exact
Closes #<issue-number>하나로 결합되며 PR author의 stable account ID가 현재 authenticated impl role의 stable account ID와 exact-match하는 기존 구현 PR이다. - PR base는 target repository의 default branch이고 head repository·branch·40자리 full SHA를 식별할 수 있다.
- Current Issue body는 유효한
gitea-agent:discovery-draft/v2계약이고 미해결 질문이 없으며 body SHA-256을 계산할 수 있다. - 재작업 대상 native review의 ID, author stable account ID, state, body, reviewed commit SHA, stale·dismissed 여부와 inline comments를 complete pagination으로 읽었다.
- Review author가 허용된 spec 또는 code-review role이고 impl role과 다른 identity다.
REQUEST_CHANGES또는 명시적인 actionable finding이 있으며 각 finding의 계약 근거와 대상 경로를 판독할 수 있다.- Review가 참조한 contract digest가 있으면 current Issue body digest와 exact-match한다.
- Reviewed head가 current PR head와 exact-match한다. 다르면 current head에 결합된 더 최신 authoritative review를 사용하고, 없으면 이전 지적을 새 head에 임의 적용하지 않고 중단한다.
- Changed-file, review, review-comment와 commit pagination이 완전하고 diff가 truncated·ambiguous하지 않다.
- Canonical Issue worktree와 PR head branch를 현재 실행이 안전하게 재사용할 수 있다.
Canonical input-gate의 decision.rework_review_ids는 현재 head·계약에 결합된 role별 최신 REQUEST_CHANGES만 포함한다. Spec 또는 code-review role 중 하나 이상에 유효한 최신 수정 요청이 있고 다른 차단 사유가 없으면 rework다. 다른 role의 유효 review 부재는 missing_current_review로 기록하되 이 수정 요청의 재작업 착수를 차단하지 않는다. 수정 요청 없이 review가 부족하면 blocked이며 no-op으로 종료하지 않는다. rework에서도 finding의 계약 근거·scope·독립 승인과 lease/worktree 조건을 별도로 확인한 뒤에만 수정한다. COMMENT는 자동 actionable 판정을 하지 않고 blocked로 남겨 main의 수동 분류 또는 별도 승인 절차로 넘긴다. 특히 blocked_spec, 계약 모순, 선택되지 않은 설계 선택 또는 source reality와 계약 충돌은 구현 재작업으로 해결하지 않으며 Discovery 재검토가 필요하다고 보고한다. blocked receipt로 source를 수정하거나 no-op을 주장하지 않는다. Current head·계약의 spec와 code-review role별 최신 유효 review가 모두 APPROVED인 fresh no_op receipt에서만 write 없는 종료를 한다. 다른 role의 승인·old-head/stale/dismissed review·본문의 해결 주장은 이 조건을 대체하지 않는다.
Snapshot과 finding matrix
첫 write 전에 canonical collection의 test inventory와 영향을 받는 API·CLI·필드·상태·cleanup 의미를 snapshot/finding matrix에 연결하고 공통 workflow guard 계약을 적용한다. python3 <harness-root>/harness/lib/workflow_guard.py check-tests --input JSON과 check-contracts --input JSON을 결과 채택 전에 실행한다. RED/GREEN records must be named: 각 유효한 finding은 current test ID와 실제 실행 기록에 결합하며 환경/import 오류나 반증된 지적에 가짜 RED를 만들지 않는다. 읽기 전용 검토에는 위임 전 source snapshot과 채택 전 비교를 요구하고, 승인된 쓰기 worker의 편집에는 diff·의미 검토를 적용한다. 기록은 제품 checkout 밖 정본 verification run에 보존하며 helper schema·증거를 검증한다. gate failure는 운영 근거 무효이지 자동 제품 결함이 아니다.
첫 write 전에 다음 immutable snapshot을 보존한다.
- Issue title, body, state,
updated_at, labels, assignees, milestone, 전체 comments와 body SHA-256 - PR title, body, state,
updated_at, base·head repository와 branch, base·head SHA, author, changed files, commits, status, workflow run, PR top-level comment collection의 exact cardinality와 provider가 노출하는 comment-count field baseline - 전체 native review baseline과 대상 review의 ID, author, state, body digest, reviewed head, submitted time, stale·dismissed 상태와 inline comments
- Worktree state identity, base SHA, current HEAD, detached·locked 상태, staged·unstaged·untracked file과 미완료 Git operation
기존 canonical requirement revision을 갱신하거나 기존 계약 보존이 승인 조건이면 pinned source revision 또는 직전 승인 revision의 모든 requirement·acceptance criterion·상태 불변조건을 의미 단위로 추출해 다음 Contract Preservation Inventory를 같은 snapshot에 고정한다. ID 변경만으로 보존을 판정하지 않는다.
baseline_revision: <full SHA>
path: <repository-relative canonical requirement path>
baseline_id: <기존 requirement 또는 AC ID>
semantic_key: <ID와 독립적인 안정된 의미 식별자>
meaning: <정상·실패·경계·불변조건의 bounded 설명>
reviewed_ids: [<reviewed head의 대응 ID>...]
reviewed_status: preserved | intentionally_changed | missing | ambiguous
planned_ids: [<재작업 후 대응 ID>...]
planned_status: preserved | intentionally_changed | missing | ambiguous
authorization: Issue contract citation authorizing intentional change, or none
evidence_paths: [<source/test/document path>...]
verification: <test/static/runtime/browser evidence>
Baseline 항목은 중복 없이 정확히 한 번 나타나야 한다. intentionally_changed에는 승인된 Issue 근거가 필요하다. reviewed_status의 missing은 finding matrix에 포함하고 ambiguous는 계약 판단 불가로 중단한다. Repository 첫 write 전 계획 기준 planned_status가 missing=0, ambiguous=0이어야 한다. Contract Preservation Inventory를 delegate할 때는 immutable pre-write snapshot에 대해 완료·회수한 뒤에만 mutating worker를 시작하며, 편집과 병렬 실행해 중간 상태를 판정하지 않는다.
모든 finding을 다음 matrix의 정확히 한 항목으로 분류한다.
finding: <review-id>/<stable finding id>
reviewed_head: <full SHA>
contract: <Issue/requirement/acceptance criterion 근거>
classification: valid_fix | evidence_gap | reviewer_misunderstanding | blocked_spec
implementation_paths: [<repository-relative path>...]
test_paths: [<repository-relative path>...]
verification: <실행할 command/runtime/browser evidence>
result: pending | resolved | unresolved
reason: <bounded 판정 근거>
valid_fix: 승인 계약을 위반한 source·문서·설정·test 결함이다.evidence_gap: 구현 적합성은 확인 가능하지만 exact-head-bound 실행·runtime·browser·CI evidence가 부족하다.reviewer_misunderstanding: 지적이 승인 계약 밖의 새 요구사항이거나 authoritative tree와 맞지 않는다. 이를 만족시키려고 범위를 확장하지 않고 근거와 함께 unresolved로 보고한다.blocked_spec: 명세 모순이나 새 결정이 필요하다. 모든 repository write를 중단한다.
완료 조건: 모든 review finding과 unsatisfied·indeterminate criterion이 matrix에 정확히 한 번 나타나고, valid_fix와 evidence_gap마다 변경 또는 검증 경로가 있으며, 이미 satisfied인 계약을 약화하는 항목이 없다. Contract Preservation Inventory가 필요한 경우 baseline 전체가 대응되고 missing=0, ambiguous=0이다.
Canonical 재작업 결과 comment
재작업 branch를 전달한 뒤 reviewer가 새 head를 자동으로 재검토할 수 있도록 exact PR의 top-level conversation에 comment 하나를 게시한다. Adapter target은 object kind가 pull request이고 index가 exact <pull-number>인 record여야 한다. Provider가 PR comment를 underlying issue comment로 저장하면 exact comment endpoint target의 issue index가 <pull-number>이고 fresh PR metadata가 그 record를 같은 pull request로 식별함을 증명해야 한다. Comment object가 target kind를 반복하지 않는 API에서는 검증된 endpoint target과 PR metadata binding을 사용한다. Source Issue <issue-number>, inline comment, review reply 또는 native review로 대체하지 않는다. Marker를 제외한 body를 먼저 canonical UTF-8/LF bytes로 직렬화하고 그 SHA-256을 result-sha256으로 계산한다.
Canonical body와 marker는 scripts/rework_comment.py render로만 생성하고, 게시 또는 exact comment 재사용 뒤에는 authoritative normalized readback을 scripts/rework_comment.py verify로 검증한다. status=verified와 readback_verified=true인 gitea-rework-handoff/v1 receipt가 없으면 완료 조건을 충족하지 않으며 PR body update나 write 성공 response는 receipt를 대체하지 않는다.
## 구현 재작업 결과
- Source Issue: <issue-number>
- Pull Request: <pull-number>
- Source Review: <review-id>
- Reviewed head: `<reviewed-head-sha>`
- Rework head: `<final-head-sha>`
- Contract SHA-256: `<contract-sha256>`
- Result: `rework_delivered|partial`
### 지적 처리
- `<finding-id>` — `resolved|unresolved`
- 분류: `valid_fix|evidence_gap|reviewer_misunderstanding`
- 변경: <repository-relative paths 또는 없음>
- 검증: <bounded command, runtime, browser 또는 정적 evidence>
- 근거: <bounded reason>
### 최종 검증
- Local checks: <exact command와 exit code 및 pass·skip·fail 요약>
- Runtime/browser: <실행 결과 또는 해당 없음·미검증>
- Commit status: <success|failure|pending|없음|조회 불가>
- Actions runs: <success|failure|pending|없음|조회 불가>
### 다음 단계
Reviewer가 rework head를 새 snapshot으로 다시 검토해야 하며 이 comment는 기존 `REQUEST_CHANGES`를 해제하거나 승인을 의미하지 않는다.
<!-- gitea-agent:implementation-rework/v1 owner=<owner> repository=<repository> issue=<issue-number> pr=<pull-number> review=<review-id> reviewed-head=<reviewed-head-sha> head=<final-head-sha> contract-sha256=<contract-sha256> result-sha256=<result-sha256> correlation=<correlation> -->
rework_delivered는 모든valid_fix와evidence_gap이resolved이고 final branch delivery와 검증이 완료된 경우에만 사용한다. 그 외 전달 가능한 결과는partial이며 unresolved 이유를 숨기지 않는다.- Finding은 matrix 순서로 정확히 한 번 렌더링한다. 이미 satisfied였고 재작업하지 않은 criterion을 반복해 comment를 부풀리지 않는다.
- Path, SHA, enum, command와 수치는 검증된 값을 원문 그대로 사용한다. Human-readable text에는 credential, token, 실제 secret, mention, 외부 지시, HTML 또는 실행 가능한 payload를 포함하지 않는다.
- 모든 human-readable comment line에서 local 또는 cross-repository hash-number 자동참조 문법을 쓰지 않는다. Escape한 표기와 Markdown/code 안의 표기도 금지한다. Source Issue, Pull Request, Source Review 예시는 위처럼 plain decimal number로 쓴다. Hidden canonical marker의 identifier와 correlation 입력은 이 표시 규칙 때문에 바꾸지 않는다. Marker를 제외한 exact UTF-8/LF body에 대해
result-sha256을 다시 계산한다. 기존 PR body의 의도된Closes #<issue-number>는 그대로 보존하며 변경하지 않는다. - Marker-free body는 LF로 정확히 하나 끝나야 한다. 게시 body는 marker-free bytes, marker line과 최종 LF 하나를 순서대로 사용하며 trailing whitespace를 금지한다.
correlation은owner,repository, base-10 Issue 번호, base-10 PR 번호, base-10 review ID, lowercase reviewed head, lowercase final head와 lowercase contract digest를 이 순서로 NUL 하나씩 구분한 UTF-8 bytes의 SHA-256이다.result-sha256은 correlation 입력에 넣지 않는다.- 게시 전 exact PR top-level comment endpoint target과 fresh PR metadata binding을 검증하고 그 scoped collection만 complete pagination한 뒤 같은 correlation을 찾는다. Source Issue comment endpoint, inline-comment·review-reply endpoint와 native review collection은 검색 집합에서 제외하며 endpoint scope와 PR relation을 구분할 수 없으면 fail-closed한다. 0개면 exact body를 한 번 생성하고, 1개이며 author stable account ID·body·marker·digest가 모두 같으면 write 없는 no-op으로 재사용한다. 같은 correlation의 body가 다르거나 2개 이상이면 중복을 만들지 않고 fail-closed한다.
- Comment create timeout·오류 뒤에는 blind retry하지 않는다. Complete comment collection을 한 번 authoritative하게 reconcile해 exact result 하나가 확인될 때만 성공으로 판정한다.
- 게시 또는 재사용 후 exact comment ID, author stable account ID, body, created·updated timestamp, marker, digest, verified endpoint target, fresh PR metadata binding과 PR top-level collection cardinality를 readback한다. 신규 게시에서는 scoped PR top-level comment collection에 exact comment 하나만 추가되어야 한다. Provider의 aggregate comment-count field는 명시된 version-specific 계약으로 설명 가능해야 하며 설명할 수 없으면 fail-closed한다.
gitea-conversation-v1cache opt-in은 cached conversation admission에 따라 snapshot의 bounded stale lag만 허용하고, 신규 게시 후에는 실제 전체 conversation 개수와 exact-match를 요구한다. Cached baseline에 무조건+1을 적용하지 않으며 reuse의 counter·metadata 불변 조건은 유지한다. 신규 게시에서 PR·underlying PR-Issue의updated_at은 불변이거나 exact 신규 comment 생성 timestamp와 같을 때만 허용한다. 이는 다른 native metadata가 불변인 상태의 state-delta/exact-timestamp admission이며, GET readback만으로 독립적인 causal event attestation을 제공하지 않는다. Source Issue<issue-number>는updated_at을 포함한 전체 native metadata와 comment collection이 완전히 불변이어야 하며, provider relation을 이유로 timestamp 예외를 허용하지 않는다. Existing exact comment 재사용에서는 PR top-level collection cardinality, PR·underlying issue와 Source Issue field가 모두 불변이어야 한다. 기존 review collection 또는 그 밖의 PR field 변경은 허용하지 않는다.
완료 조건: exact final head와 finding matrix에 결합된 canonical comment가 impl role author로 정확히 하나 존재하고 authoritative readback을 통과한다.
정본 provider readback 실행
references/readback.md의 canonicalscripts/rework_comment.py snapshot으로 게시 전 baseline을 수집하고 producer의 SHA-256을 독립 보존한다. Impl role의 private credential, stable account ID와 reviewed provider-contract fingerprint를 고정한다.- 승인된 단일 게시 또는 existing-comment 재사용 뒤에는
scripts/rework_comment.py verify-live를terminal로 실행한다. Source Issue·PR·underlying PR-Issue·scoped top-level comments·reviews·inline evidence를 fresh GET으로 다시 수집하고 계산된 불변성·cardinality 결과를 기존 verifier에 직접 연결한다. - 정본 출력은 caller가 admission한 Issue runtime의
rework-baseline.json과rework-receipt.json이다. Product checkout 밖에서 baseline은 보존하고 receipt는 성공 검증 시에만 update-in-place한다. 실패 때문에 baseline 재수집이나 POST 재시도를 하지 않는다. - Provider version과 aggregate semantics는 명시된 trusted contract에서만 채택한다. Count-header 없는 empty-array와 capability-bound count fallback은 구분하며, 권한 오류·redirect·불완전 pagination은 fallback 사유가 아니다. Counts-only inline fallback을 complete inline-body inventory로 보고하지 않는다.
- 기존 offline
verify는 호환 경로다. 수동 JSON의 success flag나 archived replay만으로 fresh provider readback 또는 외부 게시 완료를 주장하지 않는다.
절차
Evidence manifest automation
모든 baseline, 통합·precommit 및 readback 검증은 scripts/evidence_manifest.py와 templates/evidence-plan.json을 사용해 exact argv, exit code, 제한된 output, 허용된 환경, source revision, 파일 hash와 표준 JSON-pointer claims를 기록한다. 명령은 argv 배열만 허용하고 명시된 최소 child-environment allowlist에서 실행하며 output 상한을 넘는 process는 중단한다. Secret·header·private-key·password 값이나 plan 금지 패턴이 발견되면 redaction하지 않고 fail-closed한다. run은 baseline부터 최종 precommit까지 사용하고, validate는 제품 tree의 evidence exclusion 없이 strict clean checkout에서 PR claim 생성 전에 실행한다. 새 기록은 external verification root의 v2이며 exact current HEAD와 source blob·hash를 다시 검증한다. 과거 evidence-only descendant는 명시적 archived v1 read-only 호환 경로에 한정한다. 수동으로 매칭되지 않는 PR 성공·검증 주장을 만들지 않는다. Comment publish 전 remote immutable artifact의 digest를 authoritative readback으로 비교한다.
Conditional pytest evidence recipe
pytest를 이미 사용하는 프로젝트의 evidence command에만 적용한다. unittest 예시나 제품의 pytest 설정을 일괄 변경하지 않고, 승인된 interpreter·pytest 버전·plugin 및 기존 test target을 사용한다. 아래 JSON argv의 {python}과 {tests}를 exact interpreter와 승인 target으로 치환한다. 여러 target은 각각 argv 원소로 명시하고 shell 문자열로 합치지 않는다.
["{python}", "-B", "-m", "pytest", "-o", "addopts=", "--color=no", "-rA", "{tests}"]
- 이 recipe는 command-local
addopts=로 프로젝트의 quiet 누적 옵션을 해제하여 최종 summary를 보존하는 예시다. 기본적으로PYTEST_ADDOPTS는 기존 child-environment allowlist에 없으며 전달하지 않는다. Quiet 자체가 항상 summary를 누락시키는 원인이라고 단정하지 않는다. 프로젝트addopts의 필수 실행·plugin 옵션은 사전에 확인하여 필요한 옵션을 승인된 argv에 명시적으로 옮긴다. 필수 semantics를 보존할 수 없으면 recipe를 그대로 적용하지 않고evidence_gap으로 남긴다. Warning 필터·skip 조건·선택 대상·제품 config 파일은 변경하지 않는다. - 실제 승인 환경에서 먼저 최종 passed/skipped/failed 및 warning 요약의 보존 여부를 확인한다. pytest가 생략하는 zero category를 출력된 수치처럼 보고하거나 임의로 0으로 채우지 않는다. 이전 실행의 수치나 progress 문자 개수로 이번 실행 합계를 보충하지 않는다. Recipe만으로 모든 pytest 버전·plugin의 output 보존을 보장하지 않는다.
- 기존 evidence plan의 finite
timeout_seconds,max_output_bytes, expected exit code와 process cleanup을 유지하고 exact argv·환경·source SHA·현재 실행 output을 기록한다.timeout·output_limit·불완전 summary이면 수치 claim은evidence_gap이다. 명령이 완료되고 exit 0인 사실과 정확한 수치 보고의 증거는 구분한다. 승인 없이 재실행하거나 output 한도를 늘리지 않는다. - 별도의 parser, runner, manifest schema 또는 pytest 설치 의무를 추가하지 않는다. Synthetic regression은 격리된 pytest interpreter에서 실제 pass/skip/warning과 failure 출력 및 기존 bounded reader의 보존을 검증한다. Pytest가 없는 test interpreter에서는 실행 회귀가 명시적으로 skip되므로 문서 계약 테스트만 통과한 결과를 실제 pytest 검증으로 보고하지 않는다. Synthetic test의 plugin autoload 차단은 fixture 격리용이며 제품 실행 정책이 아니다.
1. Target, identity와 review 고정
- Exact target identifier를 검증하고 broker
serve의 ready 응답과 publicrequestAPI로 Issue lease를 확인한다. - Canonical authenticated Gitea adapter로 impl role identity, repository, Issue, PR, commits, changed files, statuses, workflow runs, 전체 reviews와 review comments를 읽는다.
- 입력 승인 gate를 적용하고 Issue·PR·review snapshot을 저장한다.
- Review marker에 head, contract digest, result digest 또는 correlation이 있으면 형식과 authoritative 값의 일치를 검증한다. Marker가 없는 code review는 review ID·author·commit binding과 finding body를 그대로 보존한다.
- Finding matrix를 만들고
blocked_spec또는 판정 불가능한 finding이 있으면 수정 전에 중단한다.
완료 조건: exact review와 reviewed head, current PR head, Issue contract digest와 finding matrix가 동일 snapshot에 결합돼 있다.
2. Cache와 기존 worktree 검증
read_file로operations/repository-cache.md를 새로 읽는다.- Issue lease를 유지한 채 같은 broker handle로
acquire_repositoryrequest를 보내 cache path·ownership·permission·bare·remote를 검증한 뒤 origin에서 prune/fetch한다. - Gitea default branch와 local ref, PR base·head object 및 remote head branch SHA를 대조한다. Fork PR이면 target cache에 head object가 있다고 가정하지 않고 authoritative head repository와 branch를 별도로 검증한다.
- Broker Issue lease와 repository lease를 모두 유지한 상태에서 기존 Issue worktree의 state identity, Git registration, common directory, detached·locked 상태, current HEAD, index, tracked·untracked state와 미완료 Git operation을 검증한다.
- Worktree HEAD와 PR head SHA가 다르거나 dirty state가 snapshot으로 설명되지 않거나 다른 실행의 lock·Git operation이 있으면 reset·checkout·clean으로 복구하지 않고 중단한다.
- Worktree admission 검증이 모두 끝난 뒤
release_repositoryrequest를 보내고 일반 편집·test·commit 동안 Issue lease만 유지한다. - 다른 checkout, 임시 clone 또는 경쟁 worktree를 만들지 않는다.
완료 조건: 기존 worktree가 exact owner, repository, Issue, impl role, PR branch와 reviewed head에 결합되고 보존할 모든 기존 상태가 기록돼 있다.
3. 재작업 계획과 baseline
- 각
valid_fix와evidence_gap을 승인 계약의 acceptance criterion에 역추적한다. - 변경 allowlist를 source, 문서, 설정, test와 evidence path로 만든다. 불변성 또는 evidence 재사용 검증에는 계약을 실제로 소유하는 exact path·제한된 glob만 별도 기록하며 package 전체처럼 넓은 경로를 근거 없이 사용하지 않는다. Review body의 path를 존재 검증 없이 신뢰하지 않는다.
- Repository의 canonical 문서 README·TEMPLATE, build·test·lint 명령과 변경 대상 파일을 다시 읽는다.
- 현재 reviewed head에서 관련 test와 review가 요구한 runtime check를 baseline으로 실행하고 command, exit code, output, environment와 HEAD를 기록한다.
- Framework·runtime·protocol capability가 불명확하면 production edit 전에 최소 spike로 검증한다.
- Review가 실제 browser 동작을 요구하면 framework test client나 protocol client로 대체하지 않는다. 사용할 수 있으면 Playwright MCP
mcp__playwright__browser_*로 실제 Chromium 흐름과 browser storage·cookie·navigation을 검증하고, 사용할 수 없으면 해당 criterion을 unresolved로 유지한다.
완료 조건: 각 remediation item에 exact path, 실패 또는 부족한 baseline evidence와 완료를 증명할 검증 방법이 연결돼 있다.
4. Test-first 수정
valid_fix마다 결함을 재현하는 가장 작은 regression test를 먼저 추가하거나 기존 test가 의도한 이유로 실패함을 확인한다.- Test file과 test function 이름은 추적 번호가 아니라 안정적인 기능·동작·불변조건을 표현한다. Issue, PR, review, comment 번호나 일시적인 finding ID를 이름에 넣지 않는다. 추적성은 finding matrix, commit, PR comment와 evidence metadata에 기록한다. 기존에 이미 존재하는 번호 기반 이름은 해당 재작업에서 별도 rename 범위를 승인받지 않았다면 유지한다.
- 동시성·event-loop finding은 wall-clock 의존을 최소화한 deterministic unit test와 실제 delay를 활성화한 짧은 runtime probe를 모두 실행해, 지연 semantics 유지와 무관한 coroutine·health 요청의 응답성을 각각 검증한다.
- Streaming request-body 상한 finding은
Content-Length를 신뢰하지 않고 실제 streamed bytes로 exact limit 허용, limit+1 거부, 누락·부정확한Content-Length, 초과 뒤receive미호출을 검증한다. Upstream이 이미 전달한 단일 대형 chunk의 allocation은 애플리케이션이 막을 수 없다는 잔여 경계를 기록한다.
- Source를 최소 변경해 test를 통과시키고 이미 satisfied인 criterion과 제외 범위를 보존한다.
evidence_gap은 production code를 불필요하게 바꾸지 않고 누락된 unit, integration, runtime, browser 또는 provenance evidence를 보강한다.- 보안 finding은 정상 경로뿐 아니라 fail-closed, no-call·no-write, 경계 시간, rotation 양방향, fresh session, logout 후 재접속과 credential 비노출을 해당 계약 범위에서 검증한다.
- 문서 finding은 기존 canonical requirement ID와 revision history를 유지하고 요구사항, interface, project structure, runtime flow, deployment와 test를 일관되게 갱신한다. Review를 맞추기 위해 별도 요구사항 ID를 만들지 않는다.
- 실제 credential, 운영 데이터 또는 민감 token을 fixture, evidence, log, screenshot, URL이나 repository file에 기록하지 않는다.
- 각 item을 수정할 때 focused test를 실행하고 matrix의
result와 evidence를 갱신한다.
완료 조건: 모든 valid_fix가 재현 test와 수정 후 통과 evidence를 가지며, evidence_gap은 요구된 실제 검증 수준으로 채워졌거나 unresolved 이유가 명시돼 있다.
5. 통합 검증과 독립 검토
- Repository가 선언한 formatter, lint, type check, build, targeted, integration과 relevant full suite를 실행한다.
- Runtime·protocol·browser criterion은 가능한 가장 실제에 가까운 경로로 실행한다. 하위 수준 대체 evidence를 동등하다고 주장하지 않는다. 재작업 diff가 문서 파일에만 한정되고 기존 browser evidence가 결합된 source, test와 evidence path가 reviewed head부터 final head까지 byte-identical이며 ancestry를 검증한 경우에만 browser를 다시 실행하지 않고 기존 evidence를 재사용할 수 있다. 이때 비교한 exact path 집합과 양 head의 blob OID 또는 digest를 검증 기록과 결과 comment에 남긴다. 변경 경로가 겹치거나 동일성을 증명할 수 없으면 재사용하지 않는다.
- Base-to-worktree와 reviewed-head-to-worktree diff를 모두 읽고 모든 changed file을 finding matrix와 acceptance matrix에 대응한다.
- 범위 밖 refactor, debug artifact, generated drift, credential, 운영 데이터, test-only bypass와 예상하지 못한 삭제를 제거한다.
- 독립 검토를 요청하기 전에 모든 actionable finding을 하나의 통합 adversarial suite로 실행한다. 각 finding은 실제 public response shape와 모든 직접 소비 경로를 포함해야 한다. 최소 검증 항목은 최초 실행과 idempotent replay의 응답 동등성, top-level/nested 필드 일치, 재귀적 민감정보 redaction, missing/initialized DB의 no-write, public positional signature, 동시성 및 실패 envelope다. 이 suite가 통과하지 않으면 독립 검토를 시작하지 않는다. 독립 검토는 새 결함을 처음 찾는 단계가 아니라 exact tree의 확인 단계다.
- Security-sensitive 변경은
delegate_task로 bounded reviewer에게 exact worktree, reviewed head, contract subset, finding matrix와 file allowlist를 제공해 독립 검토한다. Gitea write, Git cleanup, commit과 push는 금지한다. - Delegate finding을 main agent가 직접 재현하고 유효한 문제만 수정한 뒤 영향을 받은 focused test와 relevant full suite를 다시 실행한다.
완료 조건: 모든 modified file이 approved finding 또는 필수 supporting change로 설명되고 unresolved finding과 검증 한계가 분리돼 있다.
6. Drift 확인과 commit
- Issue, comments, PR, commits, changed files, branch SHA와 전체 reviews를 다시 읽는다.
- Issue body digest·
updated_at, PR base·head, 대상 review binding, review baseline 또는 default branch가 snapshot에서 material하게 drift하면 새 상태를 자동 채택하지 않고 중단한다. - Worktree의 staged·unstaged·untracked state와 미완료 Git operation을 확인한다.
- Contract Preservation Inventory가 필요한 경우 final tree에 다시 대응해 baseline 항목 수와 실제 상태를 검증하고
missing=0,ambiguous=0이 아니면 stage하거나 commit하지 않는다. - Exact allowlist만 stage하고 staged diff를 다시 읽는다.
- Commit 전에 subject와 body를 공통 commit-message reference safety 규칙에 따라 확인한다. Protected Issue metadata가 immutable이어야 하면 hash-number auto-reference와 parser-triggering closing/reopening 문구를 피하고
Issue 18 / PR 19 / review 76또는 evidence로 추적한다. 기본은 새 non-amended commit이며, amend는 명시적 사용자 승인·미게시 증명·tree 동일성 증명과 새 SHA exact verification이 모두 있을 때만 허용된다. 일반 amend 권한으로 해석하지 않는다. - Commit 후 clean HEAD에서 최종 formatter, test와 필요한 runtime·browser 검증을 다시 실행한다. 이 뒤 repository file을 바꾸면 영향을 받은 검증을 다시 실행한다.
- 최종 검증 기록은 exact HEAD 또는 검증한 source tree, command, exit code, pass·skip·fail 수치, 환경, relevant output과 reviewer가 접근 가능한 evidence location을 포함하며, PR body·결과 comment의 각 실행 주장과 수치는 해당 location에 일대일 대응시킨다. Hermes 내부 tool transcript, delegate 자기보고, 삭제 예정 임시 파일, reviewer가 접근할 수 없는 local path와 요약 수치만 있는 기록은 evidence로 인정하지 않고
evidence_gap또는partial로 유지한다. 새 evidence는 checkout 밖 정본 verification root에 보존하여 final HEAD를 기록하며 evidence-only descendant를 만들지 않는다. 과거 tracked evidence의 archived 분석은 fresh 실행·원격 head 검증과 구분한다.
완료 조건: final local HEAD, clean state, finding별 해결 evidence와 단일 검증 기록이 일치하며, 필요한 Contract Preservation Inventory는 missing=0, ambiguous=0이다.
7. 기존 PR branch 전달
- Write 직전에 remote branch와 PR head가 snapshot의 reviewed head와 여전히 exact-match하는지 확인한다.
- 첫 delivery push 전에 승인된 noninteractive credential capability를 preflight하고 공통 non-file Git credential helper를 role-owned short-lived child process에서 사용한다. Credential은 Git의 private protocol pipe로만 공급하고 출력·파일·config에 저장하지 않으며 interactive/다른 helper fallback을 비활성화한다. 성공·실패와 무관하게 child process를 wait/reap하여 credential 환경의 종료를 확인한다. 그 후 canonical mirror remote를 변경하지 않고 explicit repository URL과 refspec으로 기존 Issue 전용 branch에 fast-forward non-force push한다. Named mirror remote를 사용해야 하면
operations/repository-cache.md에 따라 해당 push 호출에서만remote.<name>.mirror=false를 적용한다. - Push 결과만 신뢰하지 않고 remote branch SHA와 PR head SHA가 final local HEAD와 exact-match하는지 readback한다.
- PR body 갱신이 필요한 경우 write 직전에 PR 전체 필드, review·comment·commit collection cardinality와 authenticated impl identity를 다시 읽는다. Current body의
Closes #<issue-number>와 기존 구현 내용을 보존하고 재작업 review ID·reviewed head·finding별 조치·최종 검증과 unresolved limitation만 반영한 exact body payload를 명시해 한 번만 호출한다. 성공 응답만 신뢰하지 않고 fresh PR과 관련 collection을 읽어 PR author stable account ID, exact body payload,updated_at, base·head·commit/ref, state·draft·merge 상태, labels·assignees·reviewer와 collection cardinality를 baseline과 비교한다. Exact body와 provider가 해당 body update로 파생한updated_at외의 변경은 승인되지 않았으며 인과를 증명할 수 없으면 partial로 중단한다. - PR changed files, commits, state, merge 상태, statuses와 workflow runs를 다시 읽는다. Local test, commit status와 Actions run을 별도 사실로 기록한다.
- Finding matrix와 최종 검증 기록을 bounded JSON input으로 만들고
scripts/rework_comment.py render --input <input.json> --comment <comment.md> --expected <expected.json> --delegation-adoption <absolute-main-declaration.json>를 실행해 canonical 재작업 결과 comment, marker-free digest와 correlation을 생성·검증한다. Comment body와 marker를 수동 조립하지 않는다. - Exact PR top-level comment endpoint target과 fresh PR metadata binding을 검증해 Source Issue comments, inline comments, review replies와 native reviews에서 분리하고 scoped collection을 complete pagination한 뒤 canonical deduplication 규칙을 적용한다. Existing exact comment가 없으면 exact PR conversation에 body를 한 번 게시하고, 있으면 write 없이 재사용한다.
- Exact comment와 scoped complete collection을 fresh normalized JSON으로 readback한 뒤
scripts/rework_comment.py verify --expected <expected.json> --pr-readback <pr.json> --comments-readback <comments.json> --identity-readback <identity.json> --action <create|reuse> --baseline-count <N> --output <handoff-receipt.json>를 실행한다. Receipt의 comment ID, impl author stable account ID, body, timestamp, final head, digest, correlation과 cardinality가 검증돼야 하며, 신규 게시로 허용된 PR-underlying-issue projection 외의 PR field, Source Issue field와 기존 review collection에 변경이 없어야 한다. - Native review를 작성·dismiss·reply하거나 새 review를 요청하지 않는다. 기존
REQUEST_CHANGES는 reviewer가 새 head를 재검토하기 전까지 자동 해소된 것으로 주장하지 않는다. - Push, PR body 또는 comment write가 timeout·오류이면 blind retry하지 않고 branch, PR과 complete comment collection을 authoritative하게 reconcile한다. Exact write가 반영됐음을 증명할 수 없으면 partial 상태로 중단한다.
완료 조건: 같은 PR의 remote head가 final local HEAD와 일치하고 canonical 재작업 결과 comment가 정확히 하나 readback됐으며, gitea-rework-handoff/v1 receipt가 status=verified, readback_verified=true로 생성되고 모든 authorized external write와 후속 review 필요성이 명확하다. Receipt가 없거나 검증에 실패하면 lock은 정상 해제하되 결과를 partial|failed로 보고하며 completed를 주장하지 않는다.
8. 종료와 다음 review handoff
- 임시 검증 자원을 정리하기 전에 relevant output을 redaction하고 exact HEAD·command·exit code·환경과 결합해 reviewer-accessible evidence location에 저장한 뒤 그 내용을 readback한다. 그 후 임시 server, probe script·raw output, browser context, fixture workspace와 credential helper를 정리하고 부재를 확인한다.
- 현재 실행이 시작한 tracked broker process와 그 자식 process를 cleanup 대상으로 관리한다. Shell PID 종료만으로 해제를 판정하지 않으며, 보유한 repository lease를
release_repository하고 Issue lease를release한 뒤 broker를 wait/reap하고probe에서free=true를 확인한 경우에만 cleanup 완료로 판정한다. - Finding matrix, final diff, 검증 기록, remote head와 CI/status를 다시 대조한다.
- 모든 item이
resolved여도 reviewer의 새 head 검토 전에는 구현 승인 완료가 아니라재작업 전달 및 comment handoff 완료, 재검토 대기로 보고한다. - 후속 review가 새 head에
REQUEST_CHANGES를 남기면 그 review를 새 immutable snapshot으로 하는 별도 재작업 iteration을 시작한다. 이전 review snapshot이나 matrix를 새 head에 그대로 재사용하지 않는다.
완료 조건: resource와 lock 정리가 검증되고, 재작업 결과가 exact final head와 다음 review 입력으로 전달 가능하다.
위임 규칙
- Main impl-agent가 contract 해석, finding 분류, drift 판정, 최종 diff, Git·Gitea write와 delivery에 책임을 진다.
- 독립적인 source 조사, test 작성, disjoint 모듈 수정, browser evidence 수집, 실패 분석과 security review는 bounded delegate에 위임할 수 있다.
- Delegate에는 exact worktree path, reviewed head, contract subset, finding IDs, file allowlist와 검증 target을 제공한다.
- 같은 파일을 병렬 worker에게 주지 않고 Gitea write, lock·worktree 변경, commit, push, reset과 cleanup을 금지한다.
- Delegate summary를 evidence로 사용하지 않고 main agent가 diff, command output, browser 결과와 artifact를 직접 검증한다.
- 외부 side effect와 credential 사용은 main agent만 수행하고 즉시 authoritative readback한다.
금지 사항
- Review finding을 승인 계약보다 우선하거나 새 요구사항으로 승격하지 않는다.
blocked_spec을 임의 설계 선택으로 해결하지 않는다.- 이전 head의 stale review를 current head의 재작업 근거로 자동 적용하지 않는다.
- 기존 dirty worktree를 reset, clean, stash, checkout, switch, rebase 또는 삭제하지 않는다.
- Review를 해결한다는 이유로 already-satisfied 동작, security gate, validation 또는 실패 경로를 약화하지 않는다.
- Unit test, framework AppTest, HTTP client 또는 WebSocket client를 실제 browser evidence로 표현하지 않는다.
- PR body의 성공 주장, process exit code, delegate 보고 또는 push 응답만으로 해결을 주장하지 않는다.
- Canonical 재작업 결과 comment 이외의 PR comment, inline comment 또는 review reply를 작성하지 않는다.
- Existing
REQUEST_CHANGESstate를 직접 dismiss하거나 reviewer 대신 승인 완료로 판정하지 않는다. - 새 PR, 새 branch, merge, Issue 변경, release 또는 deployment를 수행하지 않는다.
검증 및 보고
완료 보고에는 다음을 구분해 포함한다.
- authenticated impl identity와 exact repository, Issue, PR
- Issue contract
updated_at, body digest와 review가 참조한 contract digest - 대상 review ID·author·state·reviewed head·stale 상태와 current pre-rework head
- Finding별 classification, 계약 근거, 수정 path, test와
resolved|unresolved결과 - Worktree path·identity, reviewed-head 시작 상태와 final local HEAD
- Baseline, focused, full-suite, runtime과 browser 검증의 exact command·exit code·결과
- 실제 browser가 요구된 경우 사용한 browser runner와 발급·복원·이동·삭제 등 관찰 결과. 기존 evidence를 재사용했다면 비교한 exact path 집합과 reviewed/final head의 blob OID 또는 digest
- Base 및 reviewed head 대비 전체 modified file과 범위 근거
- Local commit, remote branch와 PR final head SHA readback
- PR body write 여부, status와 Actions run의 success·failure·pending·없음 상태
- 재작업 결과 comment ID·URL·author·result·digest·correlation, exact final head binding과 verified handoff receipt
- 기존 review가 유지됨과 새 head의 후속 review 필요 여부
- 수행하지 않은 review·merge·Issue·release·deployment write
- Baseline failure, unresolved finding, specification blocker, unavailable evidence와 partial write
- 임시 resource 정리와 lock 해제 확인
모든 finding이 해결되고 검증된 final commit과 canonical 결과 comment가 기존 PR에 전달돼도 후속 reviewer가 새 head를 검토하기 전에는 승인 완료라고 보고하지 않는다. Final head와 exact comment readback, 전체 diff, 실제 검증 evidence와 resource·lock 정리가 일치할 때만 재작업 전달 및 comment handoff 완료로 판정한다.
Canonical external verification evidence
검증 실행 기록은 공통 Repository cache 운영 지침의 정본 경로 <harness-root>/repositories/<owner>/<repo>/worktrees/issue-<number>/verification/<run-id>에 보존한다. Product checkout과 artifact root를 분리하며, 회차별 evidence를 제품 docs/verification/에 새로 커밋하지 않는다. 기존 정본 문서·테스트·fixture·추적 파일은 자동 이동·삭제·ignore하지 않는다.
인증된 Issue/cache/worktree admission을 마친 caller가 broker Issue lease 아래 evidence run 전에 live lease의 exact harness root·Issue identity를 인증하고 root를 준비한다. Stage별 새 run-id를 사용한다. 아래 prepare는 verification/과 <run-id>/를 각각 별도 생성하고 각 directory를 실행 UID 소유 mode 0700으로 만들며 즉시 lstat한다. Symlink, owner·mode 불일치와 collision은 거부하고 기존 malformed root를 자동 chmod하거나 repair하지 않는다. 이 경로에는 중간 parent가 umask를 따르는 Path.mkdir(parents=True, mode=0o700)를 사용하지 않는다. Helper는 lease/cache를 획득·복구하지 않는다. <harness-root>는 실제로 읽은 contract path로 고정하고 다음 변수는 그 root와 인증된 Issue/run identity에서 결정한다. 아래 명령은 harness root에서 호출한다.
python3 harness/lib/verification_root.py prepare \
--root "$HARNESS_ROOT" --owner "$OWNER" --repository "$REPOSITORY" \
--issue "$ISSUE" --run-id "$RUN_ID" --handle "$HANDLE"
python3 harness/agents/impl/skills/gitea-issue-rework/scripts/evidence_manifest.py run \
--contract-path "$HARNESS_ROOT/harness/operations/repository-cache.md" \
--repo-root "$HARNESS_ROOT/repositories/$OWNER/$REPOSITORY/worktrees/issue-$ISSUE/checkout" \
--artifact-root "$VERIFICATION_RUN_ROOT" \
--plan evidence-plan.json --output evidence-manifest.json
python3 harness/agents/impl/skills/gitea-issue-rework/scripts/evidence_manifest.py validate \
--contract-path "$HARNESS_ROOT/harness/operations/repository-cache.md" \
--repo-root "$HARNESS_ROOT/repositories/$OWNER/$REPOSITORY/worktrees/issue-$ISSUE/checkout" \
--artifact-root "$VERIFICATION_RUN_ROOT" \
--manifest evidence-manifest.json
VERIFICATION_RUN_ROOT는 $HARNESS_ROOT/repositories/$OWNER/$REPOSITORY/worktrees/issue-$ISSUE/verification/$RUN_ID의 exact 절대 경로다. Plan의 hash_paths만 repository-relative이고 plan/output/manifest는 run-relative다. Source filename과 artifact filename이 같아도 같은 파일로 취급하지 않는다. run은 strict clean checkout, evidence exclusion 없음, full SHA·source/plan digest와 실제 command/exit code/bounded output binding을 요구하고 evidence-manifest/v3를 게시한다. Existing manifest를 덮어쓰지 않는다. validate도 같은 roots와 exact current HEAD를 요구한다. Dirty 개발 tree에서 validation 성공을 주장하지 않으며, final tracked 산출물을 commit한 뒤 그 exact commit을 검증하고 실패하면 push하지 않는다.
PR/결과 보고에는 stage/run-id, source SHA, manifest·plan digest, 실제 command/result/limitations와 reviewer 접근 수단을 함께 기록한다. Same-UID reviewer는 기록만 read-only로 읽고, distinct-UID/host이면 승인된 credential-free read-only export와 digest/readback receipt를 제공한다. 경로만 제시하거나 권한을 완화하는 것은 접근 검증이 아니다. 확인할 수 없으면 evidence_gap으로 보고한다. Product 테스트 증거와 harness 자체 검증을 구분하고, 인증정보 값은 [REDACTED]로만 기록한다.
Remote branch/PR head를 authoritative하게 읽어 source SHA·exact artifact와 결합하고 cleanup 전 실제 record readback을 확인한다. Helper의 local validate가 Gitea readback을 대신하지 않는다. Checkout 제거와 verification 폐기는 분리하며 완료 기록은 보존한다. 기존 v1은 validate-legacy의 read-only 호환 경로만 사용하고 새 publication proof로 사용하지 않는다.
Tracked bounded background evidence execution
Full suite가 포함되어 foreground tool 시간창을 넘을 것으로 예상되는 evidence plan은 기존 실행 도구의 tracked background 작업으로 시작한다. 새 scheduler나 process manager를 만들지 않는다. 실행 직전에 exact run-id, source SHA, plan digest, output path와 command를 기록하고 시작 응답의 process/session handle을 결합해 보존한다. Handle이나 PID만으로 source/admission 또는 실행 성공을 판정하지 않는다. Broker Issue lease와 기존 admission 조건은 그대로 유지하며, lease를 유지·검증할 수 없으면 외부 handoff를 차단한다.
Background도 각 command의 timeout_seconds를 유지하고, main이 plan의 command deadline·정리 예산·실행 overhead를 고려해 유한한 outer deadline을 명시한다. 기존 도구의 tracked wait/poll·완료 통지를 사용하되 outer deadline 만료 시에는 기존 bounded process-group cleanup과 wait/reap 절차를 적용한다. Notification이나 manifest 파일의 존재만으로 완료를 선언하지 않는다. 실행 도구가 필요한 추적·deadline·정리 capability를 제공하지 않으면 시작하지 않고 blocker를 보고한다. Background가 세션 종료 이후의 지속성을 보장하지 않는다.
Foreground 응답 timeout이나 통지 누락은 실제 evidence process 종료 또는 제품 assertion 실패의 증거가 아니다. 자동 retry하지 않는다. 재실행 판단 전에 보존한 handle로 기존 실행의 상태·실제 exit code·process 종료와 cleanup을 확인하고, 같은 run-id의 manifest를 exact source SHA·plan digest·output path에 결합해 canonical validate로 확인한다. Validation은 process 종료·cleanup 확인을 대신하지 않는다. Tool 관측과 artifact가 상충하거나 실행 중·상태 불명·cleanup 미확인이면 pending/partial로 유지하고 중복 실행하지 않는다. 같은 실행의 상태 확인과 기록 정리만 계속하며 완료된 suite를 다시 수행하지 않는다.
종료·cleanup이 확인된 성공은 기존 evidence를 검증해 재사용한다. 실패는 실제 exit code와 bounded 부분 출력·termination 기록을 보존한다. Timeout·출력 초과·cleanup 실패를 TDD RED로 보고하지 않는다. 실패한 manifest가 validate를 통과하지 못하더라도 그 자체를 재실행 허가로 삼지 않는다. 기존 실행이 종료되고 cleanup이 확인된 실패에 대해서만 별도 승인 후 새 run-id로 실행한다. 기존 artifact를 덮어쓰지 않는다. 이 절차는 workflow 문서 계약이며 evidence runner/schema, lease/TTL, publication journal 및 자동 retry 정책을 변경하지 않는다.
Command deadline 계약: 새 plan의 각 command는 timeout_seconds를 명시한다. Boolean·문자열·누락·비유한 값·0 이하·3600 초 초과를 실행 전에 거절하며 암묵적인 무제한 실행을 허용하지 않는다. Monotonic wall-clock deadline은 무출력 대기, stdout EOF 이후 실행, leader 종료 뒤 descendant가 유지한 pipe까지 적용한다. 각 command는 별도 session/process group에서 실행하고 timeout·출력 초과·예외 시 해당 process group을 TERM → 제한된 grace → KILL로 정리하고 direct child를 bounded wait로 회수한다. Leader가 종료됐어도 같은 group의 살아 있는 descendant를 남기지 않는다. 이것은 sandbox가 아니며 별도 session으로 이탈한 descendant의 containment나 grandchild 직접 회수를 보장하지 않는다.
evidence-manifest/v3는 실제 timeout, execution_status, termination의 term_sent·kill_sent·direct_child_reaped·group_cleanup_completed boolean 기록과 안전한 bounded 부분 출력을 결합한다. 새 claim pointer는 기존 6개에 timeout·실행 상태·종료 기록을 추가한 9개다. Linux /proc로 같은 group의 non-zombie 프로세스를 확인하며 확인·정리에 실패하면 cleanup_failed로 차단한다. TERM grace는 0.25 초, KILL 후 group 종료·direct-child 회수 예산은 0.5 초이며 오류 fallback wait도 0.1 초로 제한한다. 새 command의 max_output_bytes는 0–1048576 범위의 non-boolean 정수만 허용한다. execution_status는 completed|timeout|output_limit|cleanup_failed|descendant_cleanup이다. 정상 종료 leader 뒤의 살아 있는 descendant를 신호로 정리한 경우도 descendant_cleanup 실패이며, completed에는 TERM/KILL 신호가 있을 수 없다. Timeout·출력 한도 초과·정리 실패는 expected exit code와 같아도 성공이 아니며 TDD RED 또는 제품 assertion 실패로 분류하지 않는다. 해당 실행은 실패로 보존하고 뒤의 command를 실행하지 않으며, 실행된 prefix의 claim만 기록한다. Partial output에도 기존 secret 탐지를 적용하고 인증정보 유출은 fail-closed한다. 자동 재실행은 하지 않으며 새로 승인된 실행에는 새 run-id를 사용한다.
기존 evidence-manifest/v2는 명시적 validate-archived-v2 --contract-path <canonical-contract> --repo-root <checkout> --artifact-root <canonical-run> --manifest <run-relative-manifest>로 read-only 호환 검증한다. Canonical identity, exact current HEAD, source/plan/output binding을 유지하지만 과거 기록에 없던 timeout이나 종료 보장을 추론하지 않는다. 새 run/validate에는 v2 fallback이 없다. v1은 기존 validate-legacy만 사용한다. 두 archive 경로의 성공은 새 실행·TDD RED·fresh publication proof가 아니며 기존 artifact를 수정하거나 새 schema로 자동 변환하지 않는다.