pub const REASONING_METADATA_KEYS: &[&str];Expand description
ChatMessage::metadata keys that carry a source model’s private
reasoning/thinking payload — populated today by Session’s foreign-
format importers:
- Claude Code / Codex legacy singular fields (
session.rs’spush_claude_assistant/Codexreasoningresponse_itemhandling):"thinking"/"thinking_signature"/"redacted_thinking"/"reasoning"/"reasoning_content"/"reasoning_encrypted". "thinking_blocks"— the Claude Code importer’s exact per-block replay list (session.rs:3475-3480,push_claude_assistant): everythinking/redacted_thinkingcontent block preserved SEPARATELY, in order, each with its own signature/data, as a serialized JSON array. REVIEW FINDING (P4c dep 8, MEDIUM, proven): the Claude Code EXPORTER (session.rs’sto_claude_code_jsonl, ~5654-5676) PREFERS this key over the legacy singular fields whenever present — so leaving it out of this list let a full signed chain-of-thought surviveswitch_modeluntouched and get re-emitted, re-attributed to model-B, on the very next Claude Code export. Added here to close that hole."pi_thought_signature"— pi’s per-toolCall-blockthoughtSignature(Google-provider reasoning-continuity token,session.rs:4248-4249import /session.rs:7418-7419export aspi_assistant_content_valuere-emits it onto everytoolCallblock, independent of whether anythinking/thinking_blockskey is even present on the message). Audited in alongside the fix above: likeredacted_thinking, its payload is opaque/encrypted rather than literal text, but this crate already treats “opaque encrypted reasoning artifact” as reasoning- bearing forredacted_thinking—pi_thought_signatureis the same class of thing (Google’s opaque encoded reasoning trace tied to a tool call), just pi-namespaced (docs/interop/research/pi-fields.md:161groups it under “provider replay signatures” alongsidethinking_signature). Deliberately NOT added:pi_text_signature(session.rs:4219-4224/4271-4272, OpenAI Responses replay-continuity id for atextblock whose content is already fully exposed viamsg.content— pi-fields.md’s own per-field note calls it “replay- continuity residue”, not a reasoning payload) andpi_thinking_redacted(session.rs:4267-4269, a bare boolean flag with no payload of its own — and inert regardless, sincepi_assistant_content_valueonly ever reads it from inside theif let Some(thinking) = ...arm gated on the now-stripped"thinking"key, so it can never reach an export on its own). Stripping either would be over-stripping non-reasoning metadata for no leak-closing benefit.
metadata itself is never serialized onto the wire (ChatMessage’s
custom Serialize impl omits it — see message.rs), so this list is a
DEFENSE-IN-DEPTH filter, not the primary leak-prevention mechanism: the
primary one is that metadata never reaches a provider request at all,
regardless of this function. What this filter actually guarantees is the
OBSERVABLE contract dep 8 asks for — a post-switch inspection of
history (the in-memory session state, sidecar exports, /export, a
future translator emitting this session under another harness’s format)
never shows model-A’s reasoning attributed to a conversation now being
driven by model-B.