# task-2472+1 — taskctl reconcile 명령 신설 (state-orphaned 사후 정합화)

- 작업 유형: **production hardening + reconcile command + dogfooding** (drink-your-own-champagne layer 4)
- 작업 레벨: **Lv.3**
- 위임팀: **dev2-team (오딘, opus)** — task-2472 layer 3 후속, 본인이 만든 hardening의 deadlock 해소
- 독립 검증: **마아트 G2/G3**
- Track: **dev_workspace**
- 우선순위: **★★ blocking** — task-2472 state 정합화 차단
- 일시: 2026-05-07
- 선행: task-2472 PR #40 정상 머지 + .done 발행 + state file missing 발견 (state_orphaned_after_valid_merge)
- 후행: 본 task 머지 후 task-2472 자체에 reconcile 1차 적용 (★ dogfooding)
- TTL: **6시간**

## ⚠️ 본 task의 본질 — 회장 명시

> task-2472는 PR #40 정상 머지 + .done valid payload 발행되었으나 `.tasks/state/task-2472.json` 자체가 없는 상태(`state_orphaned_after_valid_merge`)로 끝났다. taskctl이 만든 본질 hardening("state file missing 상태에서 done/merge 금지")이 자기 자신의 사후 ack를 막는 deadlock이 발생.
>
> `taskctl init`으로 새 state 생성 = silent corruption. 따라서 **PR merge + .done evidence가 유효한 작업을 공식 명령으로 재구성하는 `taskctl reconcile` 경로를 신설**한다.

## 0. 배경 — task-2472 state-orphaned evidence

- **PR #40**: state=MERGED, mergedAt=2026-05-07T09:03:14Z, mergeCommit=6ec4e0d8
- **origin/main HEAD**: 6ec4e0d8 (= PR #40 merge commit)
- **ancestry**: PASS
- **`.done`**: valid JSON payload (qc_result: PASS), sha256=adc694fa...
- **`.g3-fail`**: false alert ("report not found", report mtime > g3-fail mtime → false_alert_resolved_by_late_report)
- **`.tasks/state/task-2472.json`**: **missing**
- **audit**: `memory/orchestration-audit/state-recovery.jsonl` 기록 완료 (chairman_authorized=true)

## 1. 필수 구현

### 구현 1 — `taskctl reconcile` 명령 신설

```bash
taskctl reconcile --task-id <id> \
                  --classification <enum> \
                  --evidence merge-commit=<sha> \
                  --evidence pr=<num> \
                  --approved-by-chairman \
                  --evidence-path <path>
```

**classification enum** (회장 명시 보완 1):
- `state_orphaned_after_valid_merge` — PR merge + .done valid + state file missing (현 task-2472)
- `state_corrupted_with_partial_merge` — commit 일부만 머지된 상태
- `state_inconsistent_after_force_push` — history rewrite 후 정합 깨진 상태
- `state_missing_after_taskctl_crash` — taskctl process 비정상 종료

각 classification마다 다른 검증 룰 분기. 추가 케이스 발견 시 enum 확장 + spec 갱신.

### 구현 2 — 검증 루프 (10단계, 회장 명시)

1. GitHub PR state=MERGED 검증 (`gh pr view --json state,mergedAt,mergeCommit`)
2. mergeCommit이 origin/main에 포함 검증 (`git merge-base --is-ancestor`)
3. `.done` payload JSON 유효성 검증 (필수 필드 + qc_result)
4. `.done` sha256 일치 검증 (audit jsonl 대조)
5. `.g3-fail` 분류 (자동 룰, 회장 명시 보완 3 — 아래 §1.3 참조)
6. state 파일을 수동 작성이 아니라 taskctl 명령으로 재구성
7. checksum 생성 (silent_corruption_guard 호환)
8. state-recovery audit JSONL 기록 (필수 필드 14건)
9. reconcile 후 verify-consistency 강제 실행
10. marker ack/archive도 공식 명령 경로에서만 처리

### 구현 3 — `.g3-fail` false alert 자동 분류 룰 (회장 명시 보완 3)

**자동 룰 (사람 판정 X):**
```python
def classify_g3_fail(g3_fail_path, report_path):
    payload = json.loads(g3_fail_path.read_text())
    fail_reasons = payload.get("fail_reasons", [])
    
    # 케이스 1: report not found false alert
    if all("report not found" in r for r in fail_reasons):
        if report_path.exists() and report_path.stat().st_mtime > g3_fail_path.stat().st_mtime:
            return "false_alert_resolved_by_late_report"
    
    # 케이스 2: 다른 케이스는 unresolved (fail-closed)
    return "unresolved"
```

- `false_alert_resolved_by_late_report`만 reconcile 허용
- 그 외 `unresolved` → reject (fail-closed)

### 구현 4 — dogfooding (drink-your-own-champagne layer 4, 회장 명시 보완 2)

**본 task 머지 후 즉시 task-2472 자체에 reconcile 1차 적용:**
```bash
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
```

→ task-2472 state file 정상 재구성 + audit 추가 + `taskctl status task-2472` 정상 동작 검증.

이는 layer 4 메타 검증 — **본 task가 만든 도구로 본 task의 선행 task의 결함을 정합화**.

## 2. 필수 회귀 테스트 (회장 명시 7건 + 보완 2건 = 9건)

1. state file missing + PR merged + valid .done → reconcile 성공
2. state file missing + PR not merged → reject
3. invalid .done (스키마 미준수) → reject
4. .g3-fail unresolved (false alert 룰 불충족) → reject
5. mergeCommit not in origin/main → reject
6. checksum mismatch → reject 또는 approved repair path 요구
7. reconcile audit 필드 검증 (14건 모두 존재)
8. **dogfooding**: task-2472 자체 reconcile 1차 적용 후 `taskctl status task-2472` PASS (보완 2)
9. **classification enum**: 모든 enum 케이스 인식 PASS, 미정의 enum reject (보완 1)

## 3. allowed_resources

```yaml
allowed_resources:
  paths:
    - "scripts/taskctl.py"  # reconcile 서브커맨드 추가
    - "scripts/taskctl/**"
    - "utils/state_repair.py"  # task-2472 모듈 확장
    - "utils/silent_corruption_guard.py"  # reconcile 친화 보강
    - "tests/state_machine/**"
    - "tests/regression/test_taskctl_reconcile*.py"  # 신설
    - "tests/regression/test_g3_fail_classification*.py"  # 신설
    - "memory/orchestration-audit/state-recovery.jsonl"
    - ".tasks/state/task-2472.json"  # ★ dogfooding 시 reconcile 명령으로만 생성
    # 본 task 자체
    - "memory/tasks/task-2472+1*"
    - "memory/reports/task-2472+1*"
    - "memory/plans/tasks/task-2472+1/**"
    - "memory/events/task-2472+1*"
  forbidden_paths:
    - "memory/events/task-2472.*"  # 기존 marker read-only (manual rename 금지)
    - "memory/events/task-2473.*"  # ESCALATED evidence 보존
    - "memory/events/task-2471+1.*"  # 보존
    - "memory/events/task-2471.*"
    - "memory/reports/task-2472.md"  # read-only
    - "scripts/finish-task.sh"  # task-2472 영역 (수정 금지, parser만)
    - "scripts/done-watcher.sh"  # task-2472 영역
    - "memory/specs/allowed_bot_accounts.json"
    - "memory/specs/allowed_approvers.json"
    - "memory/orchestration-audit/admin-override.jsonl"
    - ".env.keys"
    - ".secrets/**"
    - ".gitignore"
  forbidden_actions:
    - "task-2472 .done/.g3-fail 수동 rename/삭제 금지"
    - "task-2472 .done.acked 수동 생성 금지"
    - "taskctl init task-2472로 새 state 생성 금지"
    - "state JSON 수동 작성 금지"
    - "보고서만 수정해서 정합 처리 금지"
    - "admin override 금지"
    - "Gemini gate 우회 금지"
    - "skip-qc-gate 사용 금지"
    - "git push --force 금지"
    - "테스트 없는 reconcile 명령 추가 금지"
  bot_authentication:
    - "BOT_GITHUB_TOKEN .env.keys 자동 로드 (50분 systemd timer 자동 갱신)"
    - "PR author = jeon-jonghyuk-taskctl-bot[bot]"
  merge_policy: "★ task-2472 layer 3 후속 layer 4. 본 task 머지 후 즉시 task-2472 자체 dogfooding reconcile 1차 적용"
  ttl_hours: 6
```

## 4. 완료 조건 (회장 명시 5건 + 보완 4건 = 9건)

1. ✅ task-2472 상태가 공식 reconcile 경로로 복구됨
2. ✅ `taskctl status task-2472` 정상 동작
3. ✅ `.done`/`.g3-fail` 처리 결과가 audit에 남음
4. ✅ 수동 marker 변경 없음 (git diff `memory/events/task-2472.*` 0줄)
5. ✅ regression 9건 PASS
6. ✅ classification enum 4종 인식 PASS (보완 1)
7. ✅ dogfooding: 본 task 머지 후 task-2472 reconcile 1차 적용 PASS (보완 2)
8. ✅ `.g3-fail` 자동 분류 룰 PASS (보완 3)
9. ✅ PR 머지 + origin/main 반영 + DONE 발행

## 5. ESCALATED 조건

- task-2472 marker 수동 변경 → 즉시 reject
- `taskctl init task-2472` 사용 → 즉시 reject
- state JSON 수동 작성 → 즉시 reject
- regression 9건 미충족 → ESCALATED
- dogfooding 미실행 → ESCALATED
- 보고서만으로 완료 → ESCALATED

## 6. 보고서 필수 항목 (`memory/reports/task-2472+1.md`)

1. reconcile 명령 spec + diff
2. classification enum 4종 정의 + 검증 룰
3. `.g3-fail` 자동 분류 룰 + golden dataset
4. dogfooding 결과: task-2472 reconcile 1차 적용 로그
5. `taskctl status task-2472` PASS evidence
6. regression 9건 코드 + 실행 로그
7. audit jsonl 14필드 검증
8. PR merge commit SHA + origin/main ancestry
9. drink-your-own-champagne layer 4 메타 검증

## 7. 위임 완결성 4대 규칙

1. 수신 확인: dispatch 출력
2. 빌드+배포: PR 생성 + CI/Gemini/G3 PASS + merge + main HEAD 갱신
3. 실 E2E: regression 9건 PASS + dogfooding (task-2472 reconcile 1차) PASS
4. 구조 선행 파악: task-2472 본 hardening + state machine + silent_corruption_guard + audit jsonl

## 8. 시스템 청사진

본 task = task-2472 layer 3 후속 layer 4. state-orphaned 정합화 deadlock 해소. 같은 패턴 재발 시 자동 처리 가능.

## 9. dogfooding 메타 검증 (★)

본 task 머지 후 즉시:
```bash
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` 정상 생성, `taskctl status task-2472` MERGED+DONE 상태 정상 인식. 본 task 자체가 만든 도구로 자기 선행 task의 결함 정합화 = layer 4.

## goal_assertions
- `python3 -m pytest tests/regression/test_taskctl_reconcile* tests/regression/test_g3_fail_classification* tests/state_machine/ -v` (9 PASS)
- `taskctl reconcile --task-id task-2472 ...` (PASS, audit jsonl 갱신)
- `taskctl status task-2472` (정상 동작, state=DONE)
- `gh pr view <PR> --json state,mergedAt,mergeCommit` (state=MERGED)
- `git merge-base --is-ancestor <mergeCommit> origin/main` (PASS)
- `git diff <mergeCommit>~..HEAD memory/events/task-2472.*` (0줄, 수동 변경 없음)