chore: sync roadmap, spec, contract updates and stream evidence gate

This commit is contained in:
toki 2026-07-28 06:18:14 +09:00
parent e24207916a
commit 0565d2be66
9 changed files with 192 additions and 60 deletions

View file

@ -81,17 +81,15 @@ Edge는 이 값을 provider tunnel request의 `openai.provider_auth.target_heade
- normalized Chat Completions stream의 런타임 오류는 같은 `type/message` envelope를 SSE `data`로 한 번 쓰고 `[DONE]`으로 종료한다.
- normalized `/v1/responses`는 현재 streaming을 지원하지 않는다. provider-pool raw passthrough stream은 선택된 provider의 status/header/body를 그대로 relay하며 IOP envelope로 감싸지 않는다.
### 계획된 Stream Evidence Gate 오류 확장
### Stream Evidence Gate ingress 및 terminal 오류
Chat Completions와 Responses ingress에는 configured request snapshot 상한이 body 첫 read 전에 적용된다. body 또는 typed semantic view가 상한을 넘거나 rebuild peak 회계가 실패하면 provider admission 없이 HTTP `413`, `error.type="invalid_request_error"` 한 번으로 종료한다. 이 오류의 `message`는 내부 byte 수, snapshot reference, Core 오류 이름을 노출하지 않는다. 기존 public error body는 계속 `error.type``error.message`만 가지며 size/trace/causes 같은 필드를 추가하지 않는다.
위 bounded ingress/size 오류 호환성은 활성 계약이다. 아래 복구 terminal 확장은 전체 Stream Evidence Gate cycle 조립 전까지 구현 목표로 남는다.
위 bounded ingress/size 오류 호환성은 활성 계약이다. `openai.stream_evidence_gate.enabled=true`이면 지원되는 Chat Completions와 streaming provider-tunnel 경로가 [완료된 Stream Evidence Gate Core Milestone](../../agent-roadmap/archive/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)의 request-local runtime을 사용한다. runtime은 response status/header와 opening event를 첫 safe release까지 보류하고, filter 결과를 모두 모은 뒤 release, terminal 또는 bounded recovery 중 하나만 실행한다. 기본값 `false`에서는 기존 compatibility 경로를 유지한다.
[Stream Evidence Gate Core Milestone](../../agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)이 구현되기 전까지 아래 동작은 활성 외부 API 계약이 아닌 구현 목표다.
복구 요청 조립 또는 dispatch가 실패하면 endpoint별 오류 하나만 보낸다. 내부 원인 사슬은 raw stack trace, provider endpoint/body, user prompt, output/reasoning 원문, tool args/result, 인증 정보를 포함하지 않으며 외부 JSON/SSE에 `causes`, `stack`, `trace` 같은 확장 필드로 노출하지 않는다.
반복 복구 안내문은 언어 판별이나 번역용 보조 모델을 호출하지 않고 고정 영어 문구를 사용한다. 이 경로에는 보조 모델 호출 실패 유형을 추가하지 않는다.
복구 요청 조립 또는 dispatch가 실패하면 Stream Evidence Gate 구현이 정한 기존 terminal 오류 분류로 endpoint별 오류 하나만 보낸다. 내부 원인 사슬은 raw stack trace, provider endpoint/body, user prompt, output/reasoning 원문, tool args/result, 인증 정보를 포함하지 않으며 외부 JSON/SSE에 `causes`, `stack`, `trace` 같은 확장 필드로 노출하지 않는다.
Core 활성화만으로 반복, missing tool-call, schema 같은 semantic filter가 자동 활성화되지는 않는다. 현재 production registry는 공통 mechanics와 적용 가능한 request-local tool validation을 제공하며, 추가 semantic filter와 corrective directive는 각 소비 Milestone이 등록한다.
## Responses API

View file

@ -2,8 +2,8 @@
## 위치
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)
- Roadmap: [ROADMAP.md](../../../../ROADMAP.md)
- Phase: [PHASE.md](../../../../phase/knowledge-tool-optimization-extension/PHASE.md)
## 목표
@ -12,7 +12,7 @@ OpenAI-compatible output validation, incomplete tool-call syntax, missing tool-c
## 상태
[진행중]
[완료]
## 구현 잠금
@ -60,27 +60,31 @@ OpenAI-compatible output validation, incomplete tool-call syntax, missing tool-c
선택된 intent를 bounded recovery plan으로 만들고 current attempt 종료부터 lossless request rebuild와 단일 재admission까지의 실행 소유권을 공통화한다.
- [ ] [recovery-coordinator] Arbiter가 선택한 하나의 `RecoveryIntent`를 strategy별 budget, fault recovery의 request 전체 `max_recovery_attempts_total` hard cap, caller cancel, terminal/tool side effect, strategy별 commit eligibility, same-plan re-entry guard로 검증해 `exact_replay|continuation_repair|schema_repair|managed_continuation` 중 하나의 `RecoveryPlan`으로 만든다. fault recovery 전체 cap은 최초 provider 실행을 제외한 exact/schema/provider-error/일반 repair dispatch를 합산하며 기본값이자 MVP 절대 상한은 3회다. provider output-cap terminal의 managed continuation은 오류 recovery가 아니라 progress trajectory로 분류하고, request 시작 시 고정한 attempt cap·context window·reserve·consumer가 고정한 optional caller logical output cap과 Rebuilder가 조립 뒤 측정한 `rebuilt_prompt_tokens`의 다음 allowance가 남을 때만 별도 `ManagedTrajectoryBudget`으로 dispatch한다. assistant prefix는 rebuilt prompt에 포함되므로 누적 output과 이중 계상하지 않는다. fault cap은 strategy cap보다 우선하고 어느 cap이든 소진되면 다른 fault filter/strategy로 우회하지 않고 terminal로 끝낸다. exact/schema는 `transport_uncommitted`에서만 replace-attempt로 실행하고, continuation은 `stream_open`에서도 released safe prefix/cursor를 보존한 continue-stream plan으로 실행할 수 있다. plan 선택 시 Core는 preparer/continuation에 필요한 bounded request-local snapshot과 cursor를 immutable하게 고정한다. 새 dispatch 전에 현재 `AttemptController`의 provider transport ownership만 idempotent cancel/close하고 실패하면 두 provider를 병행하지 않고 terminal로 끝낸다. 선택된 plan이 consumer별 보조 준비를 요구하면 Core는 all-complete/Arbiter와 attempt ownership 종료 뒤 optional `RecoveryPlanPreparer`를 plan/idempotency key당 최대 1회, bounded deadline으로 호출한다. preparer는 Filter 병렬 평가에 참여하거나 provider 선택/retry/fallback을 실행하지 않으며 실패는 dispatch 없이 terminal로 끝난다. recovery budget은 preparer 호출이 아니라 실제 outbound recovery dispatch 직전에만 소비하고 bounded preparation snapshot은 성공·실패·cancel 뒤 release한다. cycle당 plan/dispatch는 하나지만 두 cap에 여유가 있으면 다음 attempt 결과를 새 cycle로 평가한다. 검증: 동시 violation, pre/post-commit strategy matrix, 0/1/3회 policy와 4회 이상 config rejection, strategy cap과 request 전체 cap의 교차 소진, bounded multi-cycle, snapshot-freeze/transport-only abort, abort-before-prepare/dispatch, preparer 단일 호출/deadline/failure-no-budget/snapshot-release, cancel/side-effect/re-entry fixture가 통과한다.
- [ ] [request-rebuilder] transport-agnostic Coordinator가 기본값이자 MVP 절대 상한 16 MiB이며 request 시작 시 immutable하게 고정되는 `max_ingress_snapshot_bytes` 안의 request-local lossless ingress snapshot과 selected directive를 endpoint/family별 `RequestRebuilder`에 전달하고, host `AttemptDispatcher`가 새 admission과 concrete provider/model/auth 계산을 수행한다. host는 `io.ReadAll` 전에 `http.MaxBytesReader` 또는 동등한 limit+1 판정으로 raw body를 제한하며 policy는 16 MiB 이하로만 낮출 수 있다. OpenAI JSON endpoint는 raw body를 canonical lossless representation으로 보존하고, 다른 lossless tree는 byte-preserving round-trip fixture가 있는 codec만 허용한다. `retained_bytes`는 runtime heap 추정치가 아니라 request가 소유한 backing byte/string buffer의 보수적 logical byte 합이며 shared backing은 한 번만 센다. SnapshotBuilder는 필요한 bounded typed semantic view를 더한 직후, RequestRebuilder는 임시 output을 할당하기 전과 후에 current peak를 다시 검사하고 canonical full copy를 둘 이상 유지하지 않는다. raw body가 pre-read gate와 같아도 typed view를 포함한 total retained limit을 넘으면 dispatch 전에 거부한다. ingress limit 초과는 snapshot 생성/provider dispatch 전에 fail-closed하며 filter/로그/cross-request cache에 원문을 노출하지 않고 auth도 저장하지 않는다. rebuilt request도 같은 limit을 다시 확인하고 request 종료/cancel/overflow에서 retained object를 release한다. dispatcher는 actual model/provider/execution path와 normalized event source를 가진 `AttemptBinding`을 반환하며 normalized↔tunnel path 전환도 같은 Core cycle에 연결한다. 검증: caller raw body/unknown field 보존, continuation/schema typed patch, Chat/Responses serializer, auth 비보존, provider/path 전환, pre-read raw body limit-1/limit/limit+1, exact-limit body+typed-view overflow, 16 MiB 초과 config rejection, shared-backing logical peak accounting과 rebuild 전후 overflow/no-dispatch/no-raw-log/release fixture가 통과한다.
- [x] [recovery-coordinator] Arbiter가 선택한 하나의 `RecoveryIntent`를 strategy별 budget, fault recovery의 request 전체 `max_recovery_attempts_total` hard cap, caller cancel, terminal/tool side effect, strategy별 commit eligibility, same-plan re-entry guard로 검증해 `exact_replay|continuation_repair|schema_repair|managed_continuation` 중 하나의 `RecoveryPlan`으로 만든다. fault recovery 전체 cap은 최초 provider 실행을 제외한 exact/schema/provider-error/일반 repair dispatch를 합산하며 기본값이자 MVP 절대 상한은 3회다. provider output-cap terminal의 managed continuation은 오류 recovery가 아니라 progress trajectory로 분류하고, request 시작 시 고정한 attempt cap·context window·reserve·consumer가 고정한 optional caller logical output cap과 Rebuilder가 조립 뒤 측정한 `rebuilt_prompt_tokens`의 다음 allowance가 남을 때만 별도 `ManagedTrajectoryBudget`으로 dispatch한다. assistant prefix는 rebuilt prompt에 포함되므로 누적 output과 이중 계상하지 않는다. fault cap은 strategy cap보다 우선하고 어느 cap이든 소진되면 다른 fault filter/strategy로 우회하지 않고 terminal로 끝낸다. exact/schema는 `transport_uncommitted`에서만 replace-attempt로 실행하고, continuation은 `stream_open`에서도 released safe prefix/cursor를 보존한 continue-stream plan으로 실행할 수 있다. plan 선택 시 Core는 preparer/continuation에 필요한 bounded request-local snapshot과 cursor를 immutable하게 고정한다. 새 dispatch 전에 현재 `AttemptController`의 provider transport ownership만 idempotent cancel/close하고 실패하면 두 provider를 병행하지 않고 terminal로 끝낸다. 선택된 plan이 consumer별 보조 준비를 요구하면 Core는 all-complete/Arbiter와 attempt ownership 종료 뒤 optional `RecoveryPlanPreparer`를 plan/idempotency key당 최대 1회, bounded deadline으로 호출한다. preparer는 Filter 병렬 평가에 참여하거나 provider 선택/retry/fallback을 실행하지 않으며 실패는 dispatch 없이 terminal로 끝난다. recovery budget은 preparer 호출이 아니라 실제 outbound recovery dispatch 직전에만 소비하고 bounded preparation snapshot은 성공·실패·cancel 뒤 release한다. cycle당 plan/dispatch는 하나지만 두 cap에 여유가 있으면 다음 attempt 결과를 새 cycle로 평가한다. 검증: 동시 violation, pre/post-commit strategy matrix, 0/1/3회 policy와 4회 이상 config rejection, strategy cap과 request 전체 cap의 교차 소진, bounded multi-cycle, snapshot-freeze/transport-only abort, abort-before-prepare/dispatch, preparer 단일 호출/deadline/failure-no-budget/snapshot-release, cancel/side-effect/re-entry fixture가 통과한다.
- [x] [request-rebuilder] transport-agnostic Coordinator가 기본값이자 MVP 절대 상한 16 MiB이며 request 시작 시 immutable하게 고정되는 `max_ingress_snapshot_bytes` 안의 request-local lossless ingress snapshot과 selected directive를 endpoint/family별 `RequestRebuilder`에 전달하고, host `AttemptDispatcher`가 새 admission과 concrete provider/model/auth 계산을 수행한다. host는 `io.ReadAll` 전에 `http.MaxBytesReader` 또는 동등한 limit+1 판정으로 raw body를 제한하며 policy는 16 MiB 이하로만 낮출 수 있다. OpenAI JSON endpoint는 raw body를 canonical lossless representation으로 보존하고, 다른 lossless tree는 byte-preserving round-trip fixture가 있는 codec만 허용한다. `retained_bytes`는 runtime heap 추정치가 아니라 request가 소유한 backing byte/string buffer의 보수적 logical byte 합이며 shared backing은 한 번만 센다. SnapshotBuilder는 필요한 bounded typed semantic view를 더한 직후, RequestRebuilder는 임시 output을 할당하기 전과 후에 current peak를 다시 검사하고 canonical full copy를 둘 이상 유지하지 않는다. raw body가 pre-read gate와 같아도 typed view를 포함한 total retained limit을 넘으면 dispatch 전에 거부한다. ingress limit 초과는 snapshot 생성/provider dispatch 전에 fail-closed하며 filter/로그/cross-request cache에 원문을 노출하지 않고 auth도 저장하지 않는다. rebuilt request도 같은 limit을 다시 확인하고 request 종료/cancel/overflow에서 retained object를 release한다. dispatcher는 actual model/provider/execution path와 normalized event source를 가진 `AttemptBinding`을 반환하며 normalized↔tunnel path 전환도 같은 Core cycle에 연결한다. 검증: caller raw body/unknown field 보존, continuation/schema typed patch, Chat/Responses serializer, auth 비보존, provider/path 전환, pre-read raw body limit-1/limit/limit+1, exact-limit body+typed-view overflow, 16 MiB 초과 config rejection, shared-backing logical peak accounting과 rebuild 전후 overflow/no-dispatch/no-raw-log/release fixture가 통과한다.
### Epic: [integration-adoption] Vertical Slice와 Consumer Adoption
공통 mechanics를 실제 host cycle로 연결하고 raw-free 관측과 후속 consumer 문서 계약까지 닫아 중복 구현을 방지한다.
- [ ] [vertical-slice] production semantic filter보다 먼저 model/provider별 on/off 가능한 `NoopFilter`와 test-only `InjectedViolationFilter``request snapshot → host dispatch → staged response-start → Core evidence hold → parallel filters → all-complete Arbiter → RecoveryPlan → abort → optional prepare → rebuild → single re-admission → release` 한 사이클을 얇게 완성한다. 검증: disabled passthrough, enabled pass, eager header/role 없음, injected violation one retry success, optional preparer success/failure, two violation single retry, provider/path switch, filter failure mode, backpressure, retry exhausted terminal fixture가 통과한다.
- [ ] [filter-observation] Core가 filter/coordinator decision마다 기존 request/run/provider/model correlation과 config generation, attempt/epoch, `consumer_id`, `filter_id`, `rule_id`, hold mode, event kind, effective/pending rune, decision/error policy, commit state, terminal reason, plan id/strategy/shared attempt, preparer id/status/deadline outcome, 최대 4개의 sanitized cause code와 consumer-provided sanitized evidence를 하나의 `FilterObservation` timeline event로 emit한다. 저장·보존은 기존 observability sink가 소유한다. preparer input/output와 raw output/prompt/tool args/result/auth 값은 허용하지 않으며 filter가 평가되지 않은 delta마다 observation을 만들지 않는다. 검증: 병렬 filter 시작/완료, response staging, arbitration, release/terminal/recovery/abort/prepare/rebuild/dispatch가 하나의 request timeline에서 stable id, bounded cause와 sanitized fingerprint/count/offset만으로 추적된다.
- [x] [adoption-doc] [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md), [OpenAI-compatible Incomplete Tool Call Syntax Gate](openai-compatible-incomplete-tool-call-syntax-gate.md), [OpenAI-compatible Runtime Output Integrity Filter](openai-compatible-runtime-output-integrity-filter.md), [LLM 판별 기반 Missing Tool Call 재시도 Gate](llm-judged-missing-tool-call-retry-gate.md), [에이전트 작업 루프 오케스트레이션 MVP](../../automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)에 이 Core의 소비 경계, 각자 남는 semantic policy/intent, stable filter id와 `FilterObservation` mapping, 공통 RecoveryPlan 및 bounded `FailureCauseChain`/endpoint별 단일 외부 오류 직렬화 사용을 기록한다. recovery consumer는 strategy/request-total cap을, ingress snapshot consumer는 bounded snapshot을 사용한다. 검증: 각 Milestone이 자신에게 적용되는 Core interface와 limit을 명시하고 raw stream buffer·request snapshot/rebuild·retry loop·공개 오류 사슬 직렬화를 재구현하지 않는다.
- [x] [vertical-slice] production semantic filter보다 먼저 model/provider별 on/off 가능한 `NoopFilter`와 test-only `InjectedViolationFilter``request snapshot → host dispatch → staged response-start → Core evidence hold → parallel filters → all-complete Arbiter → RecoveryPlan → abort → optional prepare → rebuild → single re-admission → release` 한 사이클을 얇게 완성한다. 검증: disabled passthrough, enabled pass, eager header/role 없음, injected violation one retry success, optional preparer success/failure, two violation single retry, provider/path switch, filter failure mode, backpressure, retry exhausted terminal fixture가 통과한다.
- [x] [filter-observation] Core가 filter/coordinator decision마다 기존 request/run/provider/model correlation과 config generation, attempt/epoch, `consumer_id`, `filter_id`, `rule_id`, hold mode, event kind, effective/pending rune, decision/error policy, commit state, terminal reason, plan id/strategy/shared attempt, preparer id/status/deadline outcome, 최대 4개의 sanitized cause code와 consumer-provided sanitized evidence를 하나의 `FilterObservation` timeline event로 emit한다. 저장·보존은 기존 observability sink가 소유한다. preparer input/output와 raw output/prompt/tool args/result/auth 값은 허용하지 않으며 filter가 평가되지 않은 delta마다 observation을 만들지 않는다. 검증: 병렬 filter 시작/완료, response staging, arbitration, release/terminal/recovery/abort/prepare/rebuild/dispatch가 하나의 request timeline에서 stable id, bounded cause와 sanitized fingerprint/count/offset만으로 추적된다.
- [x] [adoption-doc] [OpenAI-compatible 출력 검증 필터](../../../../phase/knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md), [OpenAI-compatible Incomplete Tool Call Syntax Gate](../../../../phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md), [OpenAI-compatible Runtime Output Integrity Filter](../../../../phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md), [LLM 판별 기반 Missing Tool Call 재시도 Gate](../../../../phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md), [에이전트 작업 루프 오케스트레이션 MVP](../../../../phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)에 이 Core의 소비 경계, 각자 남는 semantic policy/intent, stable filter id와 `FilterObservation` mapping, 공통 RecoveryPlan 및 bounded `FailureCauseChain`/endpoint별 단일 외부 오류 직렬화 사용을 기록한다. recovery consumer는 strategy/request-total cap을, ingress snapshot consumer는 bounded snapshot을 사용한다. 검증: 각 Milestone이 자신에게 적용되는 Core interface와 limit을 명시하고 raw stream buffer·request snapshot/rebuild·retry loop·공개 오류 사슬 직렬화를 재구현하지 않는다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 기능 Task가 아직 충족되지 않았다.
- 상태: 통과
- 요청일: 2026-07-28
- 완료 근거:
- 동일 `m-stream-evidence-gate-core` task group의 archive `complete.log` 25개를 대조했고, 미체크 Task 4개는 정확한 Milestone 경로·Task id·`PASS` 완료 근거를 갖는다.
- 현재 구현 파일과 Git 이력에서 recovery 순서·budget, lossless request rebuild, 실제 Edge vertical cycle, raw-free observation correlation을 확인했다.
- `make proto`, 관련 config refresh test와 `go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai ./packages/go/config`가 현재 코드 트리에서 통과했다.
- 현행 구현 스펙 [Stream Evidence Gate](../../../../../agent-spec/runtime/stream-evidence-gate.md), [OpenAI-compatible 입력 표면](../../../../../agent-spec/input/openai-compatible-surface.md), [Provider Pool Config와 Runtime Refresh](../../../../../agent-spec/runtime/provider-pool-config-refresh.md)와 [외부 OpenAI-compatible API 계약](../../../../../agent-contract/outer/openai-compatible-api.md)을 구현에 맞게 동기화했다.
- 검토 항목:
- [ ] 모든 consumer가 동일한 normalized event/release contract를 사용하고 raw parser를 Core에 중복하지 않는다.
- [ ] rolling/terminal/fragment hold, staged response-start, all-filter completion barrier, single-flight backpressure, deterministic single action, idle no-release, strategy별 post-commit eligibility, common RecoveryPlan/rebuild/dispatcher, single terminal sequence와 raw-free `FilterObservation` timeline 검증이 Evidence Map과 일치한다.
- [x] 모든 consumer가 동일한 normalized event/release contract를 사용하고 raw parser를 Core에 중복하지 않는다.
- [x] rolling/terminal/fragment hold, staged response-start, all-filter completion barrier, single-flight backpressure, deterministic single action, idle no-release, strategy별 post-commit eligibility, common RecoveryPlan/rebuild/dispatcher, single terminal sequence와 raw-free `FilterObservation` timeline 검증이 Evidence Map과 일치한다.
- agent-ui 상태 반영: 해당 없음
- 리뷰 코멘트: 없음
- 리뷰 코멘트: 코드레벨 종료 감사에서 blocking 결함이 없었고 계약·현행 스펙 동기화를 완료했다. 큰 이슈나 별도 plan은 필요하지 않다.
## 범위 제외
@ -103,5 +107,5 @@ OpenAI-compatible output validation, incomplete tool-call syntax, missing tool-c
- 표준선(선택): managed provider length continuation은 filter가 provider output-cap terminal을 의미 판정해 `managed_continuation` intent를 낼 때만 Core가 같은 downstream stream의 safe prefix, look-behind, release cursor와 terminal gate ownership을 보존해 진행한다. 이는 exact/schema/오류 repair의 최대 3회 fault cap과 별도의 context-window trajectory이며, 다음 dispatch allowance는 작은 attempt cap과 `remaining_caller_logical_cap(if set)``context_window - rebuilt_prompt_tokens - reserve`의 최소값으로 계산한다. provider attempt cap은 내부 운영 단위이며 caller cap은 논리 요청 전체에 한 번만 적용한다. rebuilt prompt는 original request와 보존한 assistant prefix를 포함하므로 누적 output을 별도 합산하지 않는다. context 여유 소진, caller cancel, complete tool call/side effect, 미완성 fragment 복구 실패에서는 단일 final terminal로 수렴한다. context 여유 또는 caller logical cap 소진에서만 host가 endpoint-native logical `length` terminal과 단일 종료 marker를 한 번 직렬화하며, attempt 중간 terminal은 commit하지 않는다.
- 표준선(선택): `FilterObservation`은 Core가 emit하는 공통 내부 관측 envelope이며, 저장·보존은 기존 observability sink가 소유한다. Core는 기존 request/run/provider/model correlation과 stream lifecycle 필드를 연결하고, consumer는 stable `consumer_id`/`filter_id`/`rule_id`와 fingerprint·count·offset 같은 sanitized evidence만 제공한다. 이는 외부 API field나 raw output 보존 정책을 바꾸지 않는다.
- 선행 작업: 없음
- 후속 작업: [OpenAI-compatible 출력 검증 필터](openai-compatible-output-validation-filters.md), [OpenAI-compatible Incomplete Tool Call Syntax Gate](openai-compatible-incomplete-tool-call-syntax-gate.md), [OpenAI-compatible Runtime Output Integrity Filter](openai-compatible-runtime-output-integrity-filter.md), [LLM 판별 기반 Missing Tool Call 재시도 Gate](llm-judged-missing-tool-call-retry-gate.md), [에이전트 작업 루프 오케스트레이션 MVP](../../automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)
- 후속 작업: [OpenAI-compatible 출력 검증 필터](../../../../phase/knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md), [OpenAI-compatible Incomplete Tool Call Syntax Gate](../../../../phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md), [OpenAI-compatible Runtime Output Integrity Filter](../../../../phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md), [LLM 판별 기반 Missing Tool Call 재시도 Gate](../../../../phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md), [에이전트 작업 루프 오케스트레이션 MVP](../../../../phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)
- 확인 필요: 없음

View file

@ -3,7 +3,7 @@
## 위치
- Milestone: [Milestone 문서](../../../phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)
- Phase: [PHASE.md](../../../phase/knowledge-tool-optimization-extension/PHASE.md)
- Phase: [PHASE.md](../../../../phase/knowledge-tool-optimization-extension/PHASE.md)
## 상태
@ -33,8 +33,8 @@
|------|------|------|
| Roadmap | [Milestone 문서](../../../phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md) | 범위, consumer, 완료 evidence 기준 |
| Code | `packages/go/streamgate`, `packages/go/config`, `apps/edge/internal/openai`, `apps/edge/internal/service`, `apps/node/internal/runtime`, `apps/node/internal/adapters/openai_compat`, `apps/node/internal/adapters/cli` | transport-agnostic Core와 host codec/rebuilder/dispatcher/release sink의 책임 경계 |
| Contract | [openai-compatible-api.md](../../../../agent-contract/outer/openai-compatible-api.md) | OpenAI caller surface는 기존 계약을 유지하고 Core는 내부 normalized event만 소비한다 |
| Config Contract | [edge-config-runtime-refresh.md](../../../../agent-contract/inner/edge-config-runtime-refresh.md) | limit 정책의 실제 config field/default/validation/refresh 분류를 구현할 때 함께 갱신한다. 현재 active 계약에 미구현 field를 선반영하지 않는다. |
| Contract | [openai-compatible-api.md](../../../../../agent-contract/outer/openai-compatible-api.md) | OpenAI caller surface는 기존 계약을 유지하고 Core는 내부 normalized event만 소비한다 |
| Config Contract | [edge-config-runtime-refresh.md](../../../../../agent-contract/inner/edge-config-runtime-refresh.md) | limit 정책의 실제 config field/default/validation/refresh 분류를 구현할 때 함께 갱신한다. 현재 active 계약에 미구현 field를 선반영하지 않는다. |
| User Decision | 현재 사용자 요청 | 기본 500-rune evidence hold, no time-based release, 공통 Core 분리, model/provider별 filter on/off, 동일 immutable evidence batch의 활성 filter 병렬 평가와 all-complete barrier, filter intent를 하나의 공통 RecoveryPlan으로 재조립·재admission하는 Coordinator를 같은 Milestone에 두는 방향이 확정됐다. consumer별 외부 보조 준비는 filter barrier 안이 아니라 plan 선택/current attempt 종료 뒤 optional `RecoveryPlanPreparer`로 직렬화한다. terminal failure는 bounded sanitized 원인 사슬을 내부에 보존하고 endpoint host가 외부 OpenAI-compatible 오류로 한 번만 평탄화한다. cross-request 오류 사건의 중복 집계와 LLM 기반 소스 분석·수정 제안·승인·변경 요청·병합·배포는 Core 밖의 별도 범용 플랫폼으로 프로젝트화한다. |
| Managed Length Decision | 현재 사용자 요청 | provider output-cap terminal은 semantic filter가 판정하고 Core는 same-stream continuation mechanics만 제공한다. managed profile은 작은 provider attempt `max_tokens`로 dispatch하며, 원본 요청과 channel별 assistant prefix를 rebuild한 논리 trajectory는 실제 context window 여유와 reserve, caller가 명시한 경우 logical output cap으로 제한한다. provider attempt cap은 내부 운영값이고 caller cap은 논리 요청 전체에 한 번만 적용한다. 이는 fault recovery 3회 cap과 별도다. |
@ -62,7 +62,7 @@
## Interface Contract
- 계약 원문: [openai-compatible-api.md](../../../../agent-contract/outer/openai-compatible-api.md)
- 계약 원문: [openai-compatible-api.md](../../../../../agent-contract/outer/openai-compatible-api.md)
- 입력:
- `NormalizedEvent`: codec이 생성한 `response_start`, `text_delta`, `reasoning_delta`, `tool_call_fragment`, `terminal`, `provider_error` 중 하나다. `terminal`은 provider terminal reason(예: output-cap `length`)을 raw body 없이 typed metadata로 포함할 수 있다. `response_start`는 status와 host가 allowlist로 정규화한 header metadata를 포함한다. hop-by-hop header와 body 변환 시 무효가 되는 `Content-Length`는 staging/release 대상에서 제외한다. Core는 raw wire bytes나 caller 제품명을 받지 않는다.
- `BaseEventDisposition`: Core가 event lifecycle에서 만드는 `hold`, `release_candidate`, `terminal_success_candidate`, `terminal_error_candidate`다. response-start는 hold, user-facing safe delta는 release candidate, normal terminal은 success terminal candidate, provider error는 error terminal candidate다. filter가 매칭되지 않아도 이 기본 의미는 사라지지 않는다.
@ -89,7 +89,7 @@
- 출력:
- `ReleaseEvent`: filter 통과 safe prefix 또는 허용된 replacement다.
- `CommitState`: `transport_uncommitted`, `stream_open`, `terminal_committed`다. HTTP status/header flush, SSE/agent opening event 또는 첫 body 중 가장 이른 user-visible write가 `stream_open`이다. exact/schema replay는 uncommitted에 한정하고 continuation/replacement는 별도 capability matrix를 따른다.
- `TerminalResult`: terminal event 또는 terminal error를 한 번만 전송한다. terminal error는 선택적 bounded `FailureCauseChain`과 외부 오류의 `type`/`code`/안전한 message template/`param` descriptor를 가진다. Core는 이를 재해석하지 않고 `ReleaseSink`에 전달하며 endpoint codec이 [외부 오류 계약](../../../../agent-contract/outer/openai-compatible-api.md#오류-응답)으로 직렬화한다.
- `TerminalResult`: terminal event 또는 terminal error를 한 번만 전송한다. terminal error는 선택적 bounded `FailureCauseChain`과 외부 오류의 `type`/`code`/안전한 message template/`param` descriptor를 가진다. Core는 이를 재해석하지 않고 `ReleaseSink`에 전달하며 endpoint codec이 [외부 오류 계약](../../../../../agent-contract/outer/openai-compatible-api.md#오류-응답)으로 직렬화한다.
- `ArbitrationResult`: base disposition과 모든 filter outcome을 합성한 `release`, `hold`, `terminal`, `recover`, `replacement` 단일 action이다. hold는 blocking deferred가 hard bound 전일 때만, recover는 eligible intent가 base candidate를 대체할 때만 선택한다. unmatched error는 terminal을 유지하고 같은 epoch에서 action/dispatch를 둘 이상 만들지 않는다.
- `RecoveryPlan`: 선택된 strategy, `replace_attempt|continue_stream` resume mode, contributing filter/rule ids, plan/idempotency key, strategy attempt와 request 전체 recovery attempt, 각 limit, typed directive, optional bounded preparation snapshot reference와 preparer id/status, commit/side-effect eligibility와 continuation cursor를 포함한다. RecoveryPlan Coordinator만 생성하며 preparer 성공 전에는 rebuild/dispatch 가능한 final plan으로 표시하지 않는다. snapshot 원문은 observation에 직렬화하지 않는다.
- `RebuiltRequest`: `RequestRebuilder`가 immutable ingress snapshot과 plan directive로 만든 endpoint별 새 attempt다. 기존 admission 경로가 provider를 다시 선택하고 auth를 재계산한다.
@ -206,6 +206,6 @@
- 표준선: filter interface는 context-aware synchronous pure evaluation 형태로 유지하고 Gate Coordinator가 goroutine fan-out/수집, single-flight backpressure와 cancel/deadline fail policy를 관리한다. 이로써 filter 구현이 concurrency, request mutation, attempt counter, provider admission을 각각 재구현하지 않는다.
- 표준선: 최초 vertical slice는 production semantic detector 대신 model/provider별 on/off 가능한 `NoopFilter`와 test-only `InjectedViolationFilter`로 공통 파이프라인 한 사이클을 먼저 검증한다.
- 표준선: host는 ingress body를 읽기 전에 기본값/절대 상한 16 MiB의 `max_ingress_snapshot_bytes`를 적용한다. OpenAI JSON은 raw body를 canonical source로 하나만 보존하고 Core/Rebuilder가 typed view와 rebuild 임시 output까지 retained byte를 계상한다. limit 초과는 provider dispatch와 recovery budget 소비 전에 fail-closed한다.
- 표준선: limit policy를 실제 config에 구현할 때 [Edge Config And Runtime Refresh Contract](../../../../agent-contract/inner/edge-config-runtime-refresh.md)에 field/default/range와 refresh 분류를 함께 반영한다. 현재 active contract에는 미구현 config field를 선반영하지 않는다.
- 표준선: limit policy를 실제 config에 구현할 때 [Edge Config And Runtime Refresh Contract](../../../../../agent-contract/inner/edge-config-runtime-refresh.md)에 field/default/range와 refresh 분류를 함께 반영한다. 현재 active contract에는 미구현 config field를 선반영하지 않는다.
- 표준선: managed provider-length continuation은 `length` semantic detector를 Core에 넣지 않는다. Core는 terminal staging, safe prefix/look-behind/cursor 보존, current attempt ownership 종료, trajectory allowance 계산, single re-admission과 final terminal만 소유한다. fault recovery의 최대 3회 cap과 managed context-window trajectory는 서로 다른 ledger이며, assistant prefill capability와 endpoint별 rebuild 의미는 consumer/codec이 결정한다.
- 후속 SDD: [OpenAI-compatible 출력 검증 필터 SDD](../openai-compatible-output-validation-filters/SDD.md)
- 후속 SDD: [OpenAI-compatible 출력 검증 필터 SDD](../../../../sdd/knowledge-tool-optimization-extension/openai-compatible-output-validation-filters/SDD.md)

View file

@ -29,8 +29,8 @@ Phase를 가로지르는 실제 다음 작업 선택은 [전역 마일스톤 실
- 경로: [openai-compatible-tool-call-boundary-hardening](../../archive/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-tool-call-boundary-hardening.md)
- 요약: provider-pool/OpenAI-compatible 응답에서 raw text tool-call block, unknown tool name, chat-template sentinel token이 클라이언트 화면으로 새지 않도록 Edge tool-call 경계를 검증/정규화한다.
- [진행중] Stream Evidence Gate Core
- 경로: [stream-evidence-gate-core](milestones/stream-evidence-gate-core.md)
- [완료] Stream Evidence Gate Core
- 경로: [stream-evidence-gate-core](../../archive/phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)
- 요약: codec의 response-start/event를 첫 safe release까지 stage하고 500-rune rolling, bounded terminal/fragment hold, pre-read 기본값/절대 상한 16 MiB raw-canonical ingress snapshot과 request-snapshot 기반 Filter Registry를 제공한다. Gate Coordinator가 single-flight all-complete evaluation/commit을, RecoveryPlan Coordinator와 host adapter가 strategy별 budget과 최초 실행 제외 기본값/절대 상한 3회의 request 전체 cap 아래 abort·optional one-shot plan prepare·lossless rebuild·cycle별 single re-admission을 담당한다.
- [계획] OpenAI-compatible 출력 검증 필터

View file

@ -4,80 +4,77 @@
## 실행 순서
1. [Stream Evidence Gate Core](phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)
staged response-start, rolling/terminal/fragment hold, bounded ingress snapshot, model/provider별 Registry, single-flight all-complete evaluation과 strategy/request-total cap 아래 abort·optional one-shot plan prepare·host rebuild/re-admission을 공통 mechanics로 제공한다.
2. [IOP Agent CLI Runtime](phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)
1. [IOP Agent CLI Runtime](phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)
현재 Python 감시·dispatcher와 Node CLI runtime의 전체 동등성을 단일 Go CLI Provider·AgentTaskManager 및 독립 `iop-agent` binary로 이전한다.
3. [OpenAI-compatible 출력 검증 필터](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md)
2. [OpenAI-compatible 출력 검증 필터](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md)
OpenAI-compatible single-stream 반복과 incoming request history에 누적된 assistant 반복, JSON contract 검증/repair 경로를 안정화한다.
4. [OpenAI-compatible Incomplete Tool Call Syntax Gate](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md)
3. [OpenAI-compatible Incomplete Tool Call Syntax Gate](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md)
terminal provider 응답의 incomplete tool-call syntax를 deterministic하게 판정한다.
5. [OpenAI-compatible Runtime Output Integrity Filter](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md)
4. [OpenAI-compatible Runtime Output Integrity Filter](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md)
terminal output invariant와 공통 filter/retry pipeline을 정의한다.
6. [LLM 판별 기반 Missing Tool Call 재시도 Gate](phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md)
5. [LLM 판별 기반 Missing Tool Call 재시도 Gate](phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md)
tool 사용 의도 누락 케이스를 LLM judge와 buffered retry 후보로 검토한다.
7. [Tool Call 판정 모델 Gate 리뷰](phase/knowledge-tool-optimization-extension/milestones/tool-call-validator-model-gate-review.md)
6. [Tool Call 판정 모델 Gate 리뷰](phase/knowledge-tool-optimization-extension/milestones/tool-call-validator-model-gate-review.md)
schema만으로 어려운 tool-call 후보에 validator 모델을 쓸지 검토한다.
8. [Pi CLI Provider Integration](phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md)
7. [Pi CLI Provider Integration](phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md)
Pi를 Node CLI provider 실행 후보에 추가하고 OpenAI-compatible route smoke로 안정화한다.
9. [CLI Agent Group Grade Routing](phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)
8. [CLI Agent Group Grade Routing](phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)
lane/grade 파일명과 `metadata.agent_group.task_file` 기반 CLI agent group 라우팅 계약을 정리한다.
10. [에이전트 작업 루프 오케스트레이션 MVP](phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)
9. [에이전트 작업 루프 오케스트레이션 MVP](phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)
일반 사용자 요청을 direct/Plan/Milestone으로 분류하고, 사용자 agent의 tool call로 만든 작업 파일을 IOP가 읽어 다음 실행·리뷰·완료 단계까지 연결한다.
11. [Provider 사용량 알림과 운영 표면](phase/automation-runtime-bridge/milestones/provider-usage-notification-operations-surface.md)
10. [Provider 사용량 알림과 운영 표면](phase/automation-runtime-bridge/milestones/provider-usage-notification-operations-surface.md)
공통 runtime의 quota/status/failure event를 소비해 macOS·Desktop·후속 외부 채널에 전달하는 알림과 이력 표면을 스케치한다.
12. [단계 호출과 검증 최적화 MVP](phase/knowledge-tool-optimization-extension/milestones/knowledge-tool-validation-optimization.md)
11. [단계 호출과 검증 최적화 MVP](phase/knowledge-tool-optimization-extension/milestones/knowledge-tool-validation-optimization.md)
planner/generator/verifier 단계 호출과 runtime schema 검증 실행 모드를 스케치한다.
13. [원격 코딩/유지보수 작업 환경](phase/automation-runtime-bridge/milestones/remote-workspace-operations-environment.md)
12. [원격 코딩/유지보수 작업 환경](phase/automation-runtime-bridge/milestones/remote-workspace-operations-environment.md)
workspace-bound execution 기반 원격 코딩/유지보수 운영 경계를 스케치한다.
14. [Personal Local Edge 패키징과 배포 모드 프로파일](phase/personal-edge-packaging-deployment/milestones/personal-local-edge-deployment-profiles.md)
13. [Personal Local Edge 패키징과 배포 모드 프로파일](phase/personal-edge-packaging-deployment/milestones/personal-local-edge-deployment-profiles.md)
personal/server/fleet 배포 모드와 capability gate 경계를 스케치한다.
15. [요청 실행 로그와 Usage Ledger 기반](phase/operational-observability-provider-management/milestones/request-execution-log-usage-ledger-foundation.md)
14. [요청 실행 로그와 Usage Ledger 기반](phase/operational-observability-provider-management/milestones/request-execution-log-usage-ledger-foundation.md)
요청별 provider/model 선택, timing, token, status/error를 구조화된 ledger로 남기는 기반을 스케치한다.
16. [Update Plane 안정 프로토콜](phase/update-plane-self-update-foundation/milestones/update-plane-stable-protocol.md)
15. [Update Plane 안정 프로토콜](phase/update-plane-self-update-foundation/milestones/update-plane-stable-protocol.md)
hello/status, manifest, command, event, recovery 최소 계약을 스케치한다.
17. [Host-local Manager 기반 자체 업데이트](phase/update-plane-self-update-foundation/milestones/host-local-manager-self-update.md)
16. [Host-local Manager 기반 자체 업데이트](phase/update-plane-self-update-foundation/milestones/host-local-manager-self-update.md)
manager/updater의 release staging, 검증, restart, rollback 실행 모델을 정리한다.
18. [Edge/Node 롤아웃과 복구 정책](phase/update-plane-self-update-foundation/milestones/edge-node-rollout-recovery-policy.md)
17. [Edge/Node 롤아웃과 복구 정책](phase/update-plane-self-update-foundation/milestones/edge-node-rollout-recovery-policy.md)
Edge/Node rolling update, 실패/재연결/rollback 보고 정책을 스케치한다.
19. [Provider Runtime 설정과 모델 획득 오케스트레이션](phase/operational-observability-provider-management/milestones/provider-runtime-model-acquisition-orchestration.md)
18. [Provider Runtime 설정과 모델 획득 오케스트레이션](phase/operational-observability-provider-management/milestones/provider-runtime-model-acquisition-orchestration.md)
provider runtime launch/profile, model download/cache/verification 경계를 스케치한다.
20. [Provider-Device-Model Qualification 리포트와 Lifecycle 관리](phase/operational-observability-provider-management/milestones/provider-device-model-qualification-report.md)
19. [Provider-Device-Model Qualification 리포트와 Lifecycle 관리](phase/operational-observability-provider-management/milestones/provider-device-model-qualification-report.md)
provider/device/model별 compatibility, performance, quality, lifecycle 리포트 경계를 정리한다.
21. [Provider 입력 컨텍스트 선택과 축소](phase/knowledge-tool-optimization-extension/milestones/request-context-assembly-optimization.md)
20. [Provider 입력 컨텍스트 선택과 축소](phase/knowledge-tool-optimization-extension/milestones/request-context-assembly-optimization.md)
provider dispatch 전에 무관한 과거 요청-답변 단위를 제거하고, 유지한 답변·tool/search 결과 안에서도 필요한 문단·코드 블록·구간만 남기는 입력 context 최적화를 스케치한다.
22. [장기 기억과 RAG 업데이트 사이클 (2차)](phase/knowledge-tool-optimization-extension/milestones/long-term-memory-rag-second-wave.md)
21. [장기 기억과 RAG 업데이트 사이클 (2차)](phase/knowledge-tool-optimization-extension/milestones/long-term-memory-rag-second-wave.md)
repo 장기 기억, RAG 저장소, update cycle, MCP 기반 context 절약 후보를 스케치한다.
23. [Advisor와 Context Hook 확장 (2차)](phase/knowledge-tool-optimization-extension/milestones/advisor-context-hook-second-wave.md)
22. [Advisor와 Context Hook 확장 (2차)](phase/knowledge-tool-optimization-extension/milestones/advisor-context-hook-second-wave.md)
advisor 역할과 여러 기능을 실행 흐름에 연결하는 Context Hook 경계를 스케치한다.
24. [oto 자동화 스케줄러와 CI-CD 연동 (2차)](phase/automation-runtime-bridge/milestones/oto-automation-scheduler-second-wave.md)
23. [oto 자동화 스케줄러와 CI-CD 연동 (2차)](phase/automation-runtime-bridge/milestones/oto-automation-scheduler-second-wave.md)
oto 기반 자동화, scheduler, CI-CD 연동 후보를 스케치한다.
25. [Flutter Desktop Control UI](phase/automation-runtime-bridge/milestones/flutter-desktop-control-ui.md)
24. [Flutter Desktop Control UI](phase/automation-runtime-bridge/milestones/flutter-desktop-control-ui.md)
`iop-agent` local proto-socket을 소비해 YAML 전체 설정과 project·실행·오류·로그를 관리하는 macOS Flutter 설정·운영 UI를 제공한다.
26. [Unity 3D Desktop Character](phase/automation-runtime-bridge/milestones/unity-3d-desktop-character.md)
25. [Unity 3D Desktop Character](phase/automation-runtime-bridge/milestones/unity-3d-desktop-character.md)
같은 local proto-socket을 독립적으로 소비하고 작업 상태를 투명 배경 3D 캐릭터와 animation으로 표현하는 macOS Unity client를 제공한다.

View file

@ -24,6 +24,7 @@ AI agent가 작업 전에 읽는 지도이기도 하지만, 사람도 "지금
- 실행 경로: Edge와 Node 사이의 등록, 실행, 이벤트, provider raw tunnel, 취소, command 흐름은 `runtime/edge-node-execution`에서 본다.
- 런타임 라우팅/설정: provider-pool, `models[]`, `nodes[].providers[]`, live config refresh는 `runtime/provider-pool-config-refresh`에서 본다.
- 출력 검증 런타임: staged response-start, evidence hold/release, filter arbitration, bounded recovery/rebuild, raw-free observation은 `runtime/stream-evidence-gate`에서 본다.
- 외부 HTTP 입력: OpenAI-compatible 호출, model-driven raw tunnel은 `input/openai-compatible-surface`, A2A JSON-RPC 호출은 `input/a2a-json-rpc-surface`에서 본다.
- 운영 제어: Control Plane, Edge enrollment, fleet/edge status, Flutter Client 상태 소비는 `control/control-plane-operations`에서 본다.
@ -32,6 +33,7 @@ AI agent가 작업 전에 읽는 지도이기도 하지만, 사람도 "지금
| id | 상태 | 언제 읽나 | path | 주요 근거 |
|----|------|-----------|------|-----------|
| `runtime/edge-node-execution` | 부분 | Edge-Node TCP/protobuf transport, Node 등록, run/cancel/command, provider raw tunnel, adapter 실행, Node local run store를 확인할 때 | `agent-spec/runtime/edge-node-execution.md` | `agent-contract/inner/edge-node-runtime-wire.md`, `apps/edge/internal/service/run_submit.go`, `apps/node/internal/node/run_handler.go` |
| `runtime/stream-evidence-gate` | 구현됨 | Stream Evidence Gate의 normalized event, evidence hold/release, filter registry, recovery coordinator, OpenAI request rebuild와 observation을 확인할 때 | `agent-spec/runtime/stream-evidence-gate.md` | `packages/go/streamgate/runtime.go`, `apps/edge/internal/openai/stream_gate_runtime.go`, `agent-contract/outer/openai-compatible-api.md` |
| `runtime/provider-pool-config-refresh` | 부분 | `models[]`, `nodes[].providers[]`, provider-pool dispatch, long-context admission, Edge/Node config refresh를 확인할 때 | `agent-spec/runtime/provider-pool-config-refresh.md` | `agent-contract/inner/edge-config-runtime-refresh.md`, `packages/go/config/provider_types.go`, `apps/edge/internal/configrefresh/classify.go` |
| `input/openai-compatible-surface` | 부분 | `/v1/models`, `/v1/chat/completions`, `/v1/responses`, OpenAI-compatible auth/metadata/workspace/tool handling, model-driven raw tunnel, usage metric, 외부 `model` route를 확인할 때 | `agent-spec/input/openai-compatible-surface.md` | `agent-contract/outer/openai-compatible-api.md`, `apps/edge/internal/openai/chat_handler.go`, `apps/edge/internal/openai/normalized_sse.go`, `apps/edge/internal/openai/usage_metrics.go` |
| `input/a2a-json-rpc-surface` | 부분 | Edge A2A JSON-RPC, `message/send`, `tasks/get`, `tasks/cancel`, A2A task store와 bearer auth를 확인할 때 | `agent-spec/input/a2a-json-rpc-surface.md` | `agent-contract/outer/a2a-json-rpc-api.md`, `apps/edge/internal/input/a2a/server.go`, `apps/edge/internal/input/a2a/task_store.go` |

View file

@ -12,6 +12,12 @@ source_evidence:
- type: code
path: apps/edge/internal/openai/chat_handler.go
notes: Chat Completions request validation, route dispatch, tool/reasoning 정책
- type: code
path: apps/edge/internal/openai/stream_gate_ingress.go
notes: body 첫 read 전 ingress 상한과 request-local snapshot
- type: code
path: apps/edge/internal/openai/stream_gate_runtime.go
notes: runtime-enabled Chat과 provider tunnel response lifecycle
- type: code
path: apps/edge/internal/openai/normalized_sse.go
notes: normalized Chat Completions SSE stream과 terminal event 처리
@ -74,6 +80,7 @@ Edge가 OpenAI-compatible HTTP 요청을 받아 내부 `adapter + target` 실행
| legacy route 변환 | legacy route는 외부 `model`을 route entry의 `adapter`, `target`, `node`, `session_id`, queue policy로 변환한다. |
| metadata/workspace 처리 | `metadata.workspace``RunRequest.workspace`로 분리하고, 일반 metadata는 최대 16개 string key/value만 허용한다. |
| Chat Completions | `/v1/chat/completions`는 non-streaming과 streaming SSE를 지원한다. |
| bounded ingress와 Stream Evidence Gate | Chat/Responses body를 첫 read 전에 최대 16 MiB로 제한한다. `openai.stream_evidence_gate.enabled=true`인 지원 경로는 response-start staging, filter arbitration, bounded recovery와 단일 terminal을 `runtime/stream-evidence-gate`에 위임한다. |
| model-driven response path | request `model`이 가리키는 provider capability가 provider raw tunnel 또는 normalized RunEvent path를 결정한다. caller metadata는 route나 response shape를 선택하지 않는다. |
| provider raw passthrough | `passthrough`는 provider status/header/body bytes를 기존 Edge-Node tunnel로 relay하고 pure response body에 IOP 확장 envelope를 섞지 않는다. |
| provider-native field 보존 | provider raw tunnel route는 `model` served target rewrite와 auth/header 처리 외에 selected provider가 지원하는 OpenAI-compatible 표준 field와 provider extension field를 보존한다. |
@ -88,7 +95,7 @@ Edge가 OpenAI-compatible HTTP 요청을 받아 내부 `adapter + target` 실행
## 범위
- 포함: OpenAI-compatible HTTP auth, request validation, route resolution, metadata/workspace 처리, chat/responses 변환, provider-pool dispatch handoff, tool/reasoning/strict output 처리.
- 포함: OpenAI-compatible HTTP auth, bounded ingress, request validation, route resolution, metadata/workspace 처리, chat/responses 변환, provider-pool dispatch handoff, tool/reasoning/strict output 처리.
- 제외: OpenAI 원문 API 전체 호환, legacy `/v1/completions`, A2A JSON-RPC, Node adapter별 provider HTTP 세부, Control Plane 운영 API.
## 주요 흐름
@ -126,6 +133,7 @@ sequenceDiagram
## 설정/데이터/이벤트
- `configs/edge.yaml``openai` 섹션이 listener, bearer token, legacy adapter/target, model routes, strict output을 제공한다.
- `openai.stream_evidence_gate`는 기본 비활성이고, recovery cap 0..3과 16 MiB 이하 ingress snapshot 상한을 설정한다. 변경은 현재 restart-required다.
- top-level `models[]`가 있으면 OpenAI model list와 provider-pool dispatch에서 legacy route보다 우선한다.
- provider-pool model group은 capacity + priority + availability 기준으로 provider candidate를 먼저 선택하고, 선택된 provider가 OpenAI-compatible 호출 방식을 지원하면 raw tunnel passthrough로 dispatch한다. Ollama/CLI/native provider가 선택되면 normalized `RunRequest` path로 dispatch한다.
- provider capacity와 long-context slot은 model alias별이 아니라 `node_id + provider_id`별로 공유한다. queue pending 상한과 timeout은 Edge root `provider_pool` policy이며, lease 반환·refresh·disconnect/reconnect가 모든 model group waiter를 global enqueue 순서로 재평가한다.
@ -145,6 +153,7 @@ sequenceDiagram
## 검증
- `go test ./apps/edge/internal/openai`
- `go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai ./packages/go/config`
- `go test ./apps/edge/internal/service`
- `go test ./apps/edge/internal/openai -run 'Tunnel|UsageMetrics|ToolValidation|Dispatch|Reasoning|Retry'`
- `rg --fixed-strings "cloud_equivalent_cost" docs/openai-usage-grafana.md`
@ -154,6 +163,7 @@ sequenceDiagram
## 한계와 주의사항
- normalized(non-provider) `/v1/responses`는 non-streaming string input만 지원한다. provider model group route의 `/v1/responses`는 raw passthrough로 streaming과 Codex/unknown field를 그대로 provider에 전달한다.
- Stream Evidence Gate 활성화만으로 반복, missing tool-call, schema 같은 semantic filter가 자동 활성화되지는 않는다. 해당 mechanics와 현재 지원 경로는 `agent-spec/runtime/stream-evidence-gate.md`를 따른다.
- `/v1/completions`는 제공하지 않는다.
- OpenAI-compatible request에 provider/Ollama 전용 root field를 추가하지 않는다.
- workspace는 prompt 본문에 섞지 않고 metadata에서 분리한다.
@ -184,3 +194,4 @@ sequenceDiagram
- 2026-07-14: provider 미보고 reasoning text에 estimated-token counter(`iop_openai_reasoning_estimated_tokens_total`, `estimation_method="chars_div_4"`) 추가와 provider-reported reasoning 우선 기준을 반영.
- 2026-07-18: 저장소 구조 분해 뒤 streaming, provider tunnel, split test의 `source_evidence`를 현재 경로로 동기화.
- 2026-07-22: cross-model provider resource admission, provider-pool 공통 queue policy와 live candidate 소진 시 502 unavailable 의미를 현재 service/OpenAI 구현과 계약 기준으로 동기화.
- 2026-07-28: bounded ingress와 Stream Evidence Gate 활성 경로·한계·검증 포인터를 현재 구현 기준으로 반영.

View file

@ -48,6 +48,9 @@ source_evidence:
- type: test
path: packages/go/config/provider_catalog_validation_config_test.go
notes: provider/model 참조와 validation 검증
- type: test
path: packages/go/config/stream_evidence_gate_config_test.go
notes: Stream Evidence Gate 기본값, recovery cap과 ingress 상한 검증
- type: test
path: apps/edge/internal/node/mapper_test.go
notes: provider-first adapter payload, Seulgivibe alias/provider label 검증
@ -94,6 +97,7 @@ Edge 설정에서 provider-pool이 어떻게 모델 실행 후보를 고르고,
| long-context admission | estimated input token이 threshold 이상이면 `context_class=long`으로 분류하고, provider long slot이 있으면 일반 capacity slot과 함께 점유한다. |
| config refresh dry-run/apply | loopback admin HTTP `POST /refresh`가 candidate config를 dry-run 또는 apply한다. |
| refresh classification | listener, Edge identity, bootstrap path, adapter structural 변경 등은 restart-required로 분류한다. |
| Stream Evidence Gate config | `openai.stream_evidence_gate`는 runtime 활성화, request-total/strategy fault recovery cap과 ingress snapshot 상한을 제공하며 현재 restart-required로 분류된다. |
| mutable apply | 적용 가능한 변경은 Edge `Cfg`, `NodeStore`, service/input model catalog, OpenAI long-context threshold를 copy-on-write로 교체한다. |
| Node config refresh push | 변경이 있으면 Edge가 dispatch-ready Node에 node-specific `NodeConfigRefreshRequest`를 push한다. accepted지만 pending인 Node는 register response config를 적용한 뒤 ready가 될 때까지 push 대상이 아니다. |
| Node registry swap | Node는 refresh payload로 새 adapter registry를 만들고 router registry를 swap한다. old registry stop은 active run이 있으면 drain 이후로 지연한다. |
@ -103,7 +107,7 @@ Edge 설정에서 provider-pool이 어떻게 모델 실행 후보를 고르고,
## 범위
- 포함: Edge config load/default/validation, provider-pool dispatch, queue admission, long-context admission, config refresh classification/apply, Node config refresh payload.
- 포함: Edge config load/default/validation, Stream Evidence Gate 설정, provider-pool dispatch, queue admission, long-context admission, config refresh classification/apply, Node config refresh payload.
- 제외: 개별 adapter의 provider API 호출 세부, OpenAI HTTP request/response shape, Control Plane 원격 config 변경 UX, private credential 관리.
## 주요 흐름
@ -140,6 +144,7 @@ sequenceDiagram
## 설정/데이터/이벤트
- `long_context_threshold_tokens` 기본 예시는 `100000`이고 0 이하 값은 config load에서 거부된다.
- `openai.stream_evidence_gate.enabled` 기본값은 `false`다. request fault recovery는 0..3, strategy cap은 request-total 이하, ingress snapshot은 1..16777216 bytes이며 설정 변경은 restart-required다.
- `provider_pool.max_queue`는 0/생략 시 기본값 `16`, `queue_timeout_ms`는 생략 시 `30000`이고 명시적 0은 timeout 없음이다. canonical root key가 없을 때만 서로 같은 legacy provider queue pair를 승격하며 값이 다르면 load를 거부한다.
- `nodes[].providers[].capacity``long_context_capacity`는 provider resource 속성이고 같은 provider를 공유하는 model alias가 합산 점유한다. `total_context_tokens`는 runtime ledger가 아니라 `context_window_tokens * long_context_capacity` 정적 validation 값이다.
- provider `enabled=false`는 dispatch pool에서 제외하지만 adapter process lifecycle 변경을 의미하지 않는다.
@ -168,6 +173,7 @@ sequenceDiagram
- provider health는 현재 config/provider snapshot 기반이다. 모든 runtime에 대한 active health probe가 완성된 것은 아니다.
- refresh admin API는 operator-local 표면이다. 접근 제어 없이 public interface에 노출하지 않는다.
- Stream Evidence Gate의 request-local lifecycle과 지원 OpenAI 경로는 `agent-spec/runtime/stream-evidence-gate.md`에서 관리한다.
- adapter structural 변경은 contract상 restart-required로 분류된다. Node handler가 registry swap을 지원하더라도 Edge refresh classifier가 허용한 변경만 apply해야 한다.
- no-change apply는 runtime snapshot을 교체하지만 Node push는 생략한다.
- `NodeRuntimeConfig.concurrency`는 legacy metadata이며 provider-pool admission의 node-wide capacity로 쓰지 않는다.
@ -186,3 +192,4 @@ sequenceDiagram
- 2026-07-18: 저장소 구조 분해 뒤 config, provider resolution/admission, split test의 `source_evidence`를 현재 경로로 동기화.
- 2026-07-22: pending accepted connection과 dispatch-ready connection을 구분하고, ready ack 뒤에만 provider candidate 복구·refresh push·queued waiter pump가 일어나는 현재 동작을 반영.
- 2026-07-22: root provider-pool queue policy, cross-model provider lease, global queue 재평가, refresh lease 보존과 connectivity 기반 snapshot 의미를 현재 구현·계약·테스트 기준으로 동기화.
- 2026-07-28: Stream Evidence Gate 설정 기본값·상한·restart-required 분류와 runtime spec 포인터를 반영.

View file

@ -0,0 +1,113 @@
---
spec_doc_type: spec
spec_id: runtime/stream-evidence-gate
status: 구현됨
source_evidence:
- type: contract
path: agent-contract/outer/openai-compatible-api.md
notes: OpenAI-compatible ingress, stream commit와 terminal 오류 계약
- type: contract
path: agent-contract/inner/edge-config-runtime-refresh.md
notes: Stream Evidence Gate 설정과 restart-required 분류 계약
- type: code
path: packages/go/streamgate/runtime.go
notes: request-local event, evaluation, release와 recovery lifecycle
- type: code
path: packages/go/streamgate/recovery_coordinator.go
notes: abort, optional prepare, rebuild, budget consume와 single dispatch 순서
- type: code
path: apps/edge/internal/openai/stream_gate_runtime.go
notes: OpenAI Chat과 provider tunnel host wiring
- type: code
path: apps/edge/internal/openai/openai_request_rebuilder.go
notes: bounded lossless OpenAI request rebuild
- type: test
path: packages/go/streamgate/runtime_test.go
notes: Core lifecycle, recovery와 terminal 검증
- type: test
path: apps/edge/internal/openai/stream_gate_vertical_slice_test.go
notes: Edge 실제 admission과 full-cycle 검증
- type: test
path: apps/edge/internal/openai/filter_observation_sink_test.go
notes: raw-free observation allowlist와 correlation 검증
---
# 스펙: Stream Evidence Gate
## 목적
codec이 정규화한 provider event를 downstream에 쓰기 전에 evidence와 모든 활성 filter 결과를 확인하고, 한 번의 release·terminal·recovery 결정으로 수렴시키는 현재 request-local runtime을 설명한다.
## 기능 목록
| 기능 | 설명 |
|------|------|
| normalized event contract | response-start, text/reasoning, tool-call, terminal, provider-error event와 base disposition을 transport와 분리한다. |
| evidence hold | 기본 500 Unicode rune rolling window와 bounded terminal/fragment gate를 사용하며 안전한 prefix만 release한다. |
| staged commit | status/header/opening event를 첫 safe release까지 보류하고 `transport_uncommitted`, `stream_open`, `terminal_committed` 상태에서 terminal을 한 번만 commit한다. |
| filter registry와 arbitration | request 시작의 registry/config generation을 고정하고 attempt별 active filter를 다시 해석한 뒤 병렬 결과를 모두 모아 deterministic action 하나를 선택한다. |
| bounded recovery | exact replay, continuation repair, schema repair는 request-total·strategy별 fault cap 안에서 실행하며 managed continuation은 별도 trajectory budget을 사용한다. |
| request rebuild | 기본값이자 절대 상한 16 MiB의 ingress snapshot에서 OpenAI JSON unknown field를 보존하고 필요한 typed subtree만 bounded patch한다. |
| host re-admission | 현재 provider ownership을 닫은 뒤 optional one-shot prepare, rebuild, budget consume, 단일 dispatch 순서로 새 actual model/provider/path binding을 설치한다. |
| raw-free observation | request correlation, attempt/epoch, filter/rule, decision, recovery와 bounded sanitized cause/evidence만 timeline sink로 보낸다. |
## 범위
- 포함: transport-agnostic Core, OpenAI-compatible Chat runtime, provider-pool mixed path, Chat/Responses streaming provider tunnel, request-local ingress/rebuild와 Edge observation sink.
- 제외: 반복·missing tool-call·schema 같은 semantic detector 자체, provider/model 선택 알고리즘, raw parser, cross-request 저장과 범용 오류 수정 workflow.
## 주요 흐름
```mermaid
sequenceDiagram
participant Host as Edge host
participant Core as Stream Gate Core
participant Filters
participant Provider
participant Sink as Release sink
Host->>Core: request snapshot + initial AttemptBinding
Provider->>Core: normalized response-start/event
Core->>Core: stage + evidence hold
Core->>Filters: immutable EvidenceBatch 병렬 평가
Filters-->>Core: all outcomes
alt release 또는 terminal
Core->>Sink: safe release / single terminal
else recovery
Core->>Provider: current attempt abort
Core->>Host: optional prepare + bounded rebuild
Host->>Provider: single re-admission
Provider->>Core: next attempt events
end
```
## 계약
- 외부 OpenAI-compatible 오류와 stream framing: `agent-contract/outer/openai-compatible-api.md`
- Edge 설정과 refresh 분류: `agent-contract/inner/edge-config-runtime-refresh.md`
- Edge-Node provider tunnel wire: `agent-contract/inner/edge-node-runtime-wire.md`
## 설정/데이터/이벤트
- `openai.stream_evidence_gate.enabled` 기본값은 `false`이며 활성화 시 지원 경로의 response lifecycle을 Core가 소유한다.
- `max_request_fault_recovery`는 0..3, `max_strategy_fault_recovery`는 0..request-total이고 생략 시 request-total을 상속한다.
- `max_ingress_snapshot_bytes`는 1..16777216이며 생략 시 16 MiB다. raw body limit은 첫 read 전에 적용되고 canonical body, typed view와 rebuild peak가 같은 request-local ledger에 포함된다.
- Stream Evidence Gate 설정 변경은 현재 restart-required다. request가 시작된 뒤 config/registry snapshot은 바뀌지 않는다.
- production Core registry는 공통 Noop filter와 적용 가능한 request-local tool validation을 포함한다. 추가 semantic filter는 별도 소비 Milestone이 등록한다.
## 검증
- `make proto` - generated protobuf가 현재 schema와 일치해야 한다.
- `go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai ./packages/go/config` - Core, Edge vertical cycle, request rebuild, observation과 config 경계가 통과해야 한다.
- `git diff --check` - 문서와 코드 diff에 공백 오류가 없어야 한다.
## 한계와 주의사항
- normalized `/v1/responses`는 현재 streaming을 지원하지 않으며 해당 non-stream path는 Stream Evidence Gate runtime을 사용하지 않는다.
- direct provider tunnel의 non-stream response는 기존 buffered passthrough 경로를 유지한다. ingress 상한은 runtime 활성 여부와 무관하게 적용된다.
- Core 활성화만으로 후속 semantic filter가 자동 활성화되지는 않는다.
- observation은 저장소가 아니라 event envelope이며 보존·조회 정책은 host observability sink가 소유한다.
## 변경 기록
- 2026-07-28: Stream Evidence Gate Core 완료 감사에서 현재 Core, Edge wiring, 계약과 테스트 근거로 targeted spec 생성.