fix(bridge): v0.3.12 approval state management — sawRunningAfterPending gate + approval-flow.md system doc

- processResponseFile: set sawRunningAfterPending=true instead of removing resets
  (prevents infinite pending loop AND known-issues L479 auto_resolve regression)
- Hoist sawRunningAfterPending to module level for cross-function access
- Add recentPendingSteps memory dedup Map (60s TTL) for file-deletion resilience
- Create docs/approval-flow.md: complete system flow guide with state diagram
- Update known-issues.md: 2 new entries (state reset fix, memory dedup)
This commit is contained in:
Variet Worker
2026-03-16 11:11:50 +09:00
parent 37c0aae41c
commit 2d9fe964f6
7 changed files with 308 additions and 10 deletions

View File

@@ -526,3 +526,17 @@
- **해결**: 나노단위 전체 Flow 추적으로 교차 검증 후 진짜 결함만 추림 (P2 3건, P3 2건)
- **주의**: **코드 감사 시 반드시 producer→transport→consumer→side effects 전체 경로를 추적. 단편적 로컬 분석으로 위험도를 과장하지 말 것**
### [2026-03-16] processResponseFile 상태 리셋 — 무한 루프 vs auto_resolve 회귀
- **증상**: (v0.3.11) Discord 승인 후 같은 step에 대해 pending이 반복 생성 → 무한 auto-approve 루프
- **원인**: processResponseFile이 `lastPendingStepIndex = -1` + `stallProbed = false`로 무조건 리셋 → step_probe가 같은 WAITING step을 새 step으로 착각 → pending 재생성 → 루프
- **1차 시도 실패**: 리셋 2줄을 완전 제거 → 무한 루프 해소, BUT **L479 회귀** (sawRunningAfterPending이 false 유지 → Discord 승인 후 AG 진행 시 auto_resolve 중복 알림 발생)
- **올바른 해결 (v0.3.12)**: `sawRunningAfterPending = true`만 설정. lastPendingStepIndex와 stallProbed는 유지(dedup 보호), sawRunningAfterPending=true로 auto_resolve gate 닫기. 3개 변수 모두 delta>0에서 자연 리셋
- **주의**: processResponseFile의 상태 리셋은 **sawRunningAfterPending = true만 설정**. lastPendingStepIndex와 stallProbed를 건드리려면 반드시 `docs/approval-flow.md`의 상태 전이 다이어그램을 확인하고, known-issues L479 회귀 및 무한 루프 시나리오를 검증할 것. 자세한 Flow는 `docs/approval-flow.md` 참조
### [2026-03-16] recentPendingSteps 메모리 dedup — pending 파일 삭제 후 재생성 방지
- **증상**: Bot/Collector가 pending 파일을 삭제 → 파일 기반 dedup 통과 → 같은 step_index로 새 pending 생성
- **원인**: writePendingApproval()의 dedup이 파일 존재 여부에만 의존. write_response()가 pending 삭제 → dedup 무효화
- **해결**: `recentPendingSteps` Map (TTL 60초) 추가. `${conversationId}:${stepIndex}`를 키로 사용. 파일 삭제 후에도 메모리에서 차단. delta>0에서 해당 세션 항목 클리어
- **주의**: DOM observer HTTP `/pending` 경로(L738-812)는 `writePendingApproval()`을 우회하므로 이 메모리 dedup 미적용. "Run" 필터(L757)와 file_permission dedup(L786-800)이 대신 방어