# Milestone: LLM 판별 기반 Missing Tool Call 재시도 Gate

## 위치

- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)

## 목표

Pi/dev-corp 같은 tool-bearing OpenAI-compatible 요청에서 provider가 tool 사용 의도를 reasoning했지만 실제 tool call 없이 `stop` 또는 빈 응답으로 종료하는 케이스를 어떻게 다룰지 정책으로 정의한다.
runtime-only 패턴 검출만으로는 최종 답변과 missing tool-call을 안정적으로 구분할 수 없으므로, LLM judge와 buffered retry 후보를 재검토한다.
이 스케치는 "언제 멈추지 말아야 하는가"와 "언제 원응답을 그대로 종료로 인정해야 하는가"를 닫는 기준이 정해질 때까지 구현 계획과 코드 구현을 시작하지 않는다.

## 상태

[스케치]

## 승격 조건

- [ ] LLM judge를 호출할 입력 조건을 확정한다. 예: `tools[]` 존재, `tool_choice != none`, native tool call 없음, text tool-call 후보 없음, terminal finish 도달, downstream으로 아직 bytes를 내보내지 않은 buffered 상태.
- [ ] judge 판정 라벨과 action을 확정한다. 예: `final_ok`, `missing_tool_call`, `indeterminate` 각각에 대해 원응답 통과, 내부 재요청, 오류 반환, 관측 로그만 남김 중 무엇을 할지 정의한다.
- [ ] "멈추어선 안 되는 조건"과 "정상 종료로 인정할 조건"을 사용자-visible 답변, 빈 content, reasoning-only stop, malformed tool-call 실패 이후 응답으로 나누어 정의한다.
- [ ] streaming에서 어느 지점까지 buffer하고, buffer 한도/latency 한도 초과 시 fail-open 또는 fail-closed 중 어떤 정책을 적용할지 결정한다.
- [ ] 내부 retry loop의 최대 횟수, corrective prompt 문구, recursive judge 금지, tool side-effect 중복 방지, retry 실패 시 최종 응답 형태를 확정한다.
- [ ] judge timeout, invalid JSON, provider 오류, judge와 deterministic observation 충돌 같은 불확실 케이스의 fallback 정책을 확정한다.
- [ ] OpenAI-compatible API/stream/retry 계약 변경으로 승격할 때 SDD 필요 여부와 후속 구현 Milestone 분리 방식을 결정한다.

## 구현 잠금

- 상태: 잠금
- SDD: 불필요
- SDD 문서: 없음
- SDD 사유: 현재 Milestone은 정책 스케치이며, buffered stream/API/retry 계약 구현으로 승격할 때 SDD 필요 여부를 재판정한다.
- 잠금 해제 조건: 아래 체크리스트
  - [ ] 승격 조건의 종료/재시도 정책 질문이 해소되어 있다.
  - [ ] judge/retry가 적용되는 요청 경계와 제외 경계가 문서화되어 있다.
  - [ ] 구현 Milestone으로 넘길 기능 Task와 SDD gate 필요 여부가 정리되어 있다.
- 결정 필요: 아래 체크리스트
  - [ ] LLM judge를 blocking gate로 둘지 advisory signal로만 둘지 결정한다.
  - [ ] 현재 모델/provider 제약 안에서 judge 호출을 구성할지, 별도 judge route가 준비될 때까지 구현을 잠글지 결정한다.
  - [ ] `indeterminate` 판정을 원응답 통과, 사용자-visible 오류, 내부 retry 중 어느 쪽으로 처리할지 결정한다.
  - [ ] streaming UX를 위해 buffered validation을 허용할 요청 범위와 latency budget을 결정한다.
  - [ ] retry 실패를 Pi/agent client가 구분할 수 있게 어떤 error/metadata/로그로 노출할지 결정한다.
  - [ ] 이 gate를 dev-corp/Pi smoke 전용 opt-in으로 시작할지, model group/provider policy로 확장할지 결정한다.

## 범위

- OpenAI-compatible `/v1/chat/completions` provider route 중 `tools[]` 또는 tool-capable client 요청
- provider 응답이 terminal 상태로 끝났지만 native tool call이 없고, content가 비었거나 reasoning에 tool 사용 의도가 남은 케이스
- LLM judge 입력/출력 계약, 판정 라벨, timeout/오류/fallback 정책 후보
- downstream으로 첫 content/SSE를 보내기 전 buffer하는 validation path와 내부 재요청 후보
- model, IOP, Pi 중 어느 레이어의 종료인지 사후 관측할 수 있는 로그/metadata 후보

## 기능

### Epic: [missing-tool-gate] Missing Tool Call Gate Policy

tool이 필요한지 runtime만으로 확정할 수 없는 종료 응답을 LLM judge와 bounded retry 후보로 다루기 위한 정책 산출물을 묶는다.

- [ ] [case-taxonomy] 정상 최종 답변, reasoning-only stop, 빈 content stop, malformed tool-call 이후 무툴 종료, 반복 출력 중단 이후 응답을 구분하는 케이스 표가 작성되어 있다.
- [ ] [judge-contract] judge 입력 필드와 strict JSON 출력 라벨, confidence 사용 여부, invalid output fallback 후보가 정리되어 있다.
- [ ] [stream-buffer] streaming에서 first byte 전 buffer 기준, buffer 한도, latency 한도, 한도 초과 정책 후보가 정리되어 있다.
- [ ] [retry-loop] 내부 재요청 횟수, corrective prompt, recursive judge 금지, tool side-effect 중복 방지, 최종 실패 응답 후보가 정리되어 있다.
- [ ] [ops-signal] Edge 실행 로그에서 원응답, judge 판정, retry 여부, 최종 종료 원인을 model/iop/pi 레이어로 구분할 관측 필드 후보가 정리되어 있다.
- [ ] [promotion-plan] 정책 확정 후 `[계획]` 구현 Milestone과 SDD gate 필요 여부가 분리되어 있다.

## 완료 리뷰

- 상태: 없음
- 요청일: 없음
- 완료 근거: 스케치 Milestone이며 종료/재시도 정책과 구현 경계가 아직 확정되지 않았다.
- 검토 항목: 사용자 리뷰 통과, 승격 조건 충족, 후속 구현 Milestone 및 SDD gate 분리 여부
- agent-ui 상태 반영: 해당 없음
- 리뷰 코멘트: 없음

## 범위 제외

- 즉시 코드 구현 또는 dev-corp runtime 배포
- 모델 교체, provider 옵션 변경, Pi 설정 강제 변경
- runtime-only 문자열 패턴 검출만으로 tool 필요 여부를 최종 확정하는 방식
- 이미 downstream으로 보낸 SSE/content를 되돌리거나 덮어쓰는 방식
- LLM judge가 tool call을 합성하거나 tool을 대신 실행하는 방식
- 무제한 재시도, recursive judge loop, 모든 답변을 tool-call 필요 응답으로 간주하는 정책

## 작업 컨텍스트

- 관련 경로: `apps/edge/internal/openai`, `apps/edge/internal/service`, `apps/node/internal/adapters/openai_compat`, [openai-compatible-api.md](../../../../agent-contract/outer/openai-compatible-api.md)
- 표준선(선택): runtime은 tool call 부재와 일부 malformed pattern은 확인할 수 있지만, 모든 최종 답변이 tool을 필요로 하는지 여부는 deterministic하게 판정하지 않는다.
- 표준선(선택): LLM judge가 필요하더라도 downstream으로 이미 흘린 bytes는 되돌리지 않는다. gate가 필요하면 first byte 전 buffered validation 경로에서만 적용한다.
- 표준선(선택): retry는 bounded internal retry로 제한하고, loop 보장이 없으면 구현 Milestone으로 승격하지 않는다.
- 선행 작업: [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md)
- 후속 작업: 정책 확정 후 별도 implementation Milestone, [Tool Call 판정 모델 Gate 리뷰](tool-call-validator-model-gate-review.md)
- 확인 필요: `구현 잠금 > 결정 필요` 항목
