# task-2625 — RECONCILE_EVIDENCE_CONTRACT_ADDITIVE_IMPLEMENTATION

- **task_id**: task-2625
- **work_level**: Lv.2 (additive · ~50 production LOC + regression)
- **dispatched_by**: ANU (회장 결정 2026-05-21 범위 B 승인)
- **assignee**: dev6 페룬 (task-2623/2624 reconcile context 연속 · baseline 민감)
- **base_dry_run_doc**: memory/events/task-2624.reconcile_evidence_dry_run.result.json
- **base_proposal_docs**:
  - memory/events/reconcile_evidence_json_schema_proposal.json
  - memory/events/reconcile_evidence_dry_run_fixture_matrix.json
  - memory/events/reconcile_evidence_B_scope_estimate.json

---

## 0. PRE-DISPATCH SPEC (회장 verbatim 박제 · D-SPEC-EXACTNESS · paraphrase 금지)

회장 verbatim (2026-05-21):

> 범위 B 승인: RECONCILE_EVIDENCE_CONTRACT_ADDITIVE_IMPLEMENTATION
> 목표: post-merge smoke evidence 전용 path를 분리하고, lifecycle_reconciliation_manager가 해당 evidence를 additive로 조회할 수 있게 한다. 기존 QC gate 의미를 절대 오염시키지 않는다.

---

## 1. expected_files (회장 verbatim · 정확 일치)

1. `utils/post_merge_smoke_runner.py`
2. `utils/lifecycle_reconciliation_manager.py`
3. `tests/regression/test_reconcile_evidence_contract_2624.py` (★회장 지정 명명 — task ID 는 2625 지만 test 파일명은 _2624 verbatim 유지)

**expected_files count = 3**. 이 외 파일 변경 시 effective_diff_contamination → Critical7.

---

## 2. 원칙 (회장 verbatim)

- additive only
- production LOC 약 50 내외 유지
- qc-result 재사용 금지
- qc-result 기존 의미 변경 금지
- post-merge-smoke.json 전용 path 사용
- 기존 QC gate / finish-task / task-timer 무영향
- PR/merge/branch/main/credential write 금지
- Track C 수정 금지
- replacement PR runner 수정 금지

---

## 3. Evidence contract (회장 verbatim)

- post_merge_smoke_runner.py는 전용 post-merge-smoke.json evidence를 생성할 수 있어야 함
- lifecycle_reconciliation_manager.py는 RECONCILING 단계에서 해당 evidence를 조회할 수 있어야 함
- evidence schema version 포함
- status는 PASS / FAIL / TIMEOUT / BLOCKED / SKIPPED를 구분
- TIMEOUT/BLOCKED를 PASS 또는 SKIPPED로 오분류 금지
- substring matching 금지
- structured JSON field 기반 판정

### 3.1 구현 가이드 (proposal anchor)
- evidence path: `memory/events/{task_id}.post-merge-smoke.json`
- schema: `post_merge_smoke_evidence.v1` (schema_version 필드 명시)
- structured fields: `schema_version` / `smoke_status` (5 enum) / `merge_commit` / `task_id` / `ts` / `smoke_command`(optional) / `duration_ms` / `stdout_tail`(redacted) / `stderr_tail`(redacted) / `failure_reason` / `stale` / `allow_continuation`
- post_merge_smoke_runner: `run_post_merge_smoke()` 완료 직후 또는 `main()` 에서 atomic temp+rename write (모든 status PASS/FAIL/SKIPPED/TIMEOUT/BLOCKED)
- redaction: stdout_tail/stderr_tail 에 token/credential 매칭 시 [REDACTED]
- lifecycle_reconciliation_manager: `LifecycleEvidence` 에 `post_merge_smoke_status` 신규 필드 추가 (기존 `smoke_status`=QC gate 는 불변) + `gather_evidence` 에 별도 lookup (json.load 로 structured 판정 · substring 금지) + RECONCILING transition 반영

---

## 4. REF4 정책 (회장 verbatim)

- smoke SKIPPED는 기본적으로 FINALIZED 허용 금지
- SKIPPED는 POST_MERGE_SMOKE_SKIPPED / NEEDS_REVIEW / HOLD 계열로 분리
- 명시적 skip reason + 별도 policy allow 없이는 완료 처리 금지

---

## 5. smoke_command registry (회장 verbatim)

- 이번 B에서는 의무화하지 않는다
- smoke_command / smoke_command_registry_key는 optional field로 proposal 유지
- 필수화는 별도 task로 분리

---

## 6. 역할 분리 문서화 (회장 verbatim)

- qc-result = pre-merge QC gate 산출물
- post-merge-smoke.json = post-merge smoke evidence 산출물
- 둘은 절대 혼합하지 않는다
- 코드 주석/docstring 에 역할 분리 명시

---

## 7. 필수 regression (회장 verbatim · 10건)

1. post-merge-smoke PASS → reconcile에서 PASS 인식
2. FAIL → fail 인식
3. TIMEOUT → timeout 인식, PASS 오분류 금지
4. BLOCKED → blocked 인식, PASS 오분류 금지
5. SKIPPED → FINALIZED 금지
6. qc-result와 post-merge-smoke.json 역할 분리
7. 기존 qc-result backward compatibility
8. substring false-positive 방지
9. missing post-merge-smoke evidence 처리
10. malformed evidence 처리

test 파일: `tests/regression/test_reconcile_evidence_contract_2624.py` · mock-based · 실 smoke 0 · 실 reconcile apply 0 · subprocess 0

---

## 8. forbidden_paths

- `memory/events/{task_id}.qc-result` (QC gate 영역 — read 만, 의미 변경/write 금지)
- `teams/shared/qc_verify.py` (QC gate producer — 변경 0)
- `scripts/finish-task.sh` (변경 0)
- `memory/task-timer.py` (변경 0)
- `utils/replacement_pr_runner.py` (회장 verbatim — replacement PR runner 수정 금지)
- `anu_v2/**` · `dispatch/**` · `.github/workflows/*`
- credential 파일 (`.env*`, `*.pem`, `*.key`)

forbidden path 1건이라도 detected → 즉시 Critical7 보고 + halt.

---

## 9. 14단계 finalize + 8 직접 행동 (회장 doctrine 강제 · wrapper 처리 표현 금지)

### 9.1 finalize 14단계
1. expected_files 정확 일치 검증 (외부 lint 1회)
2. forbidden_paths 검증 (qc-result/qc_verify/finish-task/task-timer 무변경 확인)
3. regression test PASS (10 fixtures all pass · pytest tests/regression/test_reconcile_evidence_contract_2624.py)
4. 전체 suite 회귀 0 (기존 tests/test_task_timer_qc.py · anu_v2/tests/test_post_merge_smoke_runner_2539.py · reconcile 기존 regression PASS 카운트 유지)
5. lint/type check (ruff/mypy 프로젝트 기본)
6. commit (BOT identity · token raw 노출 0 · force/admin/rebase 금지)
7. push origin <clean_branch> (same-branch push 금지 · clean_branch_name task-2625-reconcile-evidence)
8. PR create (gh pr create --base main --head <branch>)
9. CI 통과 대기 (모든 check SUCCESS)
10. Gemini review 1회 도착 후 처리 (post-Gemini same-PR push 금지 → 위반 시 replacement PR doctrine)
11. mergeStateStatus CLEAN 확인
12. HEAD SHA lock 검증
13. squash merge (admin/force 금지 · OWNER_PAT 절대 금지)
14. post-merge smoke + reconcile 결선 (본 task 가 결선 대상 — 자기 evidence contract 검증)

### 9.2 봇 직접 행동 8항목
1. task md 본문 읽기 · 9-R 검증 · 본질 변형 0
2. expected_files 외 파일 변경 0
3. forbidden_paths 탐지 시 즉시 Critical7 보고 + halt
4. credential value 로그/PR/cron prompt 평문 노출 0
5. BOT_GITHUB_TOKEN (ghs_ App token) 만 사용 · OWNER_PAT/ghp_ 절대 금지
6. same-branch push 금지 · clean branch (task-2625-reconcile-evidence)
7. result.json 에 callback contract 9 fields 모두 PRESENT 보장
8. 봇 정상종료 직전 normal callback ANU key 발사 (c119085addb0f8b7 · 자기 key 절대 금지)

---

## 10. callback contract — 9 필수 fields (정책 (a) STANDARDIZED · UTF-8 ≤3900 bytes hard)

result.json 에 9 fields 모두 PRESENT:
1. `callback_prompt_utf8_bytes` (int · `printf '%s' "$P" | wc -c` 측정)
2. `callback_prompt_chars` (int)
3. `callback_cron_id` (string|null)
4. `callback_registration_status` (REGISTERED_FIRED_OK / REGISTERED_NOT_YET_FIRED / CALLBACK_PROMPT_TOO_LARGE / REGISTRATION_FAILED)
5. `callback_role` ("COLLECTOR_ANU")
6. `envelope_only_compliance` (bool)
7. `fallback_prompt_utf8_bytes` (int)
8. `fallback_safety_net_registered` (bool)
9. `fallback_safety_net_role_single_purpose` ("RECOVERY_ONLY_NO_FINAL_REPORT_TRIGGER")

callback prompt UTF-8 ≤3900 bytes hard limit · envelope 만 (task_id/result_path/decision_path/report_path/sha256/collector_role=ANU/owner_key/one-line summary) · 초과 시 CALLBACK_PROMPT_TOO_LARGE fail-closed.

---

## 11. baseline anchors (3-way blob · task-2623 교훈 반영 · 변경 0)

- `utils/post_merge_smoke_runner.py` — HEAD=origin/main=working-tree blob `a2c69bca117e7c756b8a93b35464aeb1d46f0687` · 590 lines · **본 task 가 additive 수정 대상**
- `utils/lifecycle_reconciliation_manager.py` — HEAD=origin/main=working-tree blob `2ccfe44f5fa57f4b2964f9570081115631661717` · 1932 lines · **본 task 가 additive 수정 대상**
- `memory/events/{task_id}.qc-result` 의미 — QC gate (qc_verify.py --gate) 산출물 · **본 task 변경 0**

봇은 작업 시작 전 두 모듈의 3-way blob 을 재확인하라 (`git ls-tree HEAD` + `git show origin/main:` + `git hash-object` 일치 검증). 불일치 시 HALT + escalate.

---

## 12. 완료 보고 (회장 verbatim · 10항목)

result.json + report 가 아래 10항목 답변:
1. B 구현 PASS/HOLD
2. expected_files 정확성 (3개만 변경 확인)
3. evidence path (memory/events/{task_id}.post-merge-smoke.json)
4. schema/status 판정 (5 enum structured JSON · substring 0)
5. REF4 처리 (SKIPPED → FINALIZED 금지 · NEEDS_REVIEW/HOLD 계열)
6. regression 결과 (10 fixtures pass/fail/skip)
7. Codex audit 결과 (HIGH/CRITICAL 0)
8. QC gate 무영향 증거 (qc-result/qc_verify/finish-task/task-timer 무변경)
9. PR/merge/credential/write 0 증거
10. live merge pilot 가능성 변화 (PARTIAL #14 closure 후 14조건 13→14 WIRED 여부)

---

## 13. doctrines (필수)

- additive only — 기존 smoke_status(QC gate) lookup/field 불변 · 신규 post_merge_smoke_status field/path 추가만
- qc-result 절대 재사용/오염 금지 (회장 핵심)
- same-PR post-Gemini push 금지 (feedback_same_pr_push_after_gemini)
- attempt-1 only · finding 시 회장 escalate (9-R)
- OWNER_TRIGGER_ONLY_CAPABILITY (BOT App token 만)
- baseline 3-way blob 재검증 (feedback_audit_baseline_3way_blob_verify_260521)

---

## 14. attempt limit

- attempt-1 only · 자동 재시도 금지
- spec drift/ambiguity 발견 시 변형 금지 → HOLD + 회장 escalate (task-2623 페룬 선례)

---

## allowed_resources (본 task의 capability)

```yaml
allowed_resources:
  paths:
    - "utils/post_merge_smoke_runner.py"
    - "utils/lifecycle_reconciliation_manager.py"
    - "tests/regression/test_reconcile_evidence_contract_2624.py"
    - "memory/events/task-2625.result.json"
    - "memory/reports/task-2625.md"
    - "memory/tasks/task-2625.md"
  forbidden_paths:
    - "memory/events/*.qc-result"
    - "teams/shared/qc_verify.py"
    - "scripts/finish-task.sh"
    - "memory/task-timer.py"
    - "utils/replacement_pr_runner.py"
    - "anu_v2/**"
    - "dispatch/**"
    - ".github/**"
    - ".env*"
    - "*.pem"
    - "*.key"
  commands:
    - "pytest"
    - "python3 -m py_compile"
    - "ruff"
    - "git"
    - "gh"
  merge_policy: "tiered"
  ttl_hours: 24
```

## 15. 산출물

봇 생성:
- `utils/post_merge_smoke_runner.py` (additive +~20 LOC evidence write)
- `utils/lifecycle_reconciliation_manager.py` (additive +~30 LOC lookup + field + transition)
- `tests/regression/test_reconcile_evidence_contract_2624.py` (신규 · 10 fixtures)
- `memory/events/task-2625.result.json` (callback 9 fields + 10항목 완료 보고)
- `memory/reports/task-2625.md` (10항목 human-readable)
- PR (1개 · clean branch task-2625-reconcile-evidence)

## 16. callback envelope (참고)

```
task_id=task-2625
result_path=memory/events/task-2625.result.json
decision_path=memory/events/task-2624.reconcile_evidence_dry_run.result.json
report_path=memory/reports/task-2625.md
sha256=<task md sha256>
collector_role=ANU
owner_key=c119085addb0f8b7
summary=RECONCILE_EVIDENCE_CONTRACT_ADDITIVE_IMPLEMENTATION result · 10항목 result.json 참조
```

끝