[verified] Clarify Issue body provider-derived revision readback contract

This commit is contained in:
2026-10-12 22:10:55 +00:00
parent c1f0034300
commit 33b0e44421
4 changed files with 31 additions and 0 deletions
@@ -109,3 +109,6 @@ comment는 다음 형식을 사용한다. `<original-body>`에는 write 직전 G
- dry-run/local 검증과 실제 Gitea write 결과 - dry-run/local 검증과 실제 Gitea write 결과
프로세스 exit나 API write 응답만으로 성공을 주장하지 않는다. Authoritative readback이 하나라도 실패하면 partial 또는 failure로 보고한다. 프로세스 exit나 API write 응답만으로 성공을 주장하지 않는다. Authoritative readback이 하나라도 실패하면 partial 또는 failure로 보고한다.
Issue body 교체에는 공통 access 지침의 **Issue body update의 provider-derived readback**을 적용한다. 13번의 post-comment snapshot을 body update 직전 baseline으로 사용한다. Comment 작성의 정상 파생 변경은 해당 comment operation의 확인된 계약으로 별도 대조하며 body update의 revision 증가 규칙을 comment write에 적용하지 않는다. `content_version`의 노출·matching provider contract 근거를 기록하고 15번의 다른 snapshot 필드 비교는 보호 필드 보존과 확인된 operation별 provider-derived 변경 검증으로 구분한다. Write 전 drift 검사는 유지하며 불확실한 결과를 완료로 추정하거나 자동 재write하지 않는다.
@@ -122,3 +122,6 @@ Bootstrap 이후 Discovery review는 canonical [Repository cache 운영 지침](
- partial 또는 fail-closed 상태 - partial 또는 fail-closed 상태
프로세스 exit나 API write 응답만으로 성공을 주장하지 않는다. Authoritative readback 또는 replay 검증이 하나라도 실패하면 completed로 보고하지 않는다. 프로세스 exit나 API write 응답만으로 성공을 주장하지 않는다. Authoritative readback 또는 replay 검증이 하나라도 실패하면 completed로 보고하지 않는다.
Issue body 교체의 snapshot과 readback에는 공통 access 지침의 **Issue body update의 provider-derived readback**을 적용한다. `content_version` 등 revision의 노출·matching provider contract 근거를 기록하고, write 직전 drift는 계속 차단한다. 15번의 비본문 필드 불변성은 보호 필드 보존과 확인된 operation별 provider-derived 변경 검증을 뜻하며 모든 snapshot 필드의 blanket equality 또는 blanket exclusion이 아니다. Readback이 불확실하거나 필수 검증이 실패하면 completed로 보고하거나 자동 재write하지 않는다.
+9
View File
@@ -40,6 +40,15 @@
- 성공 response만으로 완료를 주장하지 않는다. Exact target을 fresh readback하고 author stable account ID, payload, timestamp, commit/ref와 collection cardinality를 baseline과 비교한다. - 성공 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로 중단한다. - Timeout, malformed response 또는 connection loss 뒤에는 같은 mutation을 재호출하기 전에 complete collection을 한 번 읽어 결과를 reconciliation한다. 결과가 없거나 여러 개이거나 경쟁 mutation과 구분할 수 없으면 uncertain/partial로 중단한다.
### Issue body update의 provider-derived readback
- 이 계약은 승인된 Issue body update에만 적용한다. 현재 origin의 실제 server version·endpoint/update 경로와 독립적으로 확인한 matching provider contract를 기존 snapshot/근거에 연결한다. 보관 소스나 snapshot 자체의 version 주장만으로 현재 서버 계약을 확정하지 않는다. Revision 필드의 API 노출 여부도 확인하며, 내부 모델 필드가 transport에 항상 노출된다고 추정하지 않는다.
- Write 직전 fresh snapshot은 target identity와 body, `updated_at`, comment baseline 및 보호 필드(title·state·labels·assignees·milestone 등)를 승인 baseline과 비교한다. 노출된 revision도 비교하여 pre-write drift를 차단한다. Provider 파생 변경 허용은 write 이후에만 적용하며 drift gate나 기존 조건부 update를 완화하지 않는다.
- Readback의 body는 실제 전송 artifact의 exact bytes와 같아야 한다. 보호 필드와 해당 workflow의 complete comment baseline 계약은 그대로 검증한다. `content_version`이 해당 authenticated transport의 baseline과 readback에 제공되고 matching contract가 이 단일 body update에서 정확히 1 증가를 보장하면, 두 값이 boolean이 아닌 비음수 정수인지 확인하고 after == before + 1을 검증한다. 같은 body의 no-op에는 증가를 요구하지 않는다.
- Revision이 누락·malformed이거나 증가가 0 또는 2 이상이거나 계약이 미확인이면 one-step 검증 성공으로 추정하지 않는다. Provider가 필드를 노출하지 않는 확인된 계약이면 비노출·검증 한계를 기록하고 workflow의 나머지 필수 검증을 적용한다. 필수 revision 근거가 부족하거나 경쟁 mutation과 구분할 수 없으면 uncertain/partial로 중단한다. `updated_at` 등 다른 필드도 같은 operation의 확인된 인과·타입·변경 규칙으로 각각 대조하며 일괄 비교 제외하지 않는다. Timestamp만으로 경쟁 변경이 없다고 주장하지 않는다.
- 정상 파생 증가와 무관한 mutation을 구분하여 fresh readback으로 reconciliation한다. Body가 일치해도 다른 필수 검증이 실패하면 completed가 아니다. Timeout·오류·불일치 뒤에는 자동 재write하지 않는다. 보존된 baseline·payload·현재 결과로 판정하고 불확실하면 uncertain/partial로 보고한다. 별도 승인된 재개에서도 fresh identity·lease·snapshot·drift gate를 다시 통과한다.
- 이는 기존 adapter를 사용하는 main의 비교 절차이며 새 runtime checker·publisher·projection framework 또는 자동 retry를 추가하지 않는다. 문서 계약 테스트 통과는 실제 adapter 준수나 live 서버 동작을 검증한 것이 아니다.
## Credential 안전 ## Credential 안전
- Credential 값은 role profile의 secret store에만 저장하고 repository, harness 문서와 workflow artifact에는 저장하지 않는다. - Credential 값은 role profile의 secret store에만 저장하고 repository, harness 문서와 workflow artifact에는 저장하지 않는다.
@@ -10,6 +10,22 @@ README = HARNESS / 'docs/discovery/README.md'
class PriorityReviewContracts(unittest.TestCase): class PriorityReviewContracts(unittest.TestCase):
def test_issue_body_provider_revision_documentation_contract(self):
access = (HARNESS / 'operations/gitea-access.md').read_text()
contract = access.split('### Issue body update의 provider-derived readback', 1)[-1]
for required in ('matching provider contract', 'content_version', '정확히 1',
'baseline과 readback', '정수', 'boolean', 'pre-write drift',
'자동 재write하지 않는다', 'updated_at', '보호 필드',
'uncertain/partial', '새 runtime checker'):
self.assertIn(required, contract)
authoring = (HARNESS / 'agents/spec/skills/gitea-discovery-authoring/SKILL.md').read_text()
for text in (DISCOVERY.read_text(), authoring):
self.assertIn('Issue body update의 provider-derived readback', text)
self.assertIn('content_version', text)
self.assertIn('자동 재write하지 않는다', text)
self.assertIn('post-comment snapshot을 body update 직전 baseline', authoring)
def test_scope_classification_and_optional_nonblocking(self): def test_scope_classification_and_optional_nonblocking(self):
text = README.read_text() text = README.read_text()
for value in ('핵심 요청:', '기존 호환성:', '선택적 확장:', for value in ('핵심 요청:', '기존 호환성:', '선택적 확장:',