fix(integration): green gate with tracked streaming skip, gemini coverage, robust probe

Addresses coordinator review of the Task 15 integration suite: 1 critical
ruling, 5 important, 3 folded. make integration now exits 0.

- integration_test.go: TestStreamingIncrementalityProbe restructured —
  content assertion (5 deltas + [DONE], in order) always runs; the raw-TCP
  timing assertion (unchanged, >=3 gaps >=100ms) is gated behind
  INTEGRATION_STREAMING=1 with t.Skipf naming traefik/traefik#10269,
  verified to still genuinely fail when re-armed (not silently disabled).
- Makefile: integration-up/integration-wait moved from prerequisites into
  the integration recipe body as go test ./... -count=1
ok  	github.com/lukaszraczylo/traefik-llmgateway	6.065s sub-invocations with per-stage
  status capture, so integration-down always runs even when bring-up or
  the health wait fails; verified with a synthetic failure. Added
  .NOTPARALLEL (the integration targets are stateful).
- translate_gemini.go: fixed the same yaegi multi-value-assignment panic
  shape as the prior sse.go fix, on the live max_tokens path. Added a
  gemini chat completion assertion to integration_test.go (renamed
  TestUnifiedChatAllProviders) so this path now runs under real Yaegi.
- providers.go, translate_anthropic.go: documented the never-wrap
  contract on providerHTTPError/translateError (routes_unified.go asserts
  their concrete type directly; errors.As panics under yaegi on these).
- integration_test.go: TestCrossReplicaLimits now FLUSHALLs Redis first,
  for idempotence under integration-keep.
- mock/main.go: probe's header-terminator search now accumulates a
  rolling buffer across reads instead of only checking the latest one.
- Folded: hot-reload deadline 10s -> 20s; dynamic.yml's real-upstream
  baseUrl is now a template (dynamic.yml.tmpl) rendered via
  INTEGRATION_REAL_BASEURL (default https://llmgw.example.com), not a
  hardcoded-only hostname.

See task-15-report.md's addendum for full verification detail.
This commit is contained in:
2026-08-20 13:46:45 +01:00
parent 7939c3e74b
commit 730583d98e
8 changed files with 201 additions and 28 deletions
+7
View File
@@ -51,6 +51,13 @@ const adapterIdleConnsPerHost = 16
// so the caller — the unified route in a later task — decides whether to
// pass the body through verbatim or wrap it in the gateway's own error
// envelope.
//
// MUST be returned bare, never wrapped with fmt.Errorf("%w", ...):
// routes_unified.go's handleAdapterError relies on a direct type assertion
// (err.(*providerHTTPError)), not errors.As, because errors.As panics under
// yaegi when checking whether an interpreted pointer type implements error
// (verified empirically under real Traefik, Task 15's integration suite).
// A wrapped providerHTTPError would make that assertion fail to find it.
type providerHTTPError struct {
body []byte
status int