[HAN-268] Result — Raphael 발송 Spec Gate auto-approval + 회수 메커니즘
Summary
PR #100 머지 완료 (b84c449, fast-forward). Raphael
페르소나가 발송한 [Spec Gate] 브리핑도 Jarvis 자동
검토→[APPROVED]→라벨/리액션/execution 픽업이 동작하며, 사용자 👎 또는
[CANCEL] 코멘트로 회수 가능한 fail-safe 경로 추가. 13 TC +
전체 122 통과, code review clean pass.
완료된 것
코드 변경
| 파일 | 변경 요약 |
|---|---|
bridge.py |
subtype 가드 완화(bot_message 허용) ·
_handle_approval_briefing pending.json hydrate ·
idempotency 가드 · _handle_cancel_comment 신규 · 단계별
회수 분류 · Jarvis 자동 승인 시 사용자 DM 알림 |
spec_gate.py |
handle_reaction thumbsdown 시
approved/implementing 함께 제거 + 단계별
사용자 DM (label_only / processing / done) |
tests/test_approval_handler.py |
7 신규 TC + autouse _isolate_env fixture (env + store
경로 격리) |
.agent/docs/HAN-268.md |
SDD 스펙 (spec-reviewer 통과) |
AC 통과
회수 단계 분류
| Stage | 조건 | 회수 동작 |
|---|---|---|
label_only |
execution_store에 처리 흔적 없음 | 라벨만 제거 |
processing |
execution_store에 worktree 생성됐으나 PR 없음 | 라벨 제거 (워크트리 강제 종료는 별도 이슈) |
done |
execution_store에 pr_url 존재 |
회수 불가 + 사용자 DM에 명시 |
배운 것
Plan 단계 — bundle vs split 판단
사용자가 HAN-268·HAN-168 묶음 검토 요청. 표면 가설(“비-멤버 봇 멘션 무효”)이 유사해 보였으나 코드 surface·트리거 메커니즘·실패 본질이 모두 달랐음: - HAN-268은 Jarvis가 이미 채널 멤버 → 핸들러 로직 문제 - HAN-168은 Asurada가 DM 비멤버 → Slack IM 2인 멤버십 구조 문제
→ premature abstraction 회피: 표면 유사성에 끌려 묶지 말 것. 3번째 유사 케이스 나오면 그때 추상화 검토.
TDD 사이클 + 회귀 baseline 가치
기존 test_approval_handler.py의 6 TC가 회귀 baseline으로
작동. subtype 가드를 not event.get("subtype")에서
subtype in (None, "bot_message")로 변경할 때 안전망 역할.
TC8(test_message_changed_subtype_does_not_call_handler)가
의도치 않은 admission(message edit 이벤트) 방지.
Code review 분류 기준
5-agent code review에서 7건 후보 발견했으나 모두 80점 미만: - 70점: test isolation (functionality 영향 X) - 65점: None 가드 누락 (broad try/except로 dampened) - 60점: per-instance lock race (collision 빈도 moderate) - 50점 이하: docstring drift, 가설 검증, 테스트 inline-guard drift
→ 80점 임계값이 합리적: 50-70대는 follow-up 후보. 머지 차단할 정도는 아님.
사용자 결정 패턴: “전체 자동화 + fail-safe”
“전체 자동화. 밀려오는 작업을 다 파악하기 힘들고, 문제 생기면 그때 수정하는 전략.”
자동화의 위험을 fail-safe 메커니즘으로 덮는 패턴. 단계별 회수 동작(라벨만 / worktree 진행 중 / PR 생성됨)을 명확히 정의해 사용자가 “어디까지 진행됐는지” 파악 후 결정 가능. silent 진행 알림(자동 승인 시 DM)도 같은 맥락.
코드 리뷰 후보 (follow-up)
머지 차단은 아니지만 향후 검토 가치 있는 항목:
_handle_cancel_commentlinear_client is None 명시 가드 (HAN-65 패턴, score 65) — broad try/except로 crash는 막지만 사용자 DM “회수됨”이 false success 신호 전달_classify_recovery_stagein spec_gate.py monkeypatch hook 부재 (score 70) — TC12 fixture가 bridge 측만 patch, spec_gate 측은 real default 파일 읽음 → CI flakiness 위험- spec_gate.py
handle_reactiondocstring drift (score 50) — thumbsdown 동작이auto-discovery 제거만 명시, 실제는approved/implementing+ DM _get_spec_gate_store()싱글톤화 (score 60) — per-instance threading.Lock이 cross-thread 직렬화 안 됨
별도 follow-up 티켓 필요 시 생성. 본 이슈 자체는 Done.
링크
- PR: https://github.com/hangseung/pantheon/pull/100
(merged
b84c449) - Linear: https://linear.app/hangman-lab/issue/HAN-268
- Plan: https://github.com/hangseung/hangman-docs/blob/main/reports/HAN-268-plan.html
- Spec:
.agent/docs/HAN-268.md(main 브랜치) - 분리된 이슈: HAN-168 (Backlog 복귀, 5월 말~6월 초 픽업 예정)