[verified] Enforce delegation adoption at runtime consumers

This commit is contained in:
2026-10-11 07:11:40 +00:00
parent 9367d5a3a1
commit 6cb2317667
19 changed files with 1112 additions and 47 deletions
@@ -24,6 +24,8 @@ Baseline/current inventory를 생성·전달·채택할 때 `check-tests 이전`
위임 결과 채택 이전에 `harness/lib/delegation_evidence.py`를 [공통 증빙 채택 정본](../../../../operations/repository-cache.md#delegation-evidence-acceptance-preflight)에 따라 실행한다. 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 정본](../../../../operations/repository-cache.md#delegation-adoption-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
Issue workflow는 bootstrap 이후 반드시 [Repository cache 운영 지침](../../../../operations/repository-cache.md)의 하나의 role-neutral 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 stage run-id와 독립적이다. Runtime 생성은 approval이나 worktree admission을 대신하지 않는다. Cache bootstrap 이후 broker가 Issue lock 아래 runtime을 준비하고, ready 이후 각 workflow의 진입 검증·승인 조건을 확인한다. Client는 raw token을 inspect/log하지 않으며 public `request` API가 token을 캡슐화한다. Repository lock은 같은 handle의 `acquire_repository`/`release_repository` request로만 중첩하고, TTL 전에 `renew`한다. 정상·오류·cancel 모두 `release_repository`(보유 시) → `release` → broker wait/reap → `probe`의 `free=true` 확인 순서를 완료하기 전에는 완료·로그·보고하지 않는다. Raw `flock ... sleep`과 lock-file unlink는 금지한다.
@@ -197,11 +199,11 @@ Discovery가 `신규 작성` 또는 `수정`으로 판정한 문서만 작성한
6. 기존 requirement revision이면 final tree에 Contract Preservation Inventory를 다시 대응해 `missing=0`, `ambiguous=0`을 확인한다. 충족하지 못하면 stage하거나 commit하지 않는다.
7. 승인된 modified·untracked file을 exact allowlist로 stage하고 staged diff를 다시 읽는다. 범위 밖 파일, credential, generated artifact 또는 예상하지 못한 삭제가 있으면 commit하지 않는다.
8. Repository convention에 맞는 non-amended commit을 생성하고 base ancestry, commit tree와 worktree 상태를 검증한다. Push 전에 그 exact commit의 strict clean checkout에서 canonical external verification helper로 최종 검증을 실행·validate하고 manifest의 source SHA가 전달할 commit과 일치함을 확인한다. 실패하면 local commit을 보존하고 push하지 않는다.
9. Issue worktree는 delivery 전후 모두 detached HEAD로 유지한다. Issue 전용 remote branch가 없으면 detached final commit을 explicit repository URL과 `<final-sha>:refs/heads/<issue-branch>` refspec으로 push해 생성하고, 있으면 현재 작업이 소유한 branch이며 fast-forward 가능한 경우에만 같은 방식으로 갱신한다. `git switch -c`, `git checkout -b`, `git branch` 또는 동등한 명령으로 canonical mirror의 `refs/heads/*`에 구현용 local branch를 만들지 않는다. Default branch에는 직접 push하지 않고 force-push하지 않으며 canonical cache의 mirror remote 설정을 변경하지 않는다.
9. Main은 아래 9–12의 push/readback/PR 동작을 main-owned adapter로 구현하고 `scripts/implementation_delivery.py`의 `deliver_implementation(adapter, head=final_head, declaration=main_declaration)`로 실행한다. Callback을 직접 먼저 실행하거나 이전 PASS로 생략하지 않는다. Adapter의 인증·repository/Issue·branch scope 검증은 아래 규칙을 모두 유지한다. Issue worktree는 delivery 전후 모두 detached HEAD로 유지한다. Issue 전용 remote branch가 없으면 detached final commit을 explicit repository URL과 `<final-sha>:refs/heads/<issue-branch>` refspec으로 push해 생성하고, 있으면 현재 작업이 소유한 branch이며 fast-forward 가능한 경우에만 같은 방식으로 갱신한다. `git switch -c`, `git checkout -b`, `git branch` 또는 동등한 명령으로 canonical mirror의 `refs/heads/*`에 구현용 local branch를 만들지 않는다. Default branch에는 직접 push하지 않고 force-push하지 않으며 canonical cache의 mirror remote 설정을 변경하지 않는다.
10. Target repository write 권한이 없으면 같은 push를 반복하지 않는다. Authenticated identity가 fork를 생성할 수 있으면 기존 fork·동명 branch·PR 유무와 fork parent/base SHA를 검증한 뒤 fork의 Issue 전용 branch로 non-force push하고 cross-repository PR을 사용한다. Fork도 쓸 수 없으면 permission blocker와 local commit SHA를 보고한다.
11. Remote readback으로 branch owner, repository, branch SHA가 local commit SHA와 exact-match하는지 확인한다.
12. Default branch를 base로 PR을 생성한다. 제목은 Issue를 식별하고, 본문에는 `Closes #<number>`, 구현 요약, 문서 변경, 실제 검증 명령·결과, 제한사항과 보안상 주의점을 기록한다. PR 생성 자체로 Issue state를 변경하지 않는다.
13. PR 번호를 얻은 뒤 요구사항 문서의 `구현 PR: 미정`을 실제 PR 번호 또는 URL로 교체하고, 문서 검증과 관련 test를 재실행해 별도 commit으로 같은 branch에 non-force push한다.
13. 후속 commit의 push에도 새 head/source/context/result를 결속해 동일 delivery workflow를 사용하며 create_or_reuse_pr는 이미 확인된 같은 PR을 재사용한다. PR 번호를 얻은 뒤 요구사항 문서의 `구현 PR: 미정`을 실제 PR 번호 또는 URL로 교체하고, 문서 검증과 관련 test를 재실행해 별도 commit으로 같은 branch에 non-force push한다.
14. Gitea에서 PR details, base branch, head repository·branch·SHA, state, changed files와 commit을 다시 읽는다. 최종 remote head SHA가 최종 local commit SHA와 일치할 때만 전달 완료로 판정한다.
15. Gitea Actions 또는 commit status가 제공되면 최종 head의 success, failed, pending, run 없음 또는 조회 불가 상태를 읽고 그대로 보고한다.
16. PR 생성 또는 후속 push가 부분 실패하면 blind retry하거나 중복 PR을 만들지 않는다. 이미 생성된 fork·branch·PR과 local commit의 exact 상태 및 안전한 복구 지점을 보고한다.