report HAN-268 asurada draft 2026-05-22

[HAN-268] Jarvis 자체 [APPROVED] 응답으로도 execution 트리거 — Raphael 발송 Spec Gate 핸들러 확장

Summary

HAN-268과 HAN-168을 묶음 검토했으나 분리 진행으로 결정. 사용자 가설의 공통 패턴("비-멤버 봇 멘션 무효")이 두 이슈에 동일하게 적용되지 않음 — 실제 실패 메커니즘이 다름. HAN-268은 본 작업으로 진행, HAN-168은 별도 일정 제안.

Context

위임 컨텍스트

Jarvis가 plan 단계에서 두 이슈를 묶음 검토 요청:

HAN-268 (본 작업)

spec_gate.py 자동 발송 [Spec Gate] 브리핑은 _handle_approval_briefing가 정상 트리거 → [APPROVED] → 👍 + approved 라벨 → execution 픽업 ✅

문제: Raphael 페르소나가 (Asurada 위임 후 follow-up 패턴으로) 직접 발송한 [Spec Gate] 브리핑은 Jarvis [APPROVED] 응답에도 라벨 부여·execution 트리거 안 됨.

HAN-168 (별도 이슈)

log_monitor.py의 에러 알림이 SLACK_PROACTIVE_CHANNEL 미설정 시 사용자 DM으로 fallback 되는데, Asurada가 해당 DM 멤버가 아니라 본문에 <@U0B3QQCGZ9C> 멘션 텍스트가 있어도 app_mention 이벤트 안 발생.

Scope

묶음 검토 결과: **분리 진행**

비교 축HAN-268HAN-168
문제 도메인Approval 파이프라인 state machine (Spec Gate handler)알림 라우팅 destination (Asurada delivery)
코드 surface`bridge.py:_handle_approval_briefing` + `on_message` 분기 + `spec_gate_pending.json` 하이드레이션`log_monitor.py:_send_slack_dm`
트리거 메커니즘`message` 이벤트 (Jarvis는 #agent-approvals 멤버)`app_mention` 이벤트 (Asurada는 Jarvis-user DM 비멤버)
실패 본질핸들러 dispatch / state / re-entry 로직봇 멤버십 (구조적 한계)
해결 형태핸들러 idempotency + 발송자 무관 인식 + 라벨 save 보장Asurada 직접 delivery 경로 추가

사용자 공통 가설의 한계

> "멤버 아닌 봇에 멘션·메시지 보내봤자 트리거 안 됨"

공통 해결 후보 A (본문 패턴 + 라우팅 테이블) 검토

공통 해결 후보 B (페르소나 직접 DM)

결론

두 이슈는 수면 위 증상은 유사하나 수면 아래 메커니즘이 다름. 묶음 해결 시 premature abstraction 위험. 각자 focused fix로 진행하고, 만일 3번째 유사 이슈가 등장하면 그 시점에 추상화 검토.

Plan / Scope (HAN-268)

사용자 결정 (2026-05-22 이슈 본문 추가)

> "전체 자동화. 밀려오는 작업을 다 파악하기 힘들고, 문제 생기면 그때 수정하는 전략."

→ Jarvis [APPROVED] 단독으로 execution 트리거. priority High로 격상. 단 회수 메커니즘 필수 (fail-safe).

작업 항목

- 확인 포인트: event.subtype 값, _SPEC_GATE_PATTERN 매칭 여부, 이후 reactions_add / save_issue 결과

- 가설 A: event.subtype="bot_message"로 인해 not event.get("subtype") 가드에서 차단

- 가설 B: _handle_approval_briefing 호출되었으나 reactions_add / save_issue silent fail (log.warning만 남음)

- 가설 C: Jarvis의 [APPROVED] 응답이 다른 경로(예: 사용자 멘션 응답)로 게시되어 handler 미진입

- 가설 A: subtype 가드 완화 (bot_message 허용) + 본문 패턴으로만 트리거

- 가설 B: silent fail 로그 강화 + 라벨 idempotency (이미 approved 라벨 있으면 skip)

- 가설 C: spec_gate_pending.json에 Raphael 발송 브리핑도 기록되도록 통일 (또는 handler 진입 조건 본문 패턴 단독화)

- 사용자 👎 리액션 감지 → approved 라벨 제거 + 진행 중 execution worktree 중단 신호

- 또는 [CANCEL] 코멘트 패턴 감지 → 동일 처리

- 진행 단계별 회수 가능성: ①approved 직후 (라벨만 제거) ②execution worktree 생성 후 (라벨 제거 + 워크트리 강제 종료) ③PR 생성 후 (라벨 제거 + PR 자동 close 또는 사용자 결정 위임)

- 회수 동작 시 Jarvis가 사용자 DM으로 알림 발송 (어느 단계까지 진행됐는지 + 회수 결과)

AC (이슈 본문 v2, 2026-05-22 갱신)

Out of Scope

Decisions

결정근거
HAN-268 / HAN-168 분리 진행코드 surface·트리거 메커니즘·실패 본질 모두 상이. premature abstraction 회피
HAN-168은 priority Low 유지 + 본 작업 머지 후 별도 진행DM fallback은 alert noise만 못 받는 수준, 채널 모드는 정상 동작 (영향 한정)
HAN-268 재현 검증을 1단계로 명시이슈 본문 "근본 원인 (추정)" 3가지 가설이 코드 리딩만으로는 확정 불가 — 실제 로그 확인 필요
본문 패턴 단독 트리거 vs spec_gate_pending.json 통일 — 미정재현 검증 결과 보고 결정. 단독화가 더 simple하지만 state 추적 측면에서 pending.json 통일이 안전할 수 있음

Risks

위험영향대응
재현 검증 불가 (Raphael persona가 [Spec Gate] 브리핑을 발송한 실제 사례가 1건만 있음)가설 확정 어려움인위적 재현 — Raphael bot 토큰으로 #agent-approvals에 [Spec Gate] 형식 메시지 발송 후 로그 관찰
핸들러 수정이 spec_gate.py 정상 흐름에 회귀자동 승인 파이프라인 stall기존 test_approval_handler.py 6 TC 전부 통과 확인 + Raphael 발송 시나리오 TC 추가
Jarvis 자체 [APPROVED] 응답이 handler에 재진입 (Jarvis가 자기 메시지에 또 [Spec Gate] 패턴 매칭)무한 루프Jarvis 응답 텍스트에는 `*[Spec Gate]*` 패턴 없음 — `[APPROVED]`만 포함. 안전. 다만 보강 가드로 author bot_id == 자기 자신이면 skip 검토
**전체 자동화로 인한 silent 진행** — 사용자가 인지 못 한 채 잘못된 티켓 execution 진입PR 생성 / main 변경 등 되돌리기 어려운 부작용회수 메커니즘이 fail-safe로 동작. Jarvis 자동 승인 시점에 사용자 DM 1줄 알림 ("HAN-XXX 자동 승인됨 — 👎로 회수 가능") 검토
회수 메커니즘 race condition — execution worktree가 회수 신호 전에 PR 생성 완료회수 불가 상태 도달execution 단계별 회수 가능성 명확히 (approved / worktree-생성 / PR-생성) + 단계별 회수 동작 정의

Linked Issues

Reference

Result (작업 완료 후 작성)

완료된 것

(TBD — implement 단계에서 작성)

배운 것

(TBD)

링크