docs(roadmap): 출력 검증 후속 마일스톤을 추가한다

OpenAI-compatible 출력 검증 범위를 syntax gate, runtime integrity filter, LLM judge 정책 스케치로 나눠 후속 작업을 추적하기 위해 추가한다.
This commit is contained in:
leedongmyun 2026-07-12 12:36:23 +09:00
parent aeec784c7b
commit 70c99c17a8
4 changed files with 289 additions and 0 deletions

View file

@ -31,6 +31,18 @@ Ollama serving 경로와 운영 기반이 안정화된 뒤, 단계 호출, tool/
- 경로: [openai-compatible-output-validation-filters](milestones/openai-compatible-output-validation-filters.md)
- 요약: OpenAI-compatible Chat Completions provider stream에서 반복 출력 루프를 감지해 upstream만 중단하고 같은 downstream SSE에 continuation repair를 이어 붙이며, `metadata.scheme` JSON 출력 계약은 buffered `contract_schema` 경로로 검증/재시도한다.
- [계획] OpenAI-compatible Incomplete Tool Call Syntax Gate
- 경로: [openai-compatible-incomplete-tool-call-syntax-gate](milestones/openai-compatible-incomplete-tool-call-syntax-gate.md)
- 요약: terminal provider 응답에서 완성된 tool call 수와 raw/reasoning/content tool-call marker scanner 결과가 불일치하는 케이스를 runtime에서 deterministic하게 판정해 incomplete tool-call syntax로 분류한다.
- [스케치] OpenAI-compatible Runtime Output Integrity Filter
- 경로: [openai-compatible-runtime-output-integrity-filter](milestones/openai-compatible-runtime-output-integrity-filter.md)
- 요약: terminal assistant 응답이 content, valid tool call, 명시 허용 structured/error finish 중 하나를 만족해야 한다는 runtime invariant를 정의하고, empty terminal, reasoning-only, incomplete tool-call syntax 같은 deterministic violation을 공통 filter pipeline과 bounded retry 정책으로 묶는다.
- [스케치] LLM 판별 기반 Missing Tool Call 재시도 Gate
- 경로: [llm-judged-missing-tool-call-retry-gate](milestones/llm-judged-missing-tool-call-retry-gate.md)
- 요약: Pi/dev-corp 같은 tool-bearing 요청에서 provider가 tool 사용 의도를 reasoning했지만 tool call 없이 종료하는 케이스를 LLM judge와 buffered retry 후보로 재검토하고, 정확한 종료/재시도 정책이 정의될 때까지 구현을 잠근다.
- [스케치] 단계 호출과 검증 최적화 MVP
- 경로: [knowledge-tool-validation-optimization](milestones/knowledge-tool-validation-optimization.md)
- 요약: 요청 의도 분석, 실제 작업, 검증/schema 강제, 오류 시 회귀를 단계 호출 실행 모드의 MVP 후보로 스케치한다.

View file

@ -0,0 +1,93 @@
# 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)
- 확인 필요: `구현 잠금 > 결정 필요` 항목

View file

@ -0,0 +1,90 @@
# Milestone: OpenAI-compatible Incomplete Tool Call Syntax Gate
## 위치
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)
## 목표
OpenAI-compatible provider stream이 terminal 상태로 닫혔지만 완성된 tool call과 raw/reasoning/content tool-call marker scanner 결과가 맞지 않는 케이스를 runtime에서 deterministic하게 판정한다.
이 Milestone은 `tools[]``tool_choice` 존재 여부를 필수 증거로 삼지 않고, provider가 tool-call 문법을 시작했거나 완성한 흔적과 Edge가 조립한 `assembled_tool_call_count`의 불일치만 좁게 다룬다.
예: `assembled_tool_call_count=0`인데 `assembled_reasoning="<tool_call|>"`처럼 marker attempt가 남은 terminal 응답은 incomplete tool-call syntax로 분류한다.
## 상태
[계획]
## 승격 조건
- 없음
## 구현 잠금
- 상태: 잠금
- SDD: 불필요
- SDD 문서: 없음
- SDD 사유: 현재 범위는 provider 원문/조립 결과를 비교하는 runtime classification과 관측 필드이며, public API/proto/config schema를 확정 변경하지 않는다. 감지 후 retry/error stream 정책을 확장할 경우 별도 SDD 필요 여부를 재판정한다.
- 잠금 해제 조건: 아래 체크리스트
- [ ] matcher가 의존할 marker grammar와 provider별 적용 범위가 정리되어 있다.
- [ ] gate에 걸린 terminal 응답을 내부 retry로 처리할지 invalid-provider-output으로 처리할지 결정되어 있다.
- [ ] content marker가 이미 downstream으로 흘렀을 때의 처리와 first-byte 전 buffer 필요 여부가 정리되어 있다.
- 결정 필요: 아래 체크리스트
- [ ] 초기 marker set을 Gemma 계열 `<tool_call|>` 중심으로 시작할지, provider별 registry로 시작할지 결정한다.
- [ ] `incomplete_at_eof`, `marker_attempt_count > assembled_tool_call_count`, `complete_marker_count > assembled_tool_call_count` 각각의 action을 결정한다.
- [ ] matched response를 1회 internal retry로 돌릴지, tool-call syntax error로 즉시 닫을지 결정한다.
- [ ] reasoning-only marker와 content marker를 같은 severity로 볼지 결정한다.
- [ ] gate 결과를 Pi/agent client가 볼 수 있는 error/metadata로 노출할지, Edge 로그/observation에만 남길지 결정한다.
## 범위
- OpenAI-compatible Chat Completions provider passthrough/guarded stream의 terminal 응답 검사
- raw provider chunk, assembled content, assembled reasoning에서 tool-call marker attempt/complete/incomplete EOF를 세는 scanner
- `assembled_tool_call_count`와 scanner 결과의 불일치 판정
- `tools[]`, `tool_choice`, "tool이 필요했는가" 의미 판단과 독립적인 malformed/incomplete syntax 분류
- Edge 실행 로그와 smoke evidence에 남길 gate observation 필드
## 기능
### Epic: [syntax-gate] Incomplete Tool Call Syntax Gate
tool call marker가 존재하지만 완성된 tool call로 조립되지 않은 terminal 응답을 runtime에서 deterministic하게 잡는 capability를 묶는다.
- [ ] [marker-scanner] provider별 tool-call marker scanner가 raw/content/reasoning에서 `marker_attempt_count`, `complete_marker_count`, `incomplete_at_eof`를 산출한다.
- [ ] [count-mismatch] terminal 응답에서 `marker_attempt_count > assembled_tool_call_count`, `complete_marker_count > assembled_tool_call_count`, 또는 `incomplete_at_eof=true`이면 incomplete tool-call syntax로 분류한다.
- [ ] [no-tool-choice-dependency] `tools[]` 또는 `tool_choice`가 로그/요청에 없거나 `tool_choice`가 생략된 요청도 marker/count mismatch만으로 판정한다. 명시 `tool_choice=none`인데 marker가 나오면 missing tool-call이 아니라 malformed provider output으로 분류한다.
- [ ] [stream-boundary] reasoning-only marker와 content marker를 구분하고, content marker가 downstream으로 이미 전송될 수 있는 경로에서는 first-byte buffer 또는 invalid-output 처리 경계가 정리되어 있다.
- [ ] [ops-signal] Edge 로그/observation에 `assembled_tool_call_count`, marker scanner count, gate result, provider/model/run id가 남는다.
- [ ] [fixture-tests] `<tool_call|>` 단독 종료, 완성된 marker와 parser count 불일치, 정상 tool call, marker 없는 최종 답변 fixture가 gate 기대값을 검증한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 기능 Task가 아직 충족되지 않았고, gate match 후 action 정책 결정이 남아 있다.
- 검토 항목:
- [ ] fixture test가 marker/count mismatch와 정상 종료를 구분한다.
- [ ] dev-corp Pi 실패 사례와 같은 `assembled_reasoning="<tool_call|>"`, `assembled_tool_call_count=0` 케이스가 gate에 걸린다.
- [ ] gate action 정책과 stream boundary가 잠금 해제 조건과 일치한다.
- agent-ui 상태 반영: 해당 없음
- 리뷰 코멘트: 없음
## 범위 제외
- tool 필요 여부를 의미적으로 판정하는 LLM judge
- `I will edit`, `도구를 호출하겠다` 같은 자연어 의도만 보고 missing tool-call로 판정하는 방식
- `tools[]` 또는 `tool_choice` 존재 여부를 필수 증거로 삼는 gate
- tool schema validation 실패 재시도
- 모델 교체, Pi prompt 변경, provider option 변경
- 무제한 retry 또는 recursive repair loop
## 작업 컨텍스트
- 관련 경로: `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)
- 표준선(선택): 이 gate는 "tool을 써야 했는가"가 아니라 "tool-call 문법을 시작/완성한 흔적과 조립된 tool call 수가 맞는가"만 판단한다.
- 표준선(선택): `tool_choice`가 없으면 `unknown`으로 두고 이 gate의 필수 조건으로 쓰지 않는다.
- 표준선(선택): marker scanner는 regex만으로 시작할 수 있지만, provider별 marker가 늘어나면 작은 state scanner/registry로 승격한다.
- 상위 통합 후보: [OpenAI-compatible Runtime Output Integrity Filter](openai-compatible-runtime-output-integrity-filter.md)
- 선행 작업: [OpenAI-compatible Tool Call Boundary Hardening](../../../archive/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-tool-call-boundary-hardening.md), [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md)
- 후속 작업: [LLM 판별 기반 Missing Tool Call 재시도 Gate](llm-judged-missing-tool-call-retry-gate.md)
- 확인 필요: `구현 잠금 > 결정 필요` 항목

View file

@ -0,0 +1,94 @@
# Milestone: OpenAI-compatible Runtime Output Integrity Filter
## 위치
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)
## 목표
OpenAI-compatible provider 응답에서 절대 정상 완료로 인정하면 안 되는 terminal output 형태를 공통 runtime filter pipeline으로 관리한다.
기본 invariant는 terminal assistant 응답이 user-visible content, valid tool call, 또는 명시적으로 허용된 structured/error finish 중 하나를 반드시 가져야 한다는 것이다.
이 Milestone은 LLM 의미 판단이 아니라 deterministic detector와 bounded retry/action policy를 묶는 상위 설계 스케치이며, 정책이 닫히기 전까지 구현 계획과 코드 구현 대상으로 삼지 않는다.
## 상태
[스케치]
## 승격 조건
- [ ] terminal assistant invariant를 확정한다. 예: content, valid tool call, allowed structured/error finish 중 하나가 없으면 정상 완료가 아니다.
- [ ] detector별 violation taxonomy를 확정한다. 예: `empty_terminal_response`, `reasoning_only_terminal`, `incomplete_tool_call_syntax`, `malformed_tool_call_emit`, `repeat_loop`, `schema_contract_violation`.
- [ ] 각 detector가 반환할 공통 결과 형태를 확정한다. 예: `pass`, `retryable_violation`, `fatal_violation`, `observe_only`.
- [ ] bounded retry 정책을 확정한다. 예: max attempt, same violation 반복 시 fatal, retry 내부 재귀 금지, tool side-effect 이후 retry 금지.
- [ ] streaming boundary를 확정한다. 예: first byte 전 buffer가 필요한 rule, 이미 downstream으로 보낸 content를 되돌릴 수 없는 rule, continuation repair가 가능한 rule.
- [ ] 기존 [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md)와 [OpenAI-compatible Incomplete Tool Call Syntax Gate](openai-compatible-incomplete-tool-call-syntax-gate.md)를 통합할지, 공통 interface만 공유할지 결정한다.
- [ ] OpenAI-compatible stream/retry/error 계약 변경으로 승격할 때 SDD 필요 여부와 후속 구현 Milestone 분리 방식을 결정한다.
## 구현 잠금
- 상태: 잠금
- SDD: 불필요
- SDD 문서: 없음
- SDD 사유: 현재 Milestone은 runtime filter 통합 정책 스케치이며, public API/stream/retry/error 계약 구현으로 승격할 때 SDD 필요 여부를 재판정한다.
- 잠금 해제 조건: 아래 체크리스트
- [ ] 승격 조건의 invariant, detector taxonomy, action policy가 해소되어 있다.
- [ ] detector별 retry 가능 여부와 fatal 처리 기준이 문서화되어 있다.
- [ ] 기존 output validation/filter Milestone과의 중복/통합 경계가 정리되어 있다.
- 결정 필요: 아래 체크리스트
- [ ] "재귀"를 허용하지 않고 bounded retry로만 표현할지 결정한다.
- [ ] `empty_terminal_response``reasoning_only_terminal`을 기본 retryable로 볼지 fatal로 볼지 결정한다.
- [ ] `incomplete_tool_call_syntax`를 retryable로 볼지 invalid-provider-output으로 볼지 결정한다.
- [ ] provider/model/environment별 rule enablement를 config/registry로 둘지 hard invariant로 둘지 결정한다.
- [ ] retry 실패를 client-visible error로 노출할지, provider output error event/metadata/log only로 둘지 결정한다.
## 범위
- OpenAI-compatible Chat Completions provider stream의 terminal response integrity 검사
- deterministic detector pipeline과 detector 결과 taxonomy
- terminal assistant invariant: content, valid tool call, allowed structured/error finish
- empty terminal, reasoning-only terminal, incomplete tool-call syntax, malformed tool-call, repeat-loop, schema-contract detector의 공통 관리 후보
- bounded retry/action policy와 retry loop guard
- Edge 실행 로그와 smoke evidence에 남길 integrity filter observation 필드
## 기능
### Epic: [integrity-filter] Runtime Output Integrity Filter
deterministic output integrity rule을 개별 one-off gate가 아니라 공통 runtime filter pipeline으로 관리하는 산출물을 묶는다.
- [ ] [invariant-catalog] terminal assistant 응답이 정상 완료로 인정되기 위한 최소 invariant와 allowed exception 목록이 정리되어 있다.
- [ ] [detector-contract] detector interface가 입력 observation, 결과 enum, evidence field, retryability, severity를 공통 형태로 반환하도록 정의되어 있다.
- [ ] [detector-set] `empty_terminal_response`, `reasoning_only_terminal`, `incomplete_tool_call_syntax`, `malformed_tool_call_emit`, `repeat_loop`, `schema_contract_violation`의 초기 detector 후보가 정리되어 있다.
- [ ] [action-policy] `retryable_violation`, `fatal_violation`, `observe_only`별 action과 bounded retry 제한, same-violation 반복 처리, side-effect 이후 retry 금지 조건이 정리되어 있다.
- [ ] [stream-boundary] first-byte buffer가 필요한 rule과 streaming passthrough/continuation repair가 가능한 rule이 분리되어 있다.
- [ ] [integration-map] 기존 output validation filter, incomplete tool-call syntax gate, LLM judge gate와의 선후 관계와 중복 제거 방식이 정리되어 있다.
- [ ] [ops-evidence] filter 결과가 model/provider/run id, assembled counts, detector evidence, retry attempt, final action과 함께 로그/observation으로 남는 기준이 정리되어 있다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 스케치 Milestone이며 invariant와 action policy가 아직 확정되지 않았다.
- 검토 항목: 사용자 리뷰 통과, 승격 조건 충족, 후속 구현 Milestone 및 SDD gate 분리 여부
- agent-ui 상태 반영: 해당 없음
- 리뷰 코멘트: 없음
## 범위 제외
- LLM judge를 이용한 tool 필요 여부 의미 판단
- 무제한 재귀 retry 또는 recursive repair loop
- 이미 downstream으로 보낸 content를 되돌리거나 덮어쓰는 방식
- 모델 교체, Pi prompt 변경, provider option 변경
- 개별 detector 구현 코드 작성
- output integrity와 무관한 routing/model selection 정책
## 작업 컨텍스트
- 관련 경로: `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)
- 표준선(선택): 이 filter 계층은 "모델이 의미적으로 tool을 써야 했는가"가 아니라 "terminal output이 runtime invariant를 만족하는가"를 deterministic하게 판단한다.
- 표준선(선택): 재시도는 재귀가 아니라 bounded retry로 표현한다. retry 내부에서 같은 integrity filter가 다시 retry를 중첩 호출하지 않는다.
- 표준선(선택): detector는 독립 모듈로 두고, retry/fatal/observe action은 중앙 policy가 결정한다.
- 선행 작업: [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md), [OpenAI-compatible Incomplete Tool Call Syntax Gate](openai-compatible-incomplete-tool-call-syntax-gate.md)
- 후속 작업: detector별 implementation Milestone 또는 기존 output validation filter Milestone 통합
- 확인 필요: `구현 잠금 > 결정 필요` 항목