fix(codex-bridge): close the gaps an independent review found
Server CI and Windows package / verify (push) Successful in 3m23s
Server CI and Windows package / windows-package (push) Successful in 7m9s

- One decision per real turn: a turn starts with a user message after the
  previous final answer; tool steps, messages typed mid-turn, a lone "."
  and compaction keep the combo. Works without prompt_cache_key too.
- The virtual Otomatik name never reaches the gateway (stage off or error
  -> last choice or targets.zor); prefilter.target may not be it.
- finishCheck: at most once per turn; a broken, empty or refused retry
  delivers the already approved first answer.
- Layer window filter: only trusted windows, never the last layer.
- Correction channel only on always-pass targets while checks are on;
  Sesli-Hizli-Zeki stays always-pass by default; a >256 KB SSE frame
  passes unfiltered instead of breaking the stream.
- Turn-start questions wait in the local queue no longer than their
  timeout; decision-turn memory under a lock with refreshed order.
- Dify fetch refuses redirects (the app key never moves host); the
  rules file write retries a Windows sharing violation.
- An unreadable settings file no longer breaks every request.
- TypeScript accepts only https:// URLs the bridge accepts;
  finishCheck.timeoutSeconds (unused) removed.

Tests: 310 bridge tests, 36 electron tests; side-bridge live run for the
turn, prefilter (incl. decision timeout) and finish-check paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yilsemandClaude Opus 5.5 committed 2026-10-14 08:14:38 +03:00
1 parent 7c4ef18df0
commit a7ba300448
10 files changed
+353 -91

No files matched your search

+20 -12
View File
@@ -36,25 +36,33 @@ decision always keeps the current path.
- `jev-settings.json` schema 2 adds `watchModels`, `prefilter`, `autoRoute`, `finishCheck`,
`verifierCheck` and `policy`. A schema 1 file is filled from `jev-settings-defaults.json`.
The default chain is `Katman-1 → Katman-2 → Katman-3`; `Katman-3`, `Chat-Model` and
`bekci-sesli-bekci` always pass.
The default chain is `Katman-1 → Katman-2 → Katman-3`; `Katman-3`, `Chat-Model`,
`bekci-sesli-bekci` and `Sesli-Hizli-Zeki` always pass.
- **Correction channel** (`watchModels`): the Bekçi watch sideband is no longer bound to the hard-coded
name `Sesli-Hizli-Zeki`; any exact target in the list owns it.
name `Sesli-Hizli-Zeki`; any exact target in the list owns it, but only while it always passes the check
(a checked answer may be replaced by a layer, and a receipt must not belong to an answer the user never saw).
A single SSE frame above 256 KB no longer breaks the stream; the rest of the stream passes unfiltered.
- **Refusal pre-check** (`prefilter`): at the start of a turn, "would a mainstream model refuse or water
this down?". If yes, the step starts at `prefilter.target` instead of collecting a refusal first.
- **Automatic model** (`autoRoute`): a virtual `ide/<model>` entry ("Otomatik") in the Codex list. Each new
user message gets one decision call (hard? research?) and goes to the configured combo. Tool steps of
the same turn keep that combo, because switching providers mid-turn breaks encrypted history. The
user's explicit model choice is never changed by this stage.
- Both turn-start questions go in one call, bounded by `timeoutSeconds` (default 3 s).
- **Layer window filter**: a layer whose context window cannot hold the request is skipped.
- **Automatic model** (`autoRoute`): a virtual `ide/<model>` entry ("Otomatik") in the Codex list. A new turn
(a user message after the previous final answer) gets one decision call (hard? research?) and goes to
the configured combo. Tool steps, messages typed while the turn runs, a lone "." and compaction stay on
the same combo, because switching providers mid-turn breaks encrypted history. When the stage is off or
fails, the virtual name never reaches the gateway: the last choice or `targets.zor` is used. The user's
explicit model choice is never changed by this stage.
- Both turn-start questions go in one call; the wait, including the local queue, is bounded by
`timeoutSeconds` (default 3 s).
- **Layer window filter**: a layer whose trusted context window (pencere.bekci_calisir) cannot hold the
request is skipped. The last link of the chain is never skipped.
- **Early finish check** (`finishCheck`): asked in the same call as the refusal check on a final answer.
If the answer stopped early or claimed success without evidence, it goes back to the same model once
with `finishCheck.note`; the retry is delivered without another finish question.
If the answer stopped early or claimed success without evidence, it goes back to the same model with
`finishCheck.note`, at most once per turn. If the retry breaks, comes back empty or fails the check, the
first (already approved) answer is delivered.
- **Rules from Dify** (`policy.source = dify`, `karar_politikasi.py`): the stage questions, thresholds and
combo choices may come from a Dify workflow's `kurallar` output. Fetched in the background every
`refreshMinutes`, validated against the local settings, last good copy kept in `jev-policy.json`.
The transition chain and the always-pass list stay local. A turn never waits for Dify.
The transition chain and the always-pass list stay local. A turn never waits for Dify, and a redirect
from the Dify endpoint is refused so the app key never travels to another host.
- **Workflow reviewer check** (`verifierCheck`, `karar_sor.py`): the Codex dynamic-workflow acceptance
step asks whether a reviewer approved without concrete evidence; if so acceptance is blocked.