SIGN IN SIGN UP

fix(claude): carry caller system inputs into Claude system blocks

OpenAI callers can raise instructions above user content in three ways
and Claude has one system slot for all of them, but the translators
disagreed on where each one landed. Responses instructions became a
leading user turn, a role=system item was only demoted for the first
item, role=developer silently became user text, and the Chat translator
dropped developer messages outright. An operator instruction could
therefore lose its authority or disappear without any signal.

All five sources now become separate top-level Claude system blocks in
source order, so the executor cloak decides the final placement on its
own: a mid-conversation role=system message on models that accept one,
an individual <system-reminder> block on legacy models. Blocks are never
merged, trimmed, reordered or demoted.

Anthropic only accepts text in a system slot. Verified against
api.anthropic.com: the top-level system field rejects anything else with
"system.<i>.type: Input should be 'text'", and a role=system message
accepts text, tool_addition and tool_removal only. A non-text system part
is therefore kept as a typed marker without its payload and rejected by
the cloak with a request-scoped 400 that names the offending type. That
keeps the failure local, spends no upstream call on a request that cannot
succeed, and stops caller content from ever reaching the top-level system
field where it would break the Claude Code fingerprint shape.
S
sususu committed
6f8f11a3249e7e6a04ab917a2efa1b8db26bcd3d
Parent: 3fac4a0