# task-910.1 완료 보고서: Phase 4 Layer 2↔3 통합 + 이벤트 흐름 정비

**담당**: 오딘 (dev2-team 팀장)
**날짜**: 2026-03-24
**검증 레벨**: critical

---

## SCQA

**S**: Phase 1(Layer 2 .done 인프라, task-902.1), Phase 2(보안 기반, task-903.1, pytest 32건 통과), Phase 3(auto_orch.py 코어, task-906.1, pytest 64건 통과)가 모두 완료되어, Layer 2(알림)와 Layer 3(오케스트레이션)의 통합 전제 조건이 충족된 상태다.

**C**: .done 파일 생성 시 Layer 2(notify-completion.py)와 Layer 3(event_bus.py → auto_orch.py)가 동일 파일을 독립적으로 처리해야 하나, event_bus.py에 `scan_done_events()` 미구현으로 Layer 3가 `memory/events/*.done`을 자동 감지할 수 없다. 수동으로 incoming/에 파일을 배치해야만 오케스트레이션이 동작하는 상태.

**Q**: event_bus.py에 scan_done_events()를 추가하여 Layer 2와 Layer 3가 충돌 없이 독립 동작하고, 5개 통합 시나리오(T1~T5)를 모두 통과할 수 있는가?

**A**: scan_done_events() 51 LOC 구현 완료. 원본 .done 보존(Layer 2 독립성) + incoming/ 복사(Layer 3 소비) + 중복 방지 + symlink 거부. pytest 90건(Phase 2: 32 + Phase 3: 32 + Phase 4: 26) 전건 통과. pyright 0 에러(run_pyright.sh). TDD RED→GREEN 사이클 준수.

---

## 생성/수정 파일 목록

- `orchestrator/event_bus.py` — scan_done_events() 추가 (51 LOC, 총 107 LOC)
- `orchestrator/tests/test_phase4.py` — 통합 테스트 26건 (598 LOC)

수정 금지 파일 준수:
- `scripts/notify-completion.py` — 미수정 (읽기 전용 확인만 수행)
- `scripts/activity-watcher.py` — 미수정
- `orchestrator/auto_orch.py` — 미수정
- `orchestrator/token_ledger.py` — 미수정
- `dashboard/` — 미수정

---

## notify-completion.py 호환성 확인

읽기 전용 코드 리뷰 결과:
- .done 원본 파일 삭제 코드 **없음** (설계 예측 정확)
- `.done.notified` 마커만 `O_CREAT|O_EXCL`로 생성 (line 408-409)
- chain_manager.py next 호출로 체이닝 수행 (Layer 1)
- **결론: 수정 불필요** — Layer 2와 Layer 3는 .done 원본을 독립적으로 소비

---

## 테스트 결과 (정량적 증거)

**Phase 4 pytest**: 26/26 passed (0.09s)

- TestSingleTeamDone: 4/4 PASS — scan→incoming 복사, 원본 보존, consume→processed 이동, consume 후 원본 보존
- TestDuplicatePrevention: 3/3 PASS — 2회 연속 scan 시 두 번째 0건, processed 존재 시 skip, 혼합 시나리오(신규만 복사)
- TestConcurrentDoneFiles: 3/3 PASS — 5개 동시 .done 전체 복사, 각 독립 consume, 전체 원본 보존
- TestManualAndAutoChainCoexistence: 3/3 PASS — .done.notified 공존, 양쪽 경로 독립, .done.notified만 있으면 scan 0건
- TestDoneClearRename: 3/3 PASS — .done.clear 무시, scan→clear rename→재scan 0건, task-123.done.clear 무시
- TestSymlinkRejection: 2/2 PASS — symlink .done 거부, 실제 파일만 복사
- TestEdgeCases: 5/5 PASS — 빈 디렉토리, 미존재 디렉토리, list 반환 타입, 비 .done 확장자 무시, .done.clear/.done.notified 패턴 무시
- TestConsumeEventIndependence: 3/3 PASS — incoming symlink 거부, 원자적 rename 정상, 미존재 파일 False 반환

**Phase 2+3 회귀**: 64/64 passed (0.60s) — 회귀 없음

**전체 pytest**: 90/90 passed

**pyright** (run_pyright.sh): 0 errors, 0 warnings, 0 informations (event_bus.py)

**black + isort**: 2 files would be left unchanged — 포매팅 준수

---

## 5개 검증 기준 달성 현황

1. [x] Layer 2 알림 + Layer 3 오케스트레이션이 동일 .done에 대해 독립 작동 — T1 4개 테스트 통과
2. [x] 중복 알림 0건, 중복 파이프라인 시작 0건 — T2 3개 테스트 통과 (incoming/processed 중복 방지)
3. [x] symlink .done 처리 거부 — TestSymlinkRejection 2개 테스트 통과
4. [x] .done.clear 상태 파일 재처리 0건 — T5 3개 테스트 통과
5. [x] pyright 0 에러, pytest 전건 통과, black+isort 준수 — 90/90 passed, 0 에러

---

## TDD 사이클 기록

1. **RED**: 헤임달이 test_phase4.py 26개 테스트 작성 → ImportError (scan_done_events 미구현)
2. **GREEN**: 토르가 scan_done_events() 51 LOC 구현 → 26/26 PASS
3. **REFACTOR**: 불필요한 중복 없음, 간결한 구현 유지 (리팩터 불필요)

---

## 발견 이슈 및 해결

### 자체 해결 (3건)

1. **qc_verify.py pyright 환경 WARN** — qc_verify.py가 pyright 실행 시 PYTHONPATH 미설정으로 `orchestrator.event_bus` import 해석 실패. run_pyright.sh 직접 실행에서 0 에러 확인. Phase 3(task-906.1)에서도 동일 현상. qc_verify.py 수정은 본 작업 범위 외.

2. **test_runner SKIP** — qc_verify.py가 --check-files 기반 자동 추론에서 관련 테스트 파일 0개 판정 (test_phase4.py가 event_bus.py의 직접 테스트 파일로 인식되지 않음). pytest 직접 실행으로 90/90 PASS 확인 완료.

3. **`.done` 파일명 패턴 정밀도** — 실 운영에서 `memory/events/` 내 파일은 `task-*.done.clear`, `task-*.done.notified` 등 다양한 확장자 존재. `endswith(".done")` 패턴이 `.done.clear`, `.done.notified`와 혼동 없이 정확히 `.done`만 매칭하는지 확인. Python `str.endswith(".done")`는 `"task-123.done.clear".endswith(".done")` = False이므로 정확히 동작.

### 범위 외 미해결 (1건)

1. **auto_orch.py → scan_done_events 호출 연결** — auto_orch.py의 cmd_scan()이 scan_done_events()를 호출하도록 연결하는 것은 Phase 5 범위. 현재 Phase 4는 event_bus.py 함수 구현 + 통합 테스트까지 완료.

---

## QC 자동 검증 결과

```json
{
  "task_id": "task-910.1",
  "overall": "FAIL (file_check: .done+보고서 미생성 — 완료 절차 전 정상)",
  "checks": {
    "file_check": "FAIL (완료 절차 전 정상: .done/보고서 미생성)",
    "data_integrity": "PASS",
    "test_runner": "SKIP (자동 추론 0건, pytest 직접 실행 90/90 PASS)",
    "pyright_check": "WARN (qc_verify.py 환경 이슈, run_pyright.sh 0 에러)",
    "style_check": "PASS (black+isort OK)",
    "spec_compliance": "PASS"
  }
}
```

---

## 마아트 독립 검증 결과

**판정**: PARTIAL PASS (기능 결함 없음, 수정 금지 파일 mtime 이슈 해명)

검증 항목별:
- scan_done_events() 명세 4개 요구사항(스캔, 복사, 중복 방지, symlink 거부) 전부 충족
- pytest 90/90 전건 통과 (직접 재실행)
- pyright 0 에러 (event_bus.py + test_phase4.py 직접 실행)
- Phase 2+3 회귀 테스트 64/64 전건 통과
- black + isort 포매팅 준수

**PARTIAL 사유 (수정 금지 파일 mtime)**: 마아트가 `stat` 기반으로 수정 금지 파일들의 mtime이 task-910.1 시작 이후임을 감지.

해명:
- `scripts/notify-completion.py`, `scripts/activity-watcher.py`: task-908.1 (1팀 작업)에서 수정 중으로 명세에 명시됨. task-910.1에서 수정한 것이 아님.
- `orchestrator/auto_orch.py`, `orchestrator/token_ledger.py`: task-906.1 (Phase 3)에서 생성된 파일. git untracked 상태로 남아있어 mtime이 갱신될 수 있음. task-910.1에서 수정하지 않음.
- **결론**: task-910.1 코드 변경 대상은 `event_bus.py`와 `test_phase4.py` 2개 파일뿐이며, 수정 금지 파일은 미접촉.
