iop/agent-spec/runtime/stream-evidence-gate.md
toki f9442edfef feat(runtime): provider liveness 복구를 완성한다
장시간 무응답 attempt를 안전하게 fence하고 provider health와 분리 관측해야 중복 출력 없이 기존 recovery budget으로 재실행할 수 있다.
2026-08-06 08:49:59 +09:00

11 KiB

spec_doc_type spec_id status source_evidence
spec runtime/stream-evidence-gate 구현됨
type path notes
contract agent-contract/outer/openai-compatible-api.md OpenAI-compatible ingress, stream commit와 terminal 오류 계약
type path notes
contract agent-contract/inner/edge-config-runtime-refresh.md Stream Evidence Gate 설정과 restart-required 분류 계약
type path notes
code packages/go/streamgate/runtime.go request-local event, evaluation, release와 recovery lifecycle
type path notes
code packages/go/streamgate/recovery_coordinator.go abort, optional prepare, rebuild, budget consume와 single dispatch 순서
type path notes
code apps/edge/internal/openai/stream_gate_runtime.go OpenAI Chat과 provider tunnel host wiring
type path notes
code apps/edge/internal/openai/openai_request_rebuilder.go bounded lossless OpenAI request rebuild
type path notes
test packages/go/streamgate/runtime_test.go Core lifecycle, recovery와 terminal 검증
type path notes
test apps/edge/internal/openai/stream_gate_vertical_slice_test.go Edge 실제 admission과 full-cycle 검증
type path notes
test apps/edge/internal/openai/stream_gate_pipeline_test.go Chat/Responses tunnel의 exact-wire terminal, split tool identity, non-2xx lifecycle 검증
type path notes
test apps/edge/internal/openai/stream_gate_stall_recovery_test.go S05 endpoint/path/semantic recovery matrix, shared budget, candidate identity, transport close, guard terminals, and disabled-semantic compatibility
type path notes
test apps/edge/internal/openai/filter_observation_sink_test.go raw-free observation allowlist와 correlation 검증
type path notes
test apps/edge/internal/openai/liveness_recovery_observability_test.go request-local closed-label liveness metrics, safe default-log projection, and explicit-sink forwarding

스펙: 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를 transport와 분리하고, Chat/Responses tunnel의 caller wire는 semantic evidence와 별도 queue에서 원본 순서로 release한다.
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한다.
repeat-resume builder A selected continuation plan can consume one request-local content/reasoning snapshot and build endpoint-native Chat or Responses resume input with the fixed English directive, without caller history or another model call.
active repeat guard Request-local Chat/Responses history fingerprints, a Unicode rolling pending window, and committed look-behind produce sanitized pass, continuation, repeated-action safe-stop, or side-effect fatal decisions.
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로 보낸다. The OpenAI liveness projection additionally emits one closed eligibility metric and at most one closed final-result metric per private cycle.
typed stall handoff Every supported OpenAI Chat/Responses normalized or tunnel request has one always-on runtime liveness owner. It maps only an Edge-confirmed response_stalled terminal to a raw-free provider error and evaluates ExactReplay through the existing commit/cancel/side-effect/snapshot/shared-budget contract.

범위

  • 포함: transport-agnostic Core, OpenAI-compatible Chat와 normalized non-stream Responses 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.

주요 흐름

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 defaults to false and controls only configured semantic filters and their capability admission. The Core owns the supported response/liveness lifecycle in both states, while disabled mode preserves endpoint-native compatibility through runtime adapters.
  • 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은 바뀌지 않는다.
  • The production Core registry includes the common Noop filter, configured active repeat_guard, schema/provider-error lifecycle foundations, and applicable request-local tool validation. Repeat detection uses the configured 500-rune default, never time-based release, and returns a continuation only before a tool/side-effect boundary. Provider-error still records unmatched errors as pass until its matcher Task.
  • The private typed-stall evaluator is always registered for supported requests and is independent from configured semantic filters[] and provider capability admission. It closes a confirmed old transport without a duplicate cancel and passes the failed provider once to pool re-admission; only available permits avoided-provider fallback.
  • Liveness metrics use only execution_path, provider_health, commit_state, eligibility, and recovery_result closed vocabularies. Constructor-owned generic zap logging is replaced for the private liveness/ExactReplay rows with a safe projection; a sink supplied through SetObservationSink still receives the original immutable observations.
  • Resume recording is bounded by the ingress snapshot limit and is reset for every attempt. The Rebuilder consumes it once after the owning attempt is aborted. It uses the request-start model catalog context window and fails before dispatch when the window is unknown or the rebuilt prompt plus its completion reserve does not fit.
  • A repeat continuation cursor is a UTF-8 byte boundary for content or reasoning. Already committed look-behind fixes the cursor at the released channel boundary; the pending duplicate is discarded, and a byte-identical replacement prefix is suppressed once. Omitted temperature uses 0.2, 0.4, and 0.6 by strategy attempt; explicit temperature is preserved.

검증

  • make proto - generated protobuf가 현재 schema와 일치해야 한다.
  • go test -race -count=1 ./packages/go/streamgate ./apps/edge/internal/openai ./packages/go/config - Core, Edge vertical cycle, Chat/Responses tunnel exact-wire terminal·split tool identity·non-2xx lifecycle, request rebuild, observation과 config 경계가 통과해야 한다.
  • git diff --check - 문서와 코드 diff에 공백 오류가 없어야 한다.

한계와 주의사항

  • Normalized /v1/responses does not support streaming, but it always uses the request-local StreamGate runtime. Supported Chat/Responses provider tunnels also separate protocol finish from the transport terminal and release trailing wire once.
  • Direct provider-tunnel non-stream responses retain buffered passthrough compatibility inside the same runtime. The ingress bound applies independently of semantic-filter activation.
  • Always-on Core ownership does not automatically activate a semantic filter.
  • The repeat detector remains a separately configured filter. The implemented builder is only the request-local continuation seam; it does not translate, summarize, or use a local model or RecoveryPlanPreparer.
  • observation은 저장소가 아니라 event envelope이며 보존·조회 정책은 host observability sink가 소유한다.

변경 기록

  • 2026-07-28: Stream Evidence Gate Core 완료 감사에서 현재 Core, Edge wiring, 계약과 테스트 근거로 targeted spec 생성.
  • 2026-07-28: Chat/Responses tunnel의 terminal wire queue, split tool identity와 non-2xx provider-error lifecycle 근거로 normalized Responses runtime 범위와 foundation 한계를 현재 구현에 맞췄다.
  • 2026-07-28: Added the request-local Chat/Responses repeat-resume builder, its bounded recorder lifecycle, fixed directive, caller-history exclusion, and context-window fail-closed boundary.
  • 2026-07-29: Activated request-local history/current-stream repeat detection, Unicode safe cursors, no-progress action safe-stop, one-shot prefix suppression, and continuation temperature candidates.
  • 2026-08-05: Added raw-free response_stalled mapping and runtime-local confirmed-handoff recovery ownership for OpenAI StreamGate attempts.
  • 2026-08-05: Made supported Chat/Responses normalized and tunnel liveness ownership unconditional, isolated semantic activation to configured filters/capability admission, and added deterministic S05 recovery/guard/compatibility evidence.
  • 2026-08-06: Added request-local liveness eligibility/result metrics and constructor-default-only safe observation-log projection.