gate: the rebuke turn is not a ground — second examination uses the caller's sources

The live round trip showed the second examination listing the gate's own
rebuke as source user_2. The rebuke is the gate's turn, not something the
caller gave the model; the second reply is now examined against the
caller's original body (same sources and query as the first). Test pins
it. Elixir gate 15/0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Scott KarpandClaude Fable 5.1 committed 2026-10-13 18:40:11 +00:00
1 parent 2b8eaced27
commit 0ade2c949e
2 files changed
+6 -1

No files matched your search

+3 -1
View File
@@ -47,7 +47,9 @@ defmodule VavPipeline.Gate do
with :ok <- gather_call(), with :ok <- gather_call(),
{:ok, 200, reply2} <- forward.(upstream, body2, key, extra), {:ok, 200, reply2} <- forward.(upstream, body2, key, extra),
{:ok, second} <- examine(upstream, body2, reply2, Keyword.put(examine_opts, :rebukes, first.bedikah_ref)) do # Examined against what the CALLER gave (body, not body2): the
# rebuke is the gate's own turn and is not a ground.
{:ok, second} <- examine(upstream, body, reply2, Keyword.put(examine_opts, :rebukes, first.bedikah_ref)) do
{:ok, deliver(upstream, reply2, second, first)} {:ok, deliver(upstream, reply2, second, first)}
else else
{:ok, status, other} -> {:ok, %{status: status, reply: other, bedikah: nil, first: first, shorashim: nil}} {:ok, status, other} -> {:ok, %{status: status, reply: other, bedikah: nil, first: first, shorashim: nil}}
+3
View File
@@ -207,6 +207,9 @@ defmodule VavPipeline.GateTest do
assert pass.first.verdict == :lo_tov assert pass.first.verdict == :lo_tov
assert pass.bedikah.verdict == :tov assert pass.bedikah.verdict == :tov
assert pass.bedikah.rebukes == pass.first.bedikah_ref assert pass.bedikah.rebukes == pass.first.bedikah_ref
# The rebuke turn is the gate's, not the caller's: not a source for the second examination.
assert Enum.map(pass.bedikah.sources, & &1.id) == ["system", "user_1", "user_2"]
assert pass.bedikah.sources == pass.first.sources
[%{"text" => text}] = pass.reply["content"] [%{"text" => text}] = pass.reply["content"]
assert String.starts_with?(text, "CLEAN:") assert String.starts_with?(text, "CLEAN:")
assert text =~ "— shorashim #{pass.bedikah.bedikah_ref}: tov (after rebuke of #{pass.first.bedikah_ref}: lo_tov)" assert text =~ "— shorashim #{pass.bedikah.bedikah_ref}: tov (after rebuke of #{pass.first.bedikah_ref}: lo_tov)"