polyc-facts 2026.9.0

Shared semantic-fold library: decode-to-fact functions reused by every consumer that reads the event log, so a payment receipt or a tool call means the same thing everywhere it's read.
//! `incognito_set` event decode (#1579).
//!
//! Previously decoded inline in the conversation-trace projector
//! (`trace.rs`) via a direct
//! `polyc_proto::events_decode::decode_event_payload::<IncognitoSetEvent>`
//! call. Moved here so a future second reader (a query typed table, another
//! projector) has one decode to call rather than reimplementing the same
//! bytes→struct step — mechanical decode, no state machine or projection
//! attached.

use polyc_proto::proto::polychrome::events::v1::IncognitoSetEvent;

/// Decode an `incognito_set` event payload.
///
/// Returns `None` on a decode failure — including an over-cap payload
/// ([`polyc_proto::events_decode::MAX_EVENT_PAYLOAD_BYTES`]) — the caller
/// decides whether and how to warn.
#[must_use]
pub fn fold_incognito_set(payload: &[u8]) -> Option<IncognitoSetEvent> {
    polyc_proto::events_decode::decode_event_payload(payload)
}

#[cfg(test)]
mod tests {
    #![allow(clippy::pedantic, clippy::nursery, missing_docs, clippy::unwrap_used)]

    use buffa::Message as _;

    use super::*;

    #[test]
    fn round_trips_an_incognito_set_payload() {
        let event = IncognitoSetEvent {
            on: true,
            __buffa_unknown_fields: buffa::UnknownFields::default(),
        };
        let bytes = event.encode_to_vec();
        let decoded = fold_incognito_set(&bytes).expect("decode incognito_set");
        assert!(decoded.on);
    }

    #[test]
    fn empty_payload_decodes_to_defaults() {
        let decoded = fold_incognito_set(&[]).expect("empty payload decodes");
        assert!(!decoded.on);
    }

    #[test]
    fn garbage_bytes_do_not_decode() {
        assert!(fold_incognito_set(&[0xFF, 0xFE, 0xFD]).is_none());
    }
}