# Milestone: [output-03] 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`.
- [ ] detector가 공통 RecoveryPlan Coordinator에 제공할 typed `RecoveryIntent`와 filter별 strategy limit 후보를 확정한다. max attempt, same violation recursion, tool side-effect와 `replace_attempt|continue_stream`별 commit eligibility 실행은 Coordinator 소유로 두고, 모든 strategy는 최초 실행 제외 기본값/절대 상한 3회의 request 전체 recovery hard cap을 함께 소비한다.
- [ ] streaming boundary를 확정한다. [Stream Evidence Gate Core](stream-evidence-gate-core.md)의 first-byte 전 evidence hold, commit, terminal boundary를 공통 mechanics로 사용하고, detector별 first-byte gate/이미 downstream으로 보낸 content의 non-rollback/continuation repair 조건만 결정한다.
- [ ] 기존 [Stream Evidence Gate Core](stream-evidence-gate-core.md), [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md), [OpenAI-compatible Incomplete Tool Call Syntax Gate](openai-compatible-incomplete-tool-call-syntax-gate.md)를 어떻게 소비하는지와 detector policy 중복 제거 방식을 결정한다.
- [ ] 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의 공통 관리 후보
- detector별 decision/RecoveryIntent policy와 공통 RecoveryPlan Coordinator의 strategy budget, 최초 실행 제외 기본값/절대 상한 3회의 request 전체 recovery hard cap/recursion guard 연동
- Edge 실행 로그와 smoke evidence에 남길 integrity filter observation 필드

## 기능

### Epic: [integrity-filter] Integrity Invariants and Detector Contract

terminal invariant, 공통 detector 계약과 초기 detector taxonomy를 묶는다.

- [ ] [invariant-catalog] terminal assistant 응답이 정상 완료로 인정되기 위한 최소 invariant와 allowed exception 목록이 정리되어 있다.
- [ ] [detector-contract] detector가 [Stream Evidence Gate Core](stream-evidence-gate-core.md)의 Go `Filter` interface를 구현하고 동일 immutable `EvidenceBatch`에서 결과 enum, sanitized evidence, retryability, severity와 선택적 typed `RecoveryIntent`를 반환하도록 정의되어 있다. detector는 request mutation, retry loop/counter, submit을 소유하지 않는다.
- [ ] [detector-set] `empty_terminal_response`, `reasoning_only_terminal`, `incomplete_tool_call_syntax`, `malformed_tool_call_emit`, `repeat_loop`, `schema_contract_violation`의 초기 detector 후보가 정리되어 있다.

### Epic: [integrity-enforcement] Integrity Enforcement and Integration

detector 판정을 bounded recovery 정책과 stream 통합·운영 관측으로 연결하는 산출물을 묶는다.

- [ ] [action-policy] `retryable_violation`, `fatal_violation`, `observe_only`별 decision/intent와 priority가 정리되어 있고, strategy별 bounded budget, 최초 실행 제외 기본값/절대 상한 3회의 request 전체 recovery hard cap, same-plan recursion, side-effect 및 strategy별 commit eligibility는 Core Arbiter/RecoveryPlan Coordinator에 위임돼 있다. 전체 cap 소진은 다른 detector/strategy로 우회하지 않는다.
- [ ] [stream-boundary] [Stream Evidence Gate Core](stream-evidence-gate-core.md)의 `rolling_window|terminal_gate|fragment_gate`, response-start staging과 commit mechanics 위에서 각 rule의 hold mode/hard bound, blocking/observe-only failure, stream-open continuation 가능 여부가 분리되어 있다.
- [ ] [integration-map] Stream Evidence Gate Core, 기존 output validation filter, incomplete tool-call syntax gate, LLM judge gate와의 consumer policy 선후 관계와 중복 제거 방식이 정리되어 있다.
- [ ] [ops-evidence] detector의 stable `filter_id`/`rule_id`, assembled counts, sanitized detector evidence, retry attempt, final action이 [Stream Evidence Gate Core](stream-evidence-gate-core.md)의 `FilterObservation` timeline과 model/provider/run id correlation으로 로그/observation에 남는 기준이 정리되어 있다. raw output/prompt/tool args/result은 남기지 않는다.

## 완료 리뷰

- 상태: 없음
- 요청일: 없음
- 완료 근거: 스케치 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하게 판단한다.
- 표준선(선택): detector는 재귀나 retry loop를 실행하지 않고 typed RecoveryIntent만 반환한다. Core Coordinator가 request-local strategy budget, 최초 실행 제외 기본값/절대 상한 3회의 request 전체 recovery hard cap과 same-plan recursion guard를 적용하며 consumer policy는 0~3 범위에서 낮출 수만 있다.
- 표준선(선택): detector는 독립 `Filter` 구현체로 두고 hold/enforcement policy를 Registry에 등록한다. 모든 active outcome을 동일 batch에서 single-flight 병렬 평가한 뒤 Core Arbiter가 단일 action을 결정하며 response staging, buffer/backpressure, commit, rebuild와 dispatch는 Core를 소비한다.
- 표준선(선택): 이 consumer는 `runtime_output_integrity` consumer id와 detector 이름 기반 stable filter/rule id, invariant 의미 판정과 typed intent, sanitized assembled count만 소유하고 consumer/filter/rule id와 count를 Core `FilterObservation`에 제공한다. recovery가 승인되면 Core `RecoveryPlan`과 strategy/request-total cap, bounded ingress snapshot을 사용하며 raw stream buffer, request snapshot/rebuild, retry loop, 공개 오류 사슬 직렬화를 재구현하지 않는다. detector/rebuild 실패는 sanitized `FailureCauseChain`으로 전달하고 endpoint host가 외부 오류 하나만 직렬화한다.
- 선행 작업: [Stream Evidence Gate Core](stream-evidence-gate-core.md), [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 통합
- 확인 필요: `구현 잠금 > 결정 필요` 항목
