---
task_id: task-2472+1
type: context-notes
scope: task
status: completed
created: 2026-05-07
updated: 2026-05-07
---

# Context Notes: task-2472+1

## 사고 evidence (task-2472 state-orphaned)

- `.tasks/state/task-2472.json` 부재 (state file missing)
- `memory/events/task-2472.done` 존재, sha256 = `adc694fad95de92d45f80567bf6720e3a6e71ec7e4b6abde7f367064feb902cc`, payload qc_result=PASS
- `memory/events/task-2472.g3-fail` 존재, sha256 = `9bedbb7903469586a5b4adbe5e31db3317cecb90dec9d07b209d50c3d0dd5007`, fail_reasons=["report not found: memory/reports/task-2472.md"]
- `memory/reports/task-2472.md` 존재 (mtime: 2026-05-07 18:41:18 — g3-fail mtime 18:07:21 보다 늦음 → false_alert_resolved_by_late_report 패턴 확정)
- PR #40: state=MERGED, mergedAt=2026-05-07T09:03:14Z, mergeCommit=6ec4e0d8a4e4d2dd39fbd13eb19a69d4212faeba
- origin/main HEAD = 6ec4e0d8 (= PR #40 merge commit), ancestry PASS
- 회장 직접 audit 기록: `memory/orchestration-audit/state-recovery.jsonl` 마지막 줄, chairman_authorized=true, actor=anu-direct

## 설계 결정

### 1. reconcile 종착 상태는 DONE

이유: PR이 정상 머지되었고 `.done` payload가 valid이므로 task는 사실상 DONE 상태. reconcile은 사후 ack이므로 transitions를 합성한 후 current_state=DONE으로 마무리.

대안: MERGED → 추가로 `taskctl done` 호출 — 그러나 done은 다시 silent_corruption_guard 검증을 트리거하고 .done이 이미 있으므로 중복 발행 위험. reconcile이 직접 DONE을 set하는 것이 안전.

### 2. classification enum 분기

각 enum은 다른 evidence 셋을 요구:

| classification | 필수 evidence |
|---|---|
| `state_orphaned_after_valid_merge` | PR state=MERGED, origin/main ancestry PASS, .done valid + sha256 일치, .g3-fail가 없거나 false_alert |
| `state_corrupted_with_partial_merge` | PR partial merge evidence (commit 일부만 main에) — 현재는 enum 인식만, 실 분기는 future |
| `state_inconsistent_after_force_push` | force push 흔적 (reflog 등) — 현재는 enum 인식만 |
| `state_missing_after_taskctl_crash` | crash 시점 evidence (timer end 없음 등) — 현재는 enum 인식만 |

핵심 케이스는 `state_orphaned_after_valid_merge`. 나머지 3종은 enum 인식 + reject(Not implemented or insufficient evidence) — 회장 명시 보완 1 충족.

### 3. .g3-fail 자동 분류 룰

`false_alert_resolved_by_late_report`: fail_reasons에 "report not found"만 있고, report 파일이 g3-fail 발행 후 생성된 경우. → reconcile 허용.
`unresolved`: 그 외 모든 케이스. → reject (fail-closed).

### 4. audit jsonl 14필드 schema

```python
schema_required = [
    "task_id",          # 1
    "ts",               # 2
    "classification",   # 3
    "pr",               # 4
    "merge_commit",     # 5
    "origin_main_head", # 6
    "ancestry",         # 7
    "done_path",        # 8
    "done_sha256",      # 9
    "g3_fail_classification",  # 10
    "actor",            # 11
    "evidence_path",    # 12
    "approved_by_chairman",   # 13
    "decision",         # 14
]
```

### 5. state 재구성 transitions

reconcile이 합성하는 transitions 시퀀스 (회장 명시 evidence 기반):
1. CREATED → DISPATCHED → ACKED → RUNNING → COMMITTED → PR_OPEN → CI_PENDING → GEMINI_PENDING → REVIEW_READY → VERIFIED → HUMAN_APPROVED → MERGING → MERGED → DONE

각 transition entry에 `meta={"reconciled": True}` 표시. `_compute_checksum`은 silent_corruption_guard 호환.

### 6. silent_corruption_guard 친화 보강

현재 `verify_done_preconditions(pr, repo)`는 PR ancestry 검증을 그대로 사용. reconcile에서 직접 호출해서 (1)(2) evidence 검증.

### 7. Codex G1 게이트 피드백 반영 (2026-05-07)

Codex가 critical 1건 + high 2건 + medium 2건을 보고. critical은 "reconcile 미구현" — 본 task가 구현하는 것이므로 design-stage 게이트 semantics 한계 (사후 검증). 나머지 4건은 valuable, 모두 반영:

- **high 1 (deadlock 그대로)**: reconcile 신설로 해소. cmd_done이 .g3-fail에 막히는 것은 정상이며, reconcile은 별도 경로로 우회 (state 직접 재구성, cmd_done 호출 안 함).
- **high 2 (dogfooding 검증)**: `taskctl status --machine` 출력에서 (1) `missing != true`, (2) `current_state == "DONE"`, (3) `_checksum` 유효 — 3 조건 모두 검증.
- **medium 1 (audit path 불일치)**: `state-recovery.jsonl` (현 task 회장 audit 경로)에 14필드 schema validator 신설. 기존 `audit_chairman_recovery.py` 재사용 안 함 (경로/필드 분리).
- **medium 2 (.done 포맷 multi-version 호환)**: `.done`은 두 포맷 공존:
  - **task-timer 포맷** (현 task-2472.done): `task_id, team_id, end_time, duration_seconds, qc_result`
  - **taskctl done 포맷** (cmd_done이 emit): `task_id, ts, merge_commit_sha`
  - reconcile validator는 두 포맷 모두 허용 (지원 set). 핵심 필드는 `task_id` + (qc_result==PASS OR merge_commit_sha 존재) 중 하나.

### 8. dogfooding 실행

본 task 머지 직후, task-2472 자체에 reconcile 1차 적용:
```
taskctl reconcile --task-id task-2472 \
  --classification state_orphaned_after_valid_merge \
  --evidence merge-commit=6ec4e0d8a4e4d2dd39fbd13eb19a69d4212faeba \
  --evidence pr=40 \
  --approved-by-chairman \
  --evidence-path memory/orchestration-audit/state-recovery.jsonl
```

→ `.tasks/state/task-2472.json` 정상 생성 + audit append + `taskctl status task-2472` MERGED+DONE 인식.

## 참조

- task-2472.md: hardening spec
- utils/silent_corruption_guard.py: 3 check (mergedAt / mergeCommit.oid / origin ancestry)
- utils/audit_chairman_recovery.py: chairman manual recovery audit (참고 패턴)
- scripts/taskctl.py: build_parser(), _new_state(), _compute_checksum(), _save(), _load(), _transition()
- memory/orchestration-audit/state-recovery.jsonl: 회장 직접 audit 기록 (마지막 줄)

---

## STOP Repair 결정 근거 (2026-05-07 19:24Z, 회장 지시)

### 1. 사고 진단

commit `05d9ea17` ([task-2472+1] CI regex fix)이 `.github/workflows/{guard,ci}.yml`을 수정하면서 다음 위반 동시 발생:
- task-2479가 다루는 P0 surface (`.github/workflows/**`)와 직접 overlap
- 본 task의 `allowed_resources.paths`에 `.github/workflows/**` 미선언 → resource scope 위반
- 회장 명시 룰 "P0 신규 침범 = ESCALATED"

### 2. 제거 방식 선택: branch reset + cherry-pick 4c1e3fb3

3가지 옵션 비교:

| 옵션 | 장점 | 단점 | 선택 |
|---|---|---|---|
| `git revert 05d9ea17` | history 보존 (audit trail) | revert commit이 history에 남아 PR diff에 net 0 commit 2개 잔존 | ❌ |
| `git reset --hard 4c1e3fb3 + push --force-with-lease` | 깔끔하지만 refs 안전성 낮음 | force push가 분산 reset의 위험 (단, 실 환경은 1 dev) | ⚠️ |
| `git reset --hard origin/main + cherry-pick 4c1e3fb3` (선택) | history 깔끔, 본질 commit 1개만, force-with-lease로 안전 | 기존 commit hash 변경 (4c1e3fb3 → e24415f5) | ✅ |

**선택**: 3번. 사유:
- branch가 main에서 분기되어야 하는 본질적 정의에 부합
- 4c1e3fb3의 author/committer 정보 보존 (cherry-pick은 metadata 유지)
- diff history가 본질 변경 1개 commit으로 압축되어 audit/Gemini 리뷰 용이성 향상

### 3. SCQA 보강 의도 (g3 false alert 처리)

g3-fail 사유: `SCQA 패턴 부족: 0개 발견`. 그러나 보고서 시뮬레이션 결과:
- `**S**:`, `**C**:`, `**Q**:`, `## A —` 4개 모두 정규식 매칭 (4/4)
- 보고서 mtime > g3-fail mtime → `false_alert_resolved_by_late_report` 분류 적용 가능

회장 명시 "보고서에 SCQA 섹션 명시 보강" 요구에 따라:
- frontmatter 메타데이터 `scqa_sections: [S, C, Q, A]` 추가
- 별도 `## SCQA 명시 (V-5 게이트 호환)` 섹션 신설
- 듀얼 라벨 패턴 (`**S** (Situation):` 등) 적용으로 두 정규식 모두 매칭
- A 섹션에 본문 `**A** (Answer):` 라벨 추가 (기존 단일 매칭 → 듀얼 매칭)

자동 retry에 의존하지 않음 (회장 지시 준수). finish-task.sh 재호출 시 g3 verifier가 4/4 SCQA 매칭으로 PASS 예상.

### 4. refresh_bot_token.py 진단

- 본 task PR diff에 추가/삭제 0건
- main 히스토리에 git 추적 이력 없음
- → **별도 incident**. task-2472+1 본질 변경에 섞지 않음 (회장 지시 준수)
- 후속: 별도 task로 발행 권장 (systemd timer 50분 주기 — 21:05 KST 다음 trigger 전 복구 권장)

### 5. force push 정당성

회장 STOP 명령 원문 명시: "force push로 PR #42 갱신". `--force-with-lease`로 동시 push 방지 안전 옵션 사용. pre-push guard PASS 확인.
