katgpt_types/inference.rs
1//! Inference result + proposer/gate types.
2
3#[cfg(feature = "sr2am_configurator")]
4use super::PlanningDecision;
5
6// ---------------------------------------------------------------------------
7// InferenceResult
8// ---------------------------------------------------------------------------
9
10/// Output of a single inference pass, with reward signal for feedback loop.
11///
12/// Fields ordered by descending alignment to minimize padding:
13/// u64/i64/usize/String (8-byte) → f32 (4-byte) → Option<#[repr(u8)]> (2-byte) → u8/bool (1-byte).
14#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
15pub struct InferenceResult {
16 // --- 8-byte aligned ---
17 /// Input prompt hash (for dedup, not stored).
18 pub prompt_hash: u64,
19 /// Timestamp (Uuid v7 prefix).
20 pub timestamp: i64,
21 /// Number of nodes explored in DDTree.
22 pub tree_budget_used: usize,
23 /// Actual planning horizon used this turn (after entropy truncation, Plan 112 T13).
24 #[cfg(feature = "sr2am_configurator")]
25 pub plan_horizon_used: usize,
26 /// Domain that handled this inference.
27 pub domain: String,
28 /// Generated output text.
29 pub output: String,
30
31 // --- 4-byte aligned ---
32 /// Best-path reward (max relevance score from WasmPruner).
33 pub reward: f32,
34
35 // --- 2-byte aligned (Option<#[repr(u8)] enum>) ---
36 /// SR²AM configurator planning decision for this turn (Plan 112).
37 #[cfg(feature = "sr2am_configurator")]
38 pub planning_decision: Option<PlanningDecision>,
39
40 // --- 1-byte fields (tail-packed) ---
41 /// Was this result screened out (reward below threshold)?
42 pub screened: bool,
43 /// Inference budget level (0=cheap, 1=moderate, 2=expensive).
44 pub budget_level: u8,
45}
46
47// ---------------------------------------------------------------------------
48// Data Gate — Self-Play Stability (Plan 111, Research 075)
49// ---------------------------------------------------------------------------
50
51/// Discriminator for different self-play task types.
52#[cfg(feature = "data_gate")]
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54#[repr(u8)]
55pub enum TaskType {
56 /// Python code output prediction
57 CodeIO,
58 /// DSL expression evaluation
59 DslExpr,
60 /// Game action (Bomber, Go, FFT, Monopoly)
61 GameAction,
62 /// Open-ended generation
63 OpenEnded,
64}
65
66/// A task proposed by the self-play proposer, before solver evaluation.
67#[cfg(feature = "data_gate")]
68#[derive(Debug, Clone)]
69pub struct ProposerTask {
70 /// Task identifier for diagnostics.
71 pub id: usize,
72 /// The problem/query text.
73 pub query: String,
74 /// Optional code or DSL expression to execute.
75 pub program: Option<String>,
76 /// Optional input for the program.
77 pub program_input: Option<String>,
78 /// Task type discriminator.
79 pub task_type: TaskType,
80}
81
82/// Gate admission decision.
83///
84/// Decides whether a proposer-generated task should enter the training pool
85/// BEFORE the solver attempts it.
86#[cfg(feature = "data_gate")]
87#[repr(u8)]
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub enum GateDecision {
90 /// Task passes the gate — admitted to training pool.
91 Admit,
92 /// Task rejected with reason.
93 Reject(String),
94}
95
96/// Task-level admission gate for self-play training pool.
97///
98/// Decides whether a proposer-generated task should enter the training pool
99/// BEFORE the solver attempts it. This is the binding constraint for self-play
100/// stability (Survive or Collapse, Pu et al. 2026).
101///
102/// Key finding: a strict gate is sufficient for stability under every reward
103/// variant; no reward variant is sufficient once the gate is removed.
104#[cfg(feature = "data_gate")]
105pub trait DataGate {
106 /// Admit or reject a proposed task.
107 ///
108 /// Returns `GateDecision::Admit` if the task passes the gate,
109 /// `GateDecision::Reject(reason)` if not.
110 fn admit(&self, task: &ProposerTask) -> GateDecision;
111
112 /// Current leak rate ε (fraction of failed tasks admitted).
113 /// ε=0 means strict gate (optimal). ε=1 means gate off (collapse).
114 fn leak_rate(&self) -> f32;
115}