ai-coding-mines목차GitHub

반려는 있는데 감시 큐는 비어 있다 — 큐가 조용히 비는 세 가지 방식

쓰기 API

승인 워크플로를 감시하는 큐 하나에서 사흘 동안 세 가지가 나왔다. 셋 다 예외 없이, 로그 없이, 항목이 관측 밖으로 나간다.

① 카드 제목이 약속한 집합보다 소스 필터가 좁다

대시보드 카드 제목은 "반려 감시"인데, 소스가 감시 큐뿐이었다. 그 큐는 submitted·unknown만 고른다 — rejected를 구조적으로 제외한다. 옆 카드가 "REJECTED 2건"을 찍는 동안 이 카드는 "감시 중인 반려 건이 없습니다"라고 말했다. 화면이 자기 제목을 반박했다.

큐를 넓히지 않았다(감시 = "아직 판정 전"이라는 뜻이 흐려진다). 읽는 함수를 따로 두고 카드가 둘을 합쳐 라벨로 갈라 보여준다.

카드 제목은 계약이다. 필터가 뜻을 좁히면 제목을 좁히거나 소스를 늘린다 — 둘 중 하나는 해야 한다.

② 상태를 확정 필드가 아닌 부수 신호로 판정했다

감시 상태 판정이 comment 유무만 봤다. 그래서 반려가 아닌 메모 한 줄("임시저장 되었습니다", "담당자 배정 완료")이 항목을 rejected로 앉히고 큐 밖으로 밀어냈다.

두 겹이었다. 반려 표기가 하나도 없으면 마지막 comment를 그냥 돌려주는 폴백이 있었고("조용한 누락 방지"가 의도였다), 상태 판정 함수는 확정 상태 필드를 이미 들고 있으면서도 "rejected" if comment else "unknown"으로 텍스트 유무만 봤다.

"사유가 있다"와 "반려다"는 다른 명제다. 조용한 누락을 막으려던 폴백이 반려 아닌 것을 반려로 만들어 더 조용한 누락을 낳았다. 안전장치가 판정 근거로 승격되면 그 자체가 결함이다. 폴백은 제거가 아니라 용도 축소 — 메모는 사람이 화면에서 읽는 용도로만 남기고, 상태는 확정 필드로만 정한다.

반쪽 수리 주의. 판정만 고치면 안 된다 — 큐가 받는 상태 목록에 새 미확정 상태가 없으면 판정이 맞아도 행은 그대로 큐를 떠난다. 판정과 큐 목록은 한 뜻의 이중 구현이라 둘을 묶는 계약을 둔다: 미확정 상태 집합 ⊆ 큐가 받는 상태 집합.

부검이 한 번에 바닥까지 닿지도 않았다 — 처음엔 "이 동작은 옳고 재무장이 없던 게 결함"이라 썼고, 그것도 틀렸다. 한 겹 고치면 그 밑이 보인다.

③ 처방이 관측 상태를 갱신하지 않는다

재제출(승인 재요청) 함수는 마켓에 요청을 보내고 {success: true}만 돌려준다. 대장의 status는 손대지 않는다. 그래서 이미 큐를 떠난 행(rejected)에 처방을 걸면 — 요청은 실제로 나가고 항목은 다시 심사 큐에 들어가지만, 대장은 여전히 rejected다음 회전이 그 항목을 안 본다. 결과를 아무도 확인하지 않는다.

처방을 열심히 실행할수록 관측 밖으로 나간다. 이게 이 결함의 모양이다.

02장 "upsert가 워크플로 상태를 되돌린다"의 정반대다 — 거기선 수집기가 상태를 리셋해서 사람의 조치가 지워졌고, 여기선 조치가 상태를 안 건드려서 감시가 죽는다.

상태를 바꾸는 행위는 관측 상태도 같이 바꿔야 한다. "대장은 마켓이 뭐라 답했나를 적는다"는 원칙은 옳지만, *우리가 다시 물어봤다*는 것도 사실이고 그 사실이 관측 대상 여부를 정한다.

검증

회전마다 한 줄을 찍는다: 큐 잔류 N · 졸업 M · saved a · unknown b · approved c. 어느 상태에 몇 건이 있는지 세지 않으면 셋 중 어느 것도 보이지 않는다. 그리고 순서가 있다 — 판정을 고쳐도 대장이 이미 rejected면 첫 회전엔 안 잡힌다. 재무장으로 되돌린 뒤 다음 회전부터다. 이 순서를 놓치면 "수리했는데 왜 안 보이냐"가 된다.