From 70c99c17a8131e5268ce0b27583030f250b52c92 Mon Sep 17 00:00:00 2001 From: leedongmyun Date: Sun, 12 Jul 2026 12:36:23 +0900 Subject: [PATCH] =?UTF-8?q?docs(roadmap):=20=EC=B6=9C=EB=A0=A5=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=ED=9B=84=EC=86=8D=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAI-compatible 출력 검증 범위를 syntax gate, runtime integrity filter, LLM judge 정책 스케치로 나눠 후속 작업을 추적하기 위해 추가한다. --- .../PHASE.md | 12 +++ ...llm-judged-missing-tool-call-retry-gate.md | 93 ++++++++++++++++++ ...atible-incomplete-tool-call-syntax-gate.md | 90 ++++++++++++++++++ ...patible-runtime-output-integrity-filter.md | 94 +++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md create mode 100644 agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md create mode 100644 agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md diff --git a/agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md b/agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md index 16a9a93..337c8ba 100644 --- a/agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md +++ b/agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md @@ -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 후보로 스케치한다. diff --git a/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md new file mode 100644 index 0000000..e38c5d6 --- /dev/null +++ b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md @@ -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) +- 확인 필요: `구현 잠금 > 결정 필요` 항목 diff --git a/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md new file mode 100644 index 0000000..8ccd374 --- /dev/null +++ b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md @@ -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=""`처럼 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 계열 `` 중심으로 시작할지, 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] `` 단독 종료, 완성된 marker와 parser count 불일치, 정상 tool call, marker 없는 최종 답변 fixture가 gate 기대값을 검증한다. + +## 완료 리뷰 + +- 상태: 없음 +- 요청일: 없음 +- 완료 근거: 기능 Task가 아직 충족되지 않았고, gate match 후 action 정책 결정이 남아 있다. +- 검토 항목: + - [ ] fixture test가 marker/count mismatch와 정상 종료를 구분한다. + - [ ] dev-corp Pi 실패 사례와 같은 `assembled_reasoning=""`, `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) +- 확인 필요: `구현 잠금 > 결정 필요` 항목 diff --git a/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md new file mode 100644 index 0000000..d8cea1f --- /dev/null +++ b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md @@ -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 통합 +- 확인 필요: `구현 잠금 > 결정 필요` 항목