docs(issue-5): record the evidence requirement, the audit lock and the ack rule
Three contract points the round 2 fixes established. An idempotent re-receipt is an ACK in the table, so a caller must treat it as success. Only a genuine refusal is non-zero, and an invalid status stays the usage error it always was. That distinction is what keeps the wrapper's approved path from aborting under set -e. Completion attribution now requires evidence to be present, not merely non-contradictory, and names where it may be read from: a collector envelope beside the payload, or a non-native source's own payload. Never from inside a native Herdr payload, because MAM fields are forbidden there and one appearing anyway is not evidence of anything. The audit mirror's ordering guard is documented as a locked read-compare-write, with the reason a bare sequence number was not enough, and the note that the lock is deliberately taken outside the registry transaction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd
This commit is contained in:
1 parent
cb575fa851
commit
0e74aa1e4e
3 files changed
+18
-3
No files matched your search
@@ -31,7 +31,7 @@ Shadow 러너는 애초에 쓰기 경로가 없으므로 **프로세스 종료
|
||||
| `publish_event` (에이전트) | 자신의 작업을 `running`/`completed`/`error`/`cancelled`로 전이 | **terminal을 되돌리는 것** (`redispatch`/`finalize` 거부) |
|
||||
| `registry_cli` (래퍼·운영자) | 위 전부 + `redispatch`(terminal→`pending`, iteration 증가 필수) + `finalize`(terminal→`error`) | iteration을 되돌리는 재생 |
|
||||
|
||||
**CLI 종료 코드 변경**: `registry.py status`/`update`가 CAS에 의해 거부되면 이제 **stderr에 사유를 내고 non-zero(4)** 로 종료한다. Phase 2a 이전에는 거부가 불가능해 항상 0이었고, 그 침묵이 반복 위임이 조용히 깨진 것을 감췄다.
|
||||
**CLI 종료 코드**: `registry.py status`/`update`는 **진짜 거부**에만 non-zero(4)를 낸다. 잘못된 status 값은 rc 1(2a 이전 계약 유지), **멱등 ACK(이미 그 상태임)는 rc 0**이다 — 래퍼가 `set -e` 아래에서 승인 직후 `--set completed`를 실행하므로 이를 실패로 보고하면 성공 경로가 중단된다(교차 리뷰 F-C/F-D). Phase 2a 이전에는 거부가 불가능해 항상 0이었고, 그 침묵이 반복 위임이 조용히 깨진 것을 감췄다.
|
||||
|
||||
## 3. 락 규율 (P2A-01)
|
||||
|
||||
@@ -40,7 +40,7 @@ with registry_lock: 판정 + 레코드 1회 쓰기 + 알림 큐잉 ←
|
||||
락 해제 후: 감사 로그 flush, 발행 등 느린 작업
|
||||
```
|
||||
|
||||
감사 mirror가 락 밖으로 나가면서 순서 보장을 잃을 수 있으므로, 전이마다 단조 증가하는 `transition_seq`를 레코드와 알림에 함께 싣는다. **`update_logged_status`는 기존 `status.json`의 `transition_seq`가 더 크거나 같으면 쓰기를 건너뛴다** — 지연된 flush가 최신 상태를 되돌리지 못하게 하는 것이며, 락이 공짜로 주던 순차 일관성을 복원한다(교차 리뷰 F-B). 이 형태는 새로 만든 것이 아니라 `pick_pending`이 이미 쓰던 패턴을 모든 전이로 일반화한 것이다.
|
||||
감사 mirror가 락 밖으로 나가면서 순서 보장을 잃을 수 있으므로, 전이마다 단조 증가하는 `transition_seq`를 레코드와 알림에 함께 싣는다. **`update_logged_status`는 전용 per-job 감사 락 아래에서 읽기-비교-쓰기를 수행하고, 기존 `status.json`의 `transition_seq`가 더 크거나 같으면 쓰기를 건너뛴다**(교차 리뷰 R4: 락 없는 비교-후-쓰기는 두 flush가 모두 옛 값을 읽고 느린 쪽이 최신을 덮어쓸 수 있어, 시퀀스 번호만으로는 순서가 강제되지 않는다). 이 락은 **레지스트리 트랜잭션 밖**에서 잡으므로 느린 감사 I/O가 트랜잭션을 늘리지 않는다. 각 쓰기는 고유 임시 파일을 쓴다 — 지연된 flush가 최신 상태를 되돌리지 못하게 하는 것이며, 락이 공짜로 주던 순차 일관성을 복원한다(교차 리뷰 F-B). 이 형태는 새로 만든 것이 아니라 `pick_pending`이 이미 쓰던 패턴을 모든 전이로 일반화한 것이다.
|
||||
|
||||
## 4. `herdr agent wait` 사용 규칙
|
||||
|
||||
@@ -50,6 +50,17 @@ with registry_lock: 판정 + 레코드 1회 쓰기 + 알림 큐잉 ←
|
||||
- **타임아웃은 건강한 응답이다.** 소켓이 답했고 상태가 안 바뀐 것뿐이다. 전송 실패와 구분해야 한다.
|
||||
- 전송 실패 시 백오프는 1→2→4→8→16초 상한이며, **캐시된 스냅샷을 폐기**한다. 단절 구간 이전의 상태로 추론하면 단절이 완료처럼 보인다.
|
||||
|
||||
## 4-1. 완료 귀속에 요구되는 증거 (교차 리뷰 R1)
|
||||
|
||||
`candidate_approved`는 **증거의 존재**를 요구한다. 값이 있을 때만 비교하는 방식은, 아무 식별자도 없는 증거를 dispatch 레코드의 자기 선언만으로 승인해 버린다 — 이 검사가 대체하려던 바로 그 자기 선언이다.
|
||||
|
||||
| 요구 증거 | 위치 | 없으면 |
|
||||
|---|---|---|
|
||||
| `job_id`, `attempt_id`, `agent_session_uuid`, `pane_process_generation` | 타임라인 항목의 **`collector_attribution` 봉투** (또는 event/filesystem 등 **비-herdr** 소스의 payload) | `hold` |
|
||||
| 리포트 매니페스트의 `attempt_id` | filesystem 소스 payload의 `report_manifest` | `hold` |
|
||||
|
||||
**네이티브 경계 유지**: 식별자는 **네이티브 Herdr payload 안에서 읽지 않는다.** Phase 0이 네이티브 페이로드에 MAM 필드 주입을 금지하므로, 거기 나타난 식별자는 조작이거나 계약 위반이며 어느 쪽이든 증거가 아니다. 수집기의 연관 정보는 payload **옆**의 봉투에 둔다.
|
||||
|
||||
## 5. 판정 순서 (fail-closed)
|
||||
|
||||
1. 전송 이상 → `hold_reconnect` (증거 자체가 무효)
|
||||
|
||||
Reference in new issue
Block a user