Skip to main content

xlog_prob/
epistemic_production.rs

1//! Production GPU exact-path adapter for accepted epistemic evidence.
2//!
3//! This module is intentionally thin. It gates probabilistic execution on
4//! accepted world-view evidence, then routes into the existing GPU-native exact
5//! provenance path instead of using the bounded epistemic fixture circuit.
6
7use std::collections::BTreeSet;
8use std::sync::Arc;
9
10use xlog_core::{symbol, Result, XlogError};
11use xlog_cuda::CudaKernelProvider;
12use xlog_ir::EirEpistemicMode;
13use xlog_logic::ast::{Atom, Evidence, Program, Term};
14use xlog_logic::parse_program;
15use xlog_runtime::{EpistemicGpuBatchExecutionResult, EpistemicGpuExecutionResult};
16
17use crate::compilation::{encode_cnf_gpu, GpuPirGraph, GpuPirRoots};
18#[cfg(feature = "host-io")]
19use crate::epistemic::EpistemicAssumptionKind;
20use crate::epistemic::EpistemicEvidenceTerm;
21use crate::epistemic::{
22    AcceptedWorldViewEvidence, CircuitUpdate, CircuitUpdateMode, EpistemicAssumption,
23    EpistemicCircuit,
24};
25#[cfg(feature = "host-io")]
26use crate::exact::ExactProgramOrigin;
27use crate::exact::{ExactDdnnfProgram, GpuConfig};
28#[cfg(feature = "host-io")]
29use crate::exact::{ExactResult, ExactResultWithGrads};
30use crate::pir::{PirNode, PirNodeId};
31use crate::provenance::Value;
32use crate::provenance::{extract_from_program, Provenance};
33
34macro_rules! epistemic_prob_trace_transaction {
35    ($adapter:ident, $body:block) => {{
36        let trace_before = $adapter.trace;
37        let result: Result<_> = (|| $body)();
38        match result {
39            Ok(value) => Ok(value),
40            Err(err) => {
41                $adapter.trace = trace_before;
42                Err(err)
43            }
44        }
45    }};
46}
47
48macro_rules! checked_prob_trace_counter_inc {
49    ($adapter:ident, $field:ident) => {{
50        $adapter.trace.$field = EpistemicProbProductionAdapter::checked_trace_counter_add(
51            $adapter.trace.$field,
52            1,
53            stringify!($field),
54        )?;
55    }};
56}
57
58/// Production capability status for probabilistic paths required by v0.9.
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum EpistemicProbProductionCapabilityStatus {
61    /// Existing GPU-native production path is available.
62    Available,
63    /// Required GPU-native production path is not implemented.
64    Blocked,
65}
66
67/// Capability report for the probabilistic production adapter.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub struct EpistemicProbProductionCapabilities {
70    /// Exact/provenance compilation through `ExactDdnnfProgram`.
71    pub gpu_exact_provenance: EpistemicProbProductionCapabilityStatus,
72    /// GPU PIR upload and CNF encoding path.
73    pub gpu_pir_cnf: EpistemicProbProductionCapabilityStatus,
74    /// Bounded compile-plus-evaluate knowledge-compilation path.
75    pub gpu_knowledge_compilation: EpistemicProbProductionCapabilityStatus,
76    /// GPU query and gradient evaluation path.
77    pub gpu_exact_query_and_gradient: EpistemicProbProductionCapabilityStatus,
78    /// Whether the bounded fixture circuit may satisfy production metrics.
79    pub fixture_circuit_allowed: bool,
80    /// Blocker reason for knowledge-compilation production coverage, or empty when available.
81    pub gpu_knowledge_compilation_blocker: &'static str,
82}
83
84/// Return the current probabilistic production capability report.
85pub fn production_capabilities() -> EpistemicProbProductionCapabilities {
86    EpistemicProbProductionCapabilities {
87        gpu_exact_provenance: EpistemicProbProductionCapabilityStatus::Available,
88        gpu_pir_cnf: EpistemicProbProductionCapabilityStatus::Available,
89        gpu_knowledge_compilation: EpistemicProbProductionCapabilityStatus::Available,
90        gpu_exact_query_and_gradient: EpistemicProbProductionCapabilityStatus::Available,
91        fixture_circuit_allowed: false,
92        gpu_knowledge_compilation_blocker: "",
93    }
94}
95
96/// Trace counters proving the production adapter stayed on the GPU exact path.
97#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
98pub struct EpistemicProbProductionTrace {
99    /// Number of source compiles routed through `ExactDdnnfProgram`.
100    pub gpu_exact_source_compiles: u64,
101    /// Number of parsed-program compiles routed through `ExactDdnnfProgram`.
102    pub gpu_exact_program_compiles: u64,
103    /// Number of accepted world-view evidence objects consumed as a gate.
104    pub accepted_world_view_evidence_consumed: u64,
105    /// Number of accepted Gelfond-1991 compatibility-mode GPU world-view
106    /// evidence objects consumed as a gate.
107    pub accepted_g91_world_view_evidence_consumed: u64,
108    /// Number of accepted FAEEL GPU world-view evidence objects consumed as a gate.
109    pub accepted_faeel_world_view_evidence_consumed: u64,
110    /// Number of accepted epistemic assumptions consumed from world-view evidence.
111    pub accepted_evidence_assumptions_consumed: u64,
112    /// Number of accepted nonzero-arity epistemic assumptions consumed from GPU evidence.
113    pub accepted_gpu_nonzero_arity_evidence_assumptions_consumed: u64,
114    /// Maximum accepted GPU evidence tuple arity consumed by this adapter.
115    pub accepted_gpu_max_evidence_arity_consumed: u32,
116    /// GPU tuple-key column reads consumed from accepted world-view evidence.
117    pub accepted_gpu_tuple_key_column_reads_consumed: u64,
118    /// GPU final-tuple row filters consumed from accepted world-view evidence.
119    pub accepted_gpu_final_tuple_row_filters_consumed: u64,
120    /// Negated GPU final-tuple row filters consumed from accepted world-view evidence.
121    pub accepted_gpu_final_tuple_negated_row_filters_consumed: u64,
122    /// Row-specific GPU model-slot capacity consumed from accepted world-view evidence.
123    pub accepted_gpu_row_specific_membership_row_capacity_consumed: u64,
124    /// Fallback GPU row-filter capacity consumed outside bounded model-slot windows.
125    pub accepted_gpu_row_filter_fallback_row_capacity_consumed: u64,
126    /// Reduced integrity-constraint relations checked by accepted GPU evidence.
127    pub accepted_gpu_constraint_relations_checked_consumed: u64,
128    /// Constraint row-count metadata reads consumed from accepted GPU evidence.
129    pub accepted_gpu_constraint_row_count_device_reads_consumed: u64,
130    /// Number of accepted GPU batch evidence records consumed as a gate.
131    pub accepted_gpu_batch_evidence_consumed: u64,
132    /// Number of accepted GPU batch components consumed as individual evidence records.
133    pub accepted_gpu_batch_component_evidence_consumed: u64,
134    /// Number of accepted evidence applications that updated caller-owned incremental circuits.
135    ///
136    /// This is fixture coverage only and is intentionally excluded from production path events.
137    pub accepted_incremental_circuit_updates: u64,
138    /// Number of GPU exact query evaluations routed through `ExactDdnnfProgram`.
139    pub gpu_exact_query_evaluations: u64,
140    /// Number of source GPU exact query evaluations routed through `ExactDdnnfProgram`.
141    pub gpu_source_exact_query_evaluations: u64,
142    /// Number of parsed-program GPU exact query evaluations routed through `ExactDdnnfProgram`.
143    pub gpu_program_exact_query_evaluations: u64,
144    /// Number of GPU gradient evaluations routed through `ExactDdnnfProgram`.
145    pub gpu_exact_gradient_evaluations: u64,
146    /// Number of source GPU gradient evaluations routed through `ExactDdnnfProgram`.
147    pub gpu_source_exact_gradient_evaluations: u64,
148    /// Number of parsed-program GPU gradient evaluations routed through `ExactDdnnfProgram`.
149    pub gpu_program_exact_gradient_evaluations: u64,
150    /// Number of source-conditioned GPU gradient evaluations routed through `ExactDdnnfProgram`.
151    pub gpu_source_conditioned_gradient_evaluations: u64,
152    /// Number of parsed-program-conditioned GPU gradient evaluations routed through `ExactDdnnfProgram`.
153    pub gpu_program_conditioned_gradient_evaluations: u64,
154    /// Number of accepted PIR graphs uploaded through the existing GPU PIR layout.
155    pub gpu_pir_graph_uploads: u64,
156    /// Number of source accepted PIR graphs uploaded through the existing GPU PIR layout.
157    pub gpu_source_pir_graph_uploads: u64,
158    /// Number of parsed-program accepted PIR graphs uploaded through the existing GPU PIR layout.
159    pub gpu_program_pir_graph_uploads: u64,
160    /// Number of accepted PIR root sets encoded through the existing GPU CNF encoder.
161    pub gpu_cnf_encodes: u64,
162    /// Number of source accepted PIR root sets encoded through the existing GPU CNF encoder.
163    pub gpu_source_cnf_encodes: u64,
164    /// Number of parsed-program accepted PIR root sets encoded through the existing GPU CNF encoder.
165    pub gpu_program_cnf_encodes: u64,
166    /// Number of accepted compile-and-evaluate runs through the GPU exact path.
167    pub gpu_knowledge_compilation_end_to_end_runs: u64,
168    /// GPU exact/provenance/PIR/CNF/knowledge-compilation events that occurred inside accepted evidence gates.
169    pub accepted_gpu_production_path_events: u64,
170    /// Number of accepted source compile-and-evaluate runs through the GPU exact path.
171    pub gpu_source_knowledge_compilation_end_to_end_runs: u64,
172    /// Number of accepted parsed-program compile-and-evaluate runs through the GPU exact path.
173    pub gpu_program_knowledge_compilation_end_to_end_runs: u64,
174    /// Number of accepted assumptions compiled as exact evidence facts.
175    pub gpu_conditioned_evidence_facts: u64,
176    /// Number of accepted world-view evidence objects compiled into conditioned exact evidence.
177    pub accepted_conditioned_world_view_evidence_consumed: u64,
178    /// Number of source-conditioned accepted world-view evidence objects compiled as exact evidence.
179    pub accepted_source_conditioned_world_view_evidence_consumed: u64,
180    /// Number of parsed-program-conditioned accepted world-view evidence objects compiled as exact evidence.
181    pub accepted_program_conditioned_world_view_evidence_consumed: u64,
182    /// Number of accepted nonzero-arity assumptions compiled as exact evidence facts.
183    pub gpu_conditioned_nonzero_arity_evidence_facts: u64,
184    /// Maximum accepted exact evidence tuple arity observed across conditioned paths.
185    pub gpu_conditioned_max_evidence_arity: u32,
186    /// Number of false accepted assumptions compiled as exact evidence facts.
187    pub gpu_conditioned_negative_evidence_facts: u64,
188    /// Number of source-conditioned accepted assumptions compiled as exact evidence facts.
189    pub gpu_source_conditioned_evidence_facts: u64,
190    /// Number of source-conditioned nonzero-arity assumptions compiled as exact evidence facts.
191    pub gpu_source_conditioned_nonzero_arity_evidence_facts: u64,
192    /// Maximum source-conditioned accepted exact evidence tuple arity observed.
193    pub gpu_source_conditioned_max_evidence_arity: u32,
194    /// Number of parsed-program-conditioned accepted assumptions compiled as exact evidence facts.
195    pub gpu_program_conditioned_evidence_facts: u64,
196    /// Number of parsed-program-conditioned nonzero-arity assumptions compiled as exact evidence facts.
197    pub gpu_program_conditioned_nonzero_arity_evidence_facts: u64,
198    /// Maximum parsed-program-conditioned accepted exact evidence tuple arity observed.
199    pub gpu_program_conditioned_max_evidence_arity: u32,
200    /// Number of false source-conditioned assumptions compiled as exact evidence facts.
201    pub gpu_source_conditioned_negative_evidence_facts: u64,
202    /// Number of false parsed-program-conditioned assumptions compiled as exact evidence facts.
203    pub gpu_program_conditioned_negative_evidence_facts: u64,
204    /// Number of true `know` assumptions compiled as exact evidence facts.
205    pub gpu_conditioned_know_evidence_facts: u64,
206    /// Number of true `possible` assumptions compiled as exact evidence facts.
207    pub gpu_conditioned_possible_evidence_facts: u64,
208    /// Number of false `know` assumptions compiled as exact evidence facts.
209    pub gpu_conditioned_not_known_evidence_facts: u64,
210    /// Number of false `possible` assumptions compiled as exact evidence facts.
211    pub gpu_conditioned_not_possible_evidence_facts: u64,
212    /// Number of source-conditioned true `know` assumptions compiled as exact evidence facts.
213    pub gpu_source_conditioned_know_evidence_facts: u64,
214    /// Number of source-conditioned true `possible` assumptions compiled as exact evidence facts.
215    pub gpu_source_conditioned_possible_evidence_facts: u64,
216    /// Number of source-conditioned false `know` assumptions compiled as exact evidence facts.
217    pub gpu_source_conditioned_not_known_evidence_facts: u64,
218    /// Number of source-conditioned false `possible` assumptions compiled as exact evidence facts.
219    pub gpu_source_conditioned_not_possible_evidence_facts: u64,
220    /// Number of parsed-program-conditioned true `know` assumptions compiled as exact evidence facts.
221    pub gpu_program_conditioned_know_evidence_facts: u64,
222    /// Number of parsed-program-conditioned true `possible` assumptions compiled as exact evidence facts.
223    pub gpu_program_conditioned_possible_evidence_facts: u64,
224    /// Number of parsed-program-conditioned false `know` assumptions compiled as exact evidence facts.
225    pub gpu_program_conditioned_not_known_evidence_facts: u64,
226    /// Number of parsed-program-conditioned false `possible` assumptions compiled as exact evidence facts.
227    pub gpu_program_conditioned_not_possible_evidence_facts: u64,
228    /// CPU-only probability recomputations performed by this adapter.
229    pub cpu_only_probability_recomputations: u64,
230    /// Fixture `EpistemicCircuit` evaluations performed by this adapter.
231    pub fixture_circuit_evaluations: u64,
232}
233
234impl EpistemicProbProductionTrace {
235    fn checked_gpu_production_path_events(&self) -> Result<u64> {
236        Self::checked_production_event_sum(
237            "gpu_production_path_events",
238            &[
239                self.gpu_exact_source_compiles,
240                self.gpu_exact_program_compiles,
241                self.gpu_exact_query_evaluations,
242                self.gpu_source_exact_query_evaluations,
243                self.gpu_program_exact_query_evaluations,
244                self.gpu_exact_gradient_evaluations,
245                self.gpu_source_exact_gradient_evaluations,
246                self.gpu_program_exact_gradient_evaluations,
247                self.gpu_source_conditioned_gradient_evaluations,
248                self.gpu_program_conditioned_gradient_evaluations,
249                self.gpu_pir_graph_uploads,
250                self.gpu_source_pir_graph_uploads,
251                self.gpu_program_pir_graph_uploads,
252                self.gpu_cnf_encodes,
253                self.gpu_source_cnf_encodes,
254                self.gpu_program_cnf_encodes,
255                self.gpu_knowledge_compilation_end_to_end_runs,
256                self.gpu_source_knowledge_compilation_end_to_end_runs,
257                self.gpu_program_knowledge_compilation_end_to_end_runs,
258            ],
259        )
260    }
261
262    fn checked_production_event_sum(counter: &str, values: &[u64]) -> Result<u64> {
263        values.iter().try_fold(0u64, |acc, value| {
264            acc.checked_add(*value)
265                .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
266                    construct: "epistemic probabilistic production trace accounting".to_string(),
267                    context: format!(
268                        "GPU probability production counter {counter} overflowed while adding \
269                         {value} to {acc}"
270                    ),
271                })
272        })
273    }
274
275    fn require_pir_cnf_accounting_pair(
276        construct: &'static str,
277        pir_graph_uploads: u64,
278        cnf_encodes: u64,
279        path: &'static str,
280    ) -> Result<()> {
281        if pir_graph_uploads != cnf_encodes {
282            return Err(XlogError::UnsupportedEpistemicConstruct {
283                construct: construct.to_string(),
284                context: format!(
285                    "PIR/CNF production accounting must match for {path} path, got \
286                     pir_graph_uploads={} cnf_encodes={}",
287                    pir_graph_uploads, cnf_encodes
288                ),
289            });
290        }
291        Ok(())
292    }
293
294    fn require_pir_cnf_accounting(&self) -> Result<()> {
295        let construct = "epistemic probabilistic production metric gate";
296        Self::require_pir_cnf_accounting_pair(
297            construct,
298            self.gpu_pir_graph_uploads,
299            self.gpu_cnf_encodes,
300            "aggregate",
301        )?;
302        Self::require_pir_cnf_accounting_pair(
303            construct,
304            self.gpu_source_pir_graph_uploads,
305            self.gpu_source_cnf_encodes,
306            "source",
307        )?;
308        Self::require_pir_cnf_accounting_pair(
309            construct,
310            self.gpu_program_pir_graph_uploads,
311            self.gpu_program_cnf_encodes,
312            "program",
313        )
314    }
315
316    /// Require that no CPU-only probability recomputation counters were used.
317    pub fn require_zero_cpu_recompute(&self) -> Result<()> {
318        if self.cpu_only_probability_recomputations != 0 || self.fixture_circuit_evaluations != 0 {
319            return Err(XlogError::UnsupportedEpistemicConstruct {
320                construct: "epistemic probabilistic production adapter".to_string(),
321                context: format!(
322                    "CPU probabilistic fallback counters must be zero, got recompute={} fixture={}",
323                    self.cpu_only_probability_recomputations, self.fixture_circuit_evaluations
324                ),
325            });
326        }
327        Ok(())
328    }
329
330    /// Require internally consistent GPU tuple-membership evidence counters.
331    pub fn require_accepted_gpu_tuple_evidence_trace(&self) -> Result<()> {
332        if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
333            > self.accepted_evidence_assumptions_consumed
334        {
335            return Err(XlogError::UnsupportedEpistemicConstruct {
336                construct: "epistemic probabilistic production metric gate".to_string(),
337                context: format!(
338                    "accepted nonzero-arity evidence assumptions cannot exceed accepted \
339                     evidence assumptions: nonzero={} total={}",
340                    self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
341                    self.accepted_evidence_assumptions_consumed
342                ),
343            });
344        }
345        if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed == 0
346            && self.accepted_gpu_max_evidence_arity_consumed > 0
347        {
348            return Err(XlogError::UnsupportedEpistemicConstruct {
349                construct: "epistemic probabilistic production metric gate".to_string(),
350                context: format!(
351                    "accepted max evidence arity {} requires at least one accepted \
352                     nonzero-arity GPU evidence assumption",
353                    self.accepted_gpu_max_evidence_arity_consumed
354                ),
355            });
356        }
357        if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed > 0
358            && self.accepted_gpu_max_evidence_arity_consumed == 0
359        {
360            return Err(XlogError::UnsupportedEpistemicConstruct {
361                construct: "epistemic probabilistic production metric gate".to_string(),
362                context: format!(
363                    "accepted nonzero-arity GPU evidence requires accepted max evidence arity, \
364                     got nonzero_assumptions={} max_arity=0",
365                    self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
366                ),
367            });
368        }
369        if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed == 0
370            && self.accepted_gpu_tuple_key_column_reads_consumed != 0
371        {
372            return Err(XlogError::UnsupportedEpistemicConstruct {
373                construct: "epistemic probabilistic production metric gate".to_string(),
374                context: format!(
375                    "accepted tuple-key reads require accepted nonzero-arity GPU evidence, got \
376                     nonzero_assumptions=0 tuple_key_reads={}",
377                    self.accepted_gpu_tuple_key_column_reads_consumed
378                ),
379            });
380        }
381        if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed > 0
382            && self.accepted_gpu_tuple_key_column_reads_consumed == 0
383        {
384            return Err(XlogError::UnsupportedEpistemicConstruct {
385                construct: "epistemic probabilistic production metric gate".to_string(),
386                context: format!(
387                    "accepted nonzero-arity GPU evidence requires tuple-key device column reads, \
388                     got nonzero_assumptions={} tuple_key_reads=0",
389                    self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
390                ),
391            });
392        }
393        if self.accepted_gpu_final_tuple_negated_row_filters_consumed
394            > self.accepted_gpu_final_tuple_row_filters_consumed
395        {
396            return Err(XlogError::UnsupportedEpistemicConstruct {
397                construct: "epistemic probabilistic production metric gate".to_string(),
398                context: format!(
399                    "accepted negated final-tuple row filters cannot exceed total row filters: \
400                     negated={} total={}",
401                    self.accepted_gpu_final_tuple_negated_row_filters_consumed,
402                    self.accepted_gpu_final_tuple_row_filters_consumed
403                ),
404            });
405        }
406        if self.accepted_gpu_final_tuple_row_filters_consumed == 0
407            && (self.accepted_gpu_row_specific_membership_row_capacity_consumed != 0
408                || self.accepted_gpu_row_filter_fallback_row_capacity_consumed != 0)
409        {
410            return Err(XlogError::UnsupportedEpistemicConstruct {
411                construct: "epistemic probabilistic production metric gate".to_string(),
412                context: format!(
413                    "accepted row-specific/fallback tuple capacity requires accepted GPU row \
414                     filters, got row_filters=0 row_specific_capacity={} fallback_capacity={}",
415                    self.accepted_gpu_row_specific_membership_row_capacity_consumed,
416                    self.accepted_gpu_row_filter_fallback_row_capacity_consumed
417                ),
418            });
419        }
420        if self.accepted_gpu_final_tuple_row_filters_consumed > 0
421            && self.accepted_gpu_row_specific_membership_row_capacity_consumed == 0
422        {
423            return Err(XlogError::UnsupportedEpistemicConstruct {
424                construct: "epistemic probabilistic production metric gate".to_string(),
425                context: format!(
426                    "accepted GPU final-tuple row filters require row-specific model-slot \
427                     capacity, got row_filters={} row_specific_capacity=0",
428                    self.accepted_gpu_final_tuple_row_filters_consumed
429                ),
430            });
431        }
432        if self.accepted_gpu_constraint_row_count_device_reads_consumed
433            > self.accepted_gpu_constraint_relations_checked_consumed
434        {
435            return Err(XlogError::UnsupportedEpistemicConstruct {
436                construct: "epistemic probabilistic production metric gate".to_string(),
437                context: format!(
438                    "accepted constraint row-count device reads cannot exceed checked reduced \
439                     constraint relations, got reads={} checked={}",
440                    self.accepted_gpu_constraint_row_count_device_reads_consumed,
441                    self.accepted_gpu_constraint_relations_checked_consumed
442                ),
443            });
444        }
445        Ok(())
446    }
447
448    /// Require internally consistent accepted GPU world-view evidence counters.
449    pub fn require_accepted_gpu_world_view_evidence_trace(&self) -> Result<()> {
450        let mode_count = self
451            .accepted_g91_world_view_evidence_consumed
452            .checked_add(self.accepted_faeel_world_view_evidence_consumed)
453            .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
454                construct: "epistemic probabilistic production metric gate".to_string(),
455                context: "accepted GPU world-view mode counters overflowed".to_string(),
456            })?;
457        if self.accepted_world_view_evidence_consumed != 0
458            && mode_count != self.accepted_world_view_evidence_consumed
459        {
460            return Err(XlogError::UnsupportedEpistemicConstruct {
461                construct: "epistemic probabilistic production metric gate".to_string(),
462                context: format!(
463                    "accepted GPU world-view evidence must be classified by epistemic mode, got \
464                     evidence={} gelfond_1991={} faeel={}",
465                    self.accepted_world_view_evidence_consumed,
466                    self.accepted_g91_world_view_evidence_consumed,
467                    self.accepted_faeel_world_view_evidence_consumed
468                ),
469            });
470        }
471        if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
472            > self.accepted_evidence_assumptions_consumed
473        {
474            return Err(XlogError::UnsupportedEpistemicConstruct {
475                construct: "epistemic probabilistic production metric gate".to_string(),
476                context: format!(
477                    "accepted nonzero-arity GPU evidence assumptions cannot exceed accepted \
478                     assumptions, got nonzero={} assumptions={}",
479                    self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
480                    self.accepted_evidence_assumptions_consumed
481                ),
482            });
483        }
484        if self.accepted_world_view_evidence_consumed != 0
485            && self.accepted_evidence_assumptions_consumed
486                < self.accepted_world_view_evidence_consumed
487        {
488            return Err(XlogError::UnsupportedEpistemicConstruct {
489                construct: "epistemic probabilistic production metric gate".to_string(),
490                context: format!(
491                    "accepted GPU world-view evidence requires at least one accepted epistemic \
492                     assumption per evidence record, got evidence={} assumptions={}",
493                    self.accepted_world_view_evidence_consumed,
494                    self.accepted_evidence_assumptions_consumed
495                ),
496            });
497        }
498        if self.accepted_gpu_batch_component_evidence_consumed
499            < self.accepted_gpu_batch_evidence_consumed
500        {
501            return Err(XlogError::UnsupportedEpistemicConstruct {
502                construct: "epistemic probabilistic production metric gate".to_string(),
503                context: format!(
504                    "accepted GPU batch component evidence must cover accepted batch evidence, \
505                     got batches={} components={}",
506                    self.accepted_gpu_batch_evidence_consumed,
507                    self.accepted_gpu_batch_component_evidence_consumed
508                ),
509            });
510        }
511        if self.accepted_gpu_batch_component_evidence_consumed
512            > self.accepted_world_view_evidence_consumed
513        {
514            return Err(XlogError::UnsupportedEpistemicConstruct {
515                construct: "epistemic probabilistic production metric gate".to_string(),
516                context: format!(
517                    "accepted GPU batch component evidence cannot exceed accepted world-view \
518                     evidence, got components={} evidence={}",
519                    self.accepted_gpu_batch_component_evidence_consumed,
520                    self.accepted_world_view_evidence_consumed
521                ),
522            });
523        }
524        if self.accepted_conditioned_world_view_evidence_consumed
525            > self.accepted_world_view_evidence_consumed
526        {
527            return Err(XlogError::UnsupportedEpistemicConstruct {
528                construct: "epistemic probabilistic production metric gate".to_string(),
529                context: format!(
530                    "accepted conditioned world-view evidence cannot exceed accepted world-view \
531                     evidence, got conditioned={} evidence={}",
532                    self.accepted_conditioned_world_view_evidence_consumed,
533                    self.accepted_world_view_evidence_consumed
534                ),
535            });
536        }
537        Ok(())
538    }
539
540    fn require_conditioned_counter_sum(
541        counter: &'static str,
542        aggregate: u64,
543        source: u64,
544        program: u64,
545    ) -> Result<()> {
546        let expected = source.checked_add(program).ok_or_else(|| {
547            XlogError::UnsupportedEpistemicConstruct {
548                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
549                context: format!(
550                    "conditioned evidence counter {counter} overflowed while adding source={} \
551                     program={}",
552                    source, program
553                ),
554            }
555        })?;
556        if aggregate != expected {
557            return Err(XlogError::UnsupportedEpistemicConstruct {
558                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
559                context: format!(
560                    "conditioned evidence counter {counter} must equal source+program, got \
561                     aggregate={} source={} program={}",
562                    aggregate, source, program
563                ),
564            });
565        }
566        Ok(())
567    }
568
569    fn require_gpu_path_counter_sum(
570        counter: &'static str,
571        aggregate: u64,
572        source: u64,
573        program: u64,
574    ) -> Result<()> {
575        let expected = source.checked_add(program).ok_or_else(|| {
576            XlogError::UnsupportedEpistemicConstruct {
577                construct: "epistemic probabilistic production metric gate".to_string(),
578                context: format!(
579                    "GPU production path counter {counter} overflowed while adding source={} \
580                     program={}",
581                    source, program
582                ),
583            }
584        })?;
585        if aggregate != expected {
586            return Err(XlogError::UnsupportedEpistemicConstruct {
587                construct: "epistemic probabilistic production metric gate".to_string(),
588                context: format!(
589                    "GPU production path accounting must match source+program for {counter}, \
590                     got aggregate={} source={} program={}",
591                    aggregate, source, program
592                ),
593            });
594        }
595        Ok(())
596    }
597
598    fn require_gpu_path_accounting(&self) -> Result<()> {
599        Self::require_gpu_path_counter_sum(
600            "exact_query_evaluations",
601            self.gpu_exact_query_evaluations,
602            self.gpu_source_exact_query_evaluations,
603            self.gpu_program_exact_query_evaluations,
604        )?;
605        Self::require_gpu_path_counter_sum(
606            "exact_gradient_evaluations",
607            self.gpu_exact_gradient_evaluations,
608            self.gpu_source_exact_gradient_evaluations,
609            self.gpu_program_exact_gradient_evaluations,
610        )?;
611        Self::require_gpu_path_counter_sum(
612            "pir_graph_uploads",
613            self.gpu_pir_graph_uploads,
614            self.gpu_source_pir_graph_uploads,
615            self.gpu_program_pir_graph_uploads,
616        )?;
617        Self::require_gpu_path_counter_sum(
618            "cnf_encodes",
619            self.gpu_cnf_encodes,
620            self.gpu_source_cnf_encodes,
621            self.gpu_program_cnf_encodes,
622        )?;
623        Self::require_gpu_path_counter_sum(
624            "knowledge_compilation_end_to_end_runs",
625            self.gpu_knowledge_compilation_end_to_end_runs,
626            self.gpu_source_knowledge_compilation_end_to_end_runs,
627            self.gpu_program_knowledge_compilation_end_to_end_runs,
628        )
629    }
630
631    /// Require internally consistent conditioned exact-evidence counters.
632    pub fn require_conditioned_evidence_trace(&self) -> Result<()> {
633        Self::require_conditioned_counter_sum(
634            "accepted_world_view_evidence",
635            self.accepted_conditioned_world_view_evidence_consumed,
636            self.accepted_source_conditioned_world_view_evidence_consumed,
637            self.accepted_program_conditioned_world_view_evidence_consumed,
638        )?;
639        Self::require_conditioned_counter_sum(
640            "evidence_facts",
641            self.gpu_conditioned_evidence_facts,
642            self.gpu_source_conditioned_evidence_facts,
643            self.gpu_program_conditioned_evidence_facts,
644        )?;
645        Self::require_conditioned_counter_sum(
646            "nonzero_arity_evidence_facts",
647            self.gpu_conditioned_nonzero_arity_evidence_facts,
648            self.gpu_source_conditioned_nonzero_arity_evidence_facts,
649            self.gpu_program_conditioned_nonzero_arity_evidence_facts,
650        )?;
651        Self::require_conditioned_counter_sum(
652            "negative_evidence_facts",
653            self.gpu_conditioned_negative_evidence_facts,
654            self.gpu_source_conditioned_negative_evidence_facts,
655            self.gpu_program_conditioned_negative_evidence_facts,
656        )?;
657        Self::require_conditioned_counter_sum(
658            "know_evidence_facts",
659            self.gpu_conditioned_know_evidence_facts,
660            self.gpu_source_conditioned_know_evidence_facts,
661            self.gpu_program_conditioned_know_evidence_facts,
662        )?;
663        Self::require_conditioned_counter_sum(
664            "possible_evidence_facts",
665            self.gpu_conditioned_possible_evidence_facts,
666            self.gpu_source_conditioned_possible_evidence_facts,
667            self.gpu_program_conditioned_possible_evidence_facts,
668        )?;
669        Self::require_conditioned_counter_sum(
670            "not_known_evidence_facts",
671            self.gpu_conditioned_not_known_evidence_facts,
672            self.gpu_source_conditioned_not_known_evidence_facts,
673            self.gpu_program_conditioned_not_known_evidence_facts,
674        )?;
675        Self::require_conditioned_counter_sum(
676            "not_possible_evidence_facts",
677            self.gpu_conditioned_not_possible_evidence_facts,
678            self.gpu_source_conditioned_not_possible_evidence_facts,
679            self.gpu_program_conditioned_not_possible_evidence_facts,
680        )?;
681
682        if (self.gpu_conditioned_evidence_facts != 0
683            && self.accepted_conditioned_world_view_evidence_consumed == 0)
684            || (self.gpu_source_conditioned_evidence_facts != 0
685                && self.accepted_source_conditioned_world_view_evidence_consumed == 0)
686            || (self.gpu_program_conditioned_evidence_facts != 0
687                && self.accepted_program_conditioned_world_view_evidence_consumed == 0)
688        {
689            return Err(XlogError::UnsupportedEpistemicConstruct {
690                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
691                context: format!(
692                    "conditioned exact evidence facts require accepted conditioned world-view \
693                     evidence, got facts={} evidence={} source_facts={} source_evidence={} \
694                     program_facts={} program_evidence={}",
695                    self.gpu_conditioned_evidence_facts,
696                    self.accepted_conditioned_world_view_evidence_consumed,
697                    self.gpu_source_conditioned_evidence_facts,
698                    self.accepted_source_conditioned_world_view_evidence_consumed,
699                    self.gpu_program_conditioned_evidence_facts,
700                    self.accepted_program_conditioned_world_view_evidence_consumed
701                ),
702            });
703        }
704
705        if self.gpu_conditioned_evidence_facts
706            < self.accepted_conditioned_world_view_evidence_consumed
707            || self.gpu_source_conditioned_evidence_facts
708                < self.accepted_source_conditioned_world_view_evidence_consumed
709            || self.gpu_program_conditioned_evidence_facts
710                < self.accepted_program_conditioned_world_view_evidence_consumed
711        {
712            return Err(XlogError::UnsupportedEpistemicConstruct {
713                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
714                context: format!(
715                    "conditioned exact evidence facts must cover each accepted conditioned \
716                     world-view evidence record, got facts={} evidence={} source_facts={} \
717                     source_evidence={} program_facts={} program_evidence={}",
718                    self.gpu_conditioned_evidence_facts,
719                    self.accepted_conditioned_world_view_evidence_consumed,
720                    self.gpu_source_conditioned_evidence_facts,
721                    self.accepted_source_conditioned_world_view_evidence_consumed,
722                    self.gpu_program_conditioned_evidence_facts,
723                    self.accepted_program_conditioned_world_view_evidence_consumed
724                ),
725            });
726        }
727
728        if self.gpu_conditioned_nonzero_arity_evidence_facts > self.gpu_conditioned_evidence_facts
729            || self.gpu_source_conditioned_nonzero_arity_evidence_facts
730                > self.gpu_source_conditioned_evidence_facts
731            || self.gpu_program_conditioned_nonzero_arity_evidence_facts
732                > self.gpu_program_conditioned_evidence_facts
733        {
734            return Err(XlogError::UnsupportedEpistemicConstruct {
735                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
736                context: format!(
737                    "conditioned nonzero-arity facts cannot exceed conditioned evidence facts: \
738                     nonzero={} total={} source_nonzero={} source_total={} program_nonzero={} \
739                     program_total={}",
740                    self.gpu_conditioned_nonzero_arity_evidence_facts,
741                    self.gpu_conditioned_evidence_facts,
742                    self.gpu_source_conditioned_nonzero_arity_evidence_facts,
743                    self.gpu_source_conditioned_evidence_facts,
744                    self.gpu_program_conditioned_nonzero_arity_evidence_facts,
745                    self.gpu_program_conditioned_evidence_facts
746                ),
747            });
748        }
749        if self.gpu_conditioned_negative_evidence_facts > self.gpu_conditioned_evidence_facts
750            || self.gpu_source_conditioned_negative_evidence_facts
751                > self.gpu_source_conditioned_evidence_facts
752            || self.gpu_program_conditioned_negative_evidence_facts
753                > self.gpu_program_conditioned_evidence_facts
754        {
755            return Err(XlogError::UnsupportedEpistemicConstruct {
756                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
757                context: format!(
758                    "conditioned negative facts cannot exceed conditioned evidence facts: \
759                     negative={} total={} source_negative={} source_total={} program_negative={} \
760                     program_total={}",
761                    self.gpu_conditioned_negative_evidence_facts,
762                    self.gpu_conditioned_evidence_facts,
763                    self.gpu_source_conditioned_negative_evidence_facts,
764                    self.gpu_source_conditioned_evidence_facts,
765                    self.gpu_program_conditioned_negative_evidence_facts,
766                    self.gpu_program_conditioned_evidence_facts
767                ),
768            });
769        }
770
771        let operator_fact_count = self
772            .gpu_conditioned_know_evidence_facts
773            .checked_add(self.gpu_conditioned_possible_evidence_facts)
774            .and_then(|sum| sum.checked_add(self.gpu_conditioned_not_known_evidence_facts))
775            .and_then(|sum| sum.checked_add(self.gpu_conditioned_not_possible_evidence_facts))
776            .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
777                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
778                context: "conditioned operator evidence fact counters overflowed".to_string(),
779            })?;
780        if operator_fact_count != self.gpu_conditioned_evidence_facts {
781            return Err(XlogError::UnsupportedEpistemicConstruct {
782                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
783                context: format!(
784                    "conditioned operator evidence facts must equal total evidence facts, got \
785                     operators={} total={}",
786                    operator_fact_count, self.gpu_conditioned_evidence_facts
787                ),
788            });
789        }
790
791        let source_operator_fact_count = self
792            .gpu_source_conditioned_know_evidence_facts
793            .checked_add(self.gpu_source_conditioned_possible_evidence_facts)
794            .and_then(|sum| sum.checked_add(self.gpu_source_conditioned_not_known_evidence_facts))
795            .and_then(|sum| {
796                sum.checked_add(self.gpu_source_conditioned_not_possible_evidence_facts)
797            })
798            .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
799                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
800                context: "source conditioned operator evidence fact counters overflowed"
801                    .to_string(),
802            })?;
803        if source_operator_fact_count != self.gpu_source_conditioned_evidence_facts {
804            return Err(XlogError::UnsupportedEpistemicConstruct {
805                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
806                context: format!(
807                    "source conditioned operator evidence facts must equal source evidence \
808                     facts, got operators={} total={}",
809                    source_operator_fact_count, self.gpu_source_conditioned_evidence_facts
810                ),
811            });
812        }
813
814        let program_operator_fact_count = self
815            .gpu_program_conditioned_know_evidence_facts
816            .checked_add(self.gpu_program_conditioned_possible_evidence_facts)
817            .and_then(|sum| sum.checked_add(self.gpu_program_conditioned_not_known_evidence_facts))
818            .and_then(|sum| {
819                sum.checked_add(self.gpu_program_conditioned_not_possible_evidence_facts)
820            })
821            .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
822                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
823                context: "program conditioned operator evidence fact counters overflowed"
824                    .to_string(),
825            })?;
826        if program_operator_fact_count != self.gpu_program_conditioned_evidence_facts {
827            return Err(XlogError::UnsupportedEpistemicConstruct {
828                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
829                context: format!(
830                    "program conditioned operator evidence facts must equal program evidence \
831                     facts, got operators={} total={}",
832                    program_operator_fact_count, self.gpu_program_conditioned_evidence_facts
833                ),
834            });
835        }
836
837        let expected_max_arity = self
838            .gpu_source_conditioned_max_evidence_arity
839            .max(self.gpu_program_conditioned_max_evidence_arity);
840        if self.gpu_conditioned_max_evidence_arity != expected_max_arity {
841            return Err(XlogError::UnsupportedEpistemicConstruct {
842                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
843                context: format!(
844                    "conditioned max evidence arity must equal max(source, program), got \
845                     aggregate={} source={} program={}",
846                    self.gpu_conditioned_max_evidence_arity,
847                    self.gpu_source_conditioned_max_evidence_arity,
848                    self.gpu_program_conditioned_max_evidence_arity
849                ),
850            });
851        }
852        if (self.gpu_conditioned_nonzero_arity_evidence_facts == 0)
853            != (self.gpu_conditioned_max_evidence_arity == 0)
854        {
855            return Err(XlogError::UnsupportedEpistemicConstruct {
856                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
857                context: format!(
858                    "conditioned max evidence arity must be nonzero exactly when nonzero-arity \
859                     facts are present, got nonzero={} max_arity={}",
860                    self.gpu_conditioned_nonzero_arity_evidence_facts,
861                    self.gpu_conditioned_max_evidence_arity
862                ),
863            });
864        }
865        if (self.gpu_source_conditioned_nonzero_arity_evidence_facts == 0)
866            != (self.gpu_source_conditioned_max_evidence_arity == 0)
867        {
868            return Err(XlogError::UnsupportedEpistemicConstruct {
869                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
870                context: format!(
871                    "source conditioned max evidence arity must be nonzero exactly when \
872                     source nonzero-arity facts are present, got nonzero={} max_arity={}",
873                    self.gpu_source_conditioned_nonzero_arity_evidence_facts,
874                    self.gpu_source_conditioned_max_evidence_arity
875                ),
876            });
877        }
878        if (self.gpu_program_conditioned_nonzero_arity_evidence_facts == 0)
879            != (self.gpu_program_conditioned_max_evidence_arity == 0)
880        {
881            return Err(XlogError::UnsupportedEpistemicConstruct {
882                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
883                context: format!(
884                    "program conditioned max evidence arity must be nonzero exactly when \
885                     program nonzero-arity facts are present, got nonzero={} max_arity={}",
886                    self.gpu_program_conditioned_nonzero_arity_evidence_facts,
887                    self.gpu_program_conditioned_max_evidence_arity
888                ),
889            });
890        }
891        if (self.accepted_evidence_assumptions_consumed != 0
892            || self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed != 0
893            || self.accepted_gpu_max_evidence_arity_consumed != 0)
894            && (self.gpu_conditioned_evidence_facts > self.accepted_evidence_assumptions_consumed
895                || self.gpu_conditioned_nonzero_arity_evidence_facts
896                    > self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
897                || self.gpu_conditioned_max_evidence_arity
898                    > self.accepted_gpu_max_evidence_arity_consumed)
899        {
900            return Err(XlogError::UnsupportedEpistemicConstruct {
901                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
902                context: format!(
903                    "conditioned evidence facts must be bounded by accepted GPU evidence, got \
904                     facts={}/{} nonzero={}/{} max_arity={}/{}",
905                    self.gpu_conditioned_evidence_facts,
906                    self.accepted_evidence_assumptions_consumed,
907                    self.gpu_conditioned_nonzero_arity_evidence_facts,
908                    self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
909                    self.gpu_conditioned_max_evidence_arity,
910                    self.accepted_gpu_max_evidence_arity_consumed
911                ),
912            });
913        }
914        Ok(())
915    }
916
917    /// Require that this trace is eligible for v0.9 production probability metrics.
918    ///
919    /// This gate only proves fixture containment for an accepted probabilistic
920    /// path. It does not claim the broader probabilistic production goal is complete.
921    pub fn require_production_metric_eligibility(&self) -> Result<()> {
922        let capabilities = production_capabilities();
923        if capabilities.fixture_circuit_allowed {
924            return Err(XlogError::UnsupportedEpistemicConstruct {
925                construct: "epistemic probabilistic production metric gate".to_string(),
926                context: "bounded EpistemicCircuit fixtures are not allowed for production metrics"
927                    .to_string(),
928            });
929        }
930        if capabilities.gpu_exact_provenance != EpistemicProbProductionCapabilityStatus::Available {
931            return Err(XlogError::UnsupportedEpistemicConstruct {
932                construct: "epistemic probabilistic production metric gate".to_string(),
933                context: "GPU exact/provenance production capability is not available".to_string(),
934            });
935        }
936        if capabilities.gpu_pir_cnf != EpistemicProbProductionCapabilityStatus::Available {
937            return Err(XlogError::UnsupportedEpistemicConstruct {
938                construct: "epistemic probabilistic production metric gate".to_string(),
939                context: "GPU PIR/CNF production capability is not available".to_string(),
940            });
941        }
942        if capabilities.gpu_knowledge_compilation
943            != EpistemicProbProductionCapabilityStatus::Available
944        {
945            return Err(XlogError::UnsupportedEpistemicConstruct {
946                construct: "epistemic probabilistic production metric gate".to_string(),
947                context: capabilities.gpu_knowledge_compilation_blocker.to_string(),
948            });
949        }
950        if capabilities.gpu_exact_query_and_gradient
951            != EpistemicProbProductionCapabilityStatus::Available
952        {
953            return Err(XlogError::UnsupportedEpistemicConstruct {
954                construct: "epistemic probabilistic production metric gate".to_string(),
955                context: "GPU exact query/gradient production capability is not available"
956                    .to_string(),
957            });
958        }
959        if self.accepted_world_view_evidence_consumed == 0 {
960            return Err(XlogError::UnsupportedEpistemicConstruct {
961                construct: "epistemic probabilistic production metric gate".to_string(),
962                context: "production probability metrics require accepted world-view evidence"
963                    .to_string(),
964            });
965        }
966        let gpu_production_path_events = self.checked_gpu_production_path_events()?;
967        if gpu_production_path_events == 0 {
968            return Err(XlogError::UnsupportedEpistemicConstruct {
969                construct: "epistemic probabilistic production metric gate".to_string(),
970                context: "production probability metrics require an existing GPU exact/provenance/PIR/CNF/knowledge-compilation counter"
971                    .to_string(),
972            });
973        }
974        if self.accepted_gpu_production_path_events == 0 {
975            return Err(XlogError::UnsupportedEpistemicConstruct {
976                construct: "epistemic probabilistic production metric gate".to_string(),
977                context: "production probability metrics require GPU exact/provenance/PIR/CNF/knowledge-compilation work inside an accepted world-view evidence gate"
978                    .to_string(),
979            });
980        }
981        if self.accepted_gpu_production_path_events > gpu_production_path_events {
982            return Err(XlogError::UnsupportedEpistemicConstruct {
983                construct: "epistemic probabilistic production metric gate".to_string(),
984                context: format!(
985                    "accepted GPU probability production events cannot exceed total GPU production events: accepted={} total={}",
986                    self.accepted_gpu_production_path_events, gpu_production_path_events
987                ),
988            });
989        }
990        if self.accepted_gpu_production_path_events < self.accepted_world_view_evidence_consumed {
991            return Err(XlogError::UnsupportedEpistemicConstruct {
992                construct: "epistemic probabilistic production metric gate".to_string(),
993                context: format!(
994                    "accepted GPU probability production events must cover each accepted \
995                     world-view evidence record, got accepted_events={} evidence={}",
996                    self.accepted_gpu_production_path_events,
997                    self.accepted_world_view_evidence_consumed
998                ),
999            });
1000        }
1001        self.require_accepted_gpu_world_view_evidence_trace()?;
1002        self.require_accepted_gpu_tuple_evidence_trace()?;
1003        self.require_conditioned_evidence_trace()?;
1004        self.require_pir_cnf_accounting()?;
1005        self.require_gpu_path_accounting()?;
1006        self.require_zero_cpu_recompute()
1007    }
1008
1009    fn require_conditioned_evidence_metric_witness(&self) -> Result<()> {
1010        if self.accepted_conditioned_world_view_evidence_consumed == 0
1011            || self.gpu_conditioned_evidence_facts == 0
1012        {
1013            return Err(XlogError::UnsupportedEpistemicConstruct {
1014                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
1015                context:
1016                    "production probability metrics require accepted world-view evidence compiled as exact evidence facts"
1017                        .to_string(),
1018            });
1019        }
1020        Ok(())
1021    }
1022
1023    /// Require the stricter metric subset for accepted world-view evidence conditioning.
1024    ///
1025    /// General production eligibility proves fixture containment plus GPU exact/PIR/CNF/
1026    /// knowledge-compilation reuse. This gate additionally proves at least one accepted
1027    /// world view was compiled into exact evidence facts rather than only used as a
1028    /// production-path admission gate.
1029    pub fn require_conditioned_evidence_metric_eligibility(&self) -> Result<()> {
1030        self.require_production_metric_eligibility()?;
1031        self.require_conditioned_evidence_metric_witness()?;
1032        if self.gpu_conditioned_nonzero_arity_evidence_facts > 0
1033            && self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed == 0
1034        {
1035            return Err(XlogError::UnsupportedEpistemicConstruct {
1036                construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
1037                context: format!(
1038                    "conditioned nonzero-arity evidence facts require accepted GPU nonzero-arity \
1039                     assumptions, got conditioned_nonzero={} accepted_nonzero={}",
1040                    self.gpu_conditioned_nonzero_arity_evidence_facts,
1041                    self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
1042                ),
1043            });
1044        }
1045        self.require_zero_cpu_recompute()
1046    }
1047}
1048
1049/// Device-side PIR/CNF evidence produced after accepted epistemic gating.
1050#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1051pub struct EpistemicProbPirCnfEvidence {
1052    /// Number of host provenance PIR nodes uploaded to the GPU PIR layout.
1053    pub pir_nodes: usize,
1054    /// Number of roots supplied to GPU CNF encoding.
1055    pub root_count: usize,
1056    /// GPU CNF variable capacity emitted by `encode_cnf_gpu`.
1057    pub cnf_var_cap: u32,
1058    /// GPU CNF clause capacity emitted by `encode_cnf_gpu`.
1059    pub cnf_clause_cap: u32,
1060    /// GPU CNF literal capacity emitted by `encode_cnf_gpu`.
1061    pub cnf_lit_cap: u32,
1062}
1063
1064/// One accepted GPU epistemic execution record used for probabilistic production gating.
1065#[derive(Clone, Copy)]
1066pub struct EpistemicProbGpuExecutionEvidence<'a> {
1067    /// Accepted GPU execution result whose world-view boundary must be validated.
1068    pub result: &'a EpistemicGpuExecutionResult,
1069    /// Epistemic assumptions represented by the accepted world view.
1070    pub assumptions: &'a [EpistemicAssumption],
1071}
1072
1073/// Accepted GPU batch execution evidence used for probabilistic production gating.
1074pub struct EpistemicProbGpuBatchExecutionEvidence<'a> {
1075    /// Accepted GPU batch execution result whose aggregate trace and timing must be validated.
1076    pub batch: &'a EpistemicGpuBatchExecutionResult,
1077    /// Epistemic assumptions represented by each accepted component world view.
1078    pub assumptions_by_component: &'a [&'a [EpistemicAssumption]],
1079}
1080
1081#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1082enum EpistemicProbPirCnfPath {
1083    Source,
1084    Program,
1085}
1086
1087/// Thin adapter from accepted epistemic evidence to the existing GPU exact path.
1088pub struct EpistemicProbProductionAdapter {
1089    config: GpuConfig,
1090    trace: EpistemicProbProductionTrace,
1091}
1092
1093#[cfg(feature = "host-io")]
1094#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1095enum EpistemicProbConditionedEvidencePath {
1096    Source,
1097    Program,
1098}
1099
1100impl EpistemicProbProductionAdapter {
1101    fn checked_trace_counter_add(current: u64, delta: u64, counter: &str) -> Result<u64> {
1102        current
1103            .checked_add(delta)
1104            .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
1105                construct: "epistemic probabilistic production trace accounting".to_string(),
1106                context: format!(
1107                    "accepted GPU probability trace counter {counter} overflowed while adding \
1108                    {delta} to {current}"
1109                ),
1110            })
1111    }
1112
1113    #[cfg(feature = "host-io")]
1114    fn record_gpu_exact_query_evaluation(&mut self, program: &ExactDdnnfProgram) -> Result<()> {
1115        checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
1116        match program.origin() {
1117            ExactProgramOrigin::Source => {
1118                checked_prob_trace_counter_inc!(self, gpu_source_exact_query_evaluations);
1119            }
1120            ExactProgramOrigin::Program => {
1121                checked_prob_trace_counter_inc!(self, gpu_program_exact_query_evaluations);
1122            }
1123        }
1124        Ok(())
1125    }
1126
1127    #[cfg(feature = "host-io")]
1128    fn record_gpu_exact_gradient_evaluation(&mut self, program: &ExactDdnnfProgram) -> Result<()> {
1129        self.record_gpu_exact_gradient_evaluation_for_origin(program.origin())
1130    }
1131
1132    #[cfg(feature = "host-io")]
1133    fn record_gpu_exact_gradient_evaluation_for_origin(
1134        &mut self,
1135        origin: ExactProgramOrigin,
1136    ) -> Result<()> {
1137        checked_prob_trace_counter_inc!(self, gpu_exact_gradient_evaluations);
1138        match origin {
1139            ExactProgramOrigin::Source => {
1140                checked_prob_trace_counter_inc!(self, gpu_source_exact_gradient_evaluations);
1141            }
1142            ExactProgramOrigin::Program => {
1143                checked_prob_trace_counter_inc!(self, gpu_program_exact_gradient_evaluations);
1144            }
1145        }
1146        Ok(())
1147    }
1148
1149    /// Create a production adapter with a GPU exact inference configuration.
1150    pub fn new(config: GpuConfig) -> Self {
1151        Self {
1152            config,
1153            trace: EpistemicProbProductionTrace {
1154                cpu_only_probability_recomputations: 0,
1155                fixture_circuit_evaluations: 0,
1156                ..EpistemicProbProductionTrace::default()
1157            },
1158        }
1159    }
1160
1161    /// Return current production-path trace counters.
1162    pub fn trace(&self) -> EpistemicProbProductionTrace {
1163        self.trace
1164    }
1165
1166    /// Apply accepted world-view evidence to a caller-owned incremental circuit fixture.
1167    ///
1168    /// This records the accepted evidence boundary and zero-CPU guard, but it is not a
1169    /// production metric event. Production metric eligibility still requires an
1170    /// existing GPU exact/provenance/PIR/CNF/knowledge-compilation path counter.
1171    pub fn apply_accepted_world_view_to_circuit(
1172        &mut self,
1173        circuit: &mut EpistemicCircuit,
1174        evidence: AcceptedWorldViewEvidence,
1175    ) -> Result<CircuitUpdate> {
1176        epistemic_prob_trace_transaction!(self, {
1177            self.consume_accepted_evidence(&evidence)?;
1178            let update = circuit.apply_accepted_world_view(evidence)?;
1179            if update.mode == CircuitUpdateMode::IncrementalEvidence {
1180                self.trace.accepted_incremental_circuit_updates = Self::checked_trace_counter_add(
1181                    self.trace.accepted_incremental_circuit_updates,
1182                    1,
1183                    "accepted_incremental_circuit_updates",
1184                )?;
1185            }
1186            self.trace.require_zero_cpu_recompute()?;
1187            Ok(update)
1188        })
1189    }
1190
1191    /// Apply accepted GPU epistemic execution evidence to a caller-owned incremental circuit.
1192    pub fn apply_accepted_world_view_to_circuit_with_gpu_execution_result(
1193        &mut self,
1194        circuit: &mut EpistemicCircuit,
1195        provider: &CudaKernelProvider,
1196        result: &EpistemicGpuExecutionResult,
1197        assumptions: Vec<EpistemicAssumption>,
1198    ) -> Result<CircuitUpdate> {
1199        let evidence =
1200            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1201        self.apply_accepted_world_view_to_circuit(circuit, evidence)
1202    }
1203
1204    /// Apply accepted split/batch GPU epistemic execution evidence to an incremental circuit.
1205    pub fn apply_accepted_world_views_to_circuit_for_gpu_batch_execution_result(
1206        &mut self,
1207        circuit: &mut EpistemicCircuit,
1208        provider: &CudaKernelProvider,
1209        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1210    ) -> Result<Vec<CircuitUpdate>> {
1211        epistemic_prob_trace_transaction!(self, {
1212            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1213                provider,
1214                evidence,
1215                "epistemic probabilistic incremental circuit batch production",
1216            )?;
1217
1218            let mut updates = Vec::with_capacity(accepted.len());
1219            for evidence in accepted {
1220                updates.push(self.apply_accepted_world_view_to_circuit(circuit, evidence)?);
1221            }
1222            Ok(updates)
1223        })
1224    }
1225
1226    fn accepted_world_views_from_gpu_batch_execution_evidence(
1227        &mut self,
1228        provider: &CudaKernelProvider,
1229        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1230        construct: &str,
1231    ) -> Result<Vec<AcceptedWorldViewEvidence>> {
1232        if evidence.batch.results.is_empty() {
1233            return Err(XlogError::UnsupportedEpistemicConstruct {
1234                construct: construct.to_string(),
1235                context: "probabilistic batch gating requires at least one accepted GPU component"
1236                    .to_string(),
1237            });
1238        }
1239        if evidence.assumptions_by_component.len() != evidence.batch.results.len() {
1240            return Err(XlogError::UnsupportedEpistemicConstruct {
1241                construct: construct.to_string(),
1242                context: format!(
1243                    "assumption group count {} does not match GPU batch component count {}",
1244                    evidence.assumptions_by_component.len(),
1245                    evidence.batch.results.len()
1246                ),
1247            });
1248        }
1249        let batch_trace = evidence.batch.trace;
1250        if batch_trace.component_count != evidence.batch.results.len()
1251            || batch_trace.gpu_runtime_component_executions != evidence.batch.results.len()
1252            || batch_trace.cpu_recomposition_steps != 0
1253            || batch_trace.cpu_candidate_enumerations != 0
1254            || batch_trace.cpu_world_view_validations != 0
1255            || batch_trace.cpu_solver_search_fallbacks != 0
1256            || batch_trace.cpu_probability_recomputations != 0
1257            || batch_trace.tracked_dtoh_calls != 0
1258            || batch_trace.tracked_htod_calls != 0
1259            || batch_trace.tracked_data_plane_htod_calls != 0
1260            || batch_trace.per_candidate_host_round_trips != 0
1261            || batch_trace.violated_constraint_relations != 0
1262            || !batch_trace.aggregate_kernel_timing.is_recorded()
1263        {
1264            return Err(XlogError::UnsupportedEpistemicConstruct {
1265                construct: construct.to_string(),
1266                context: format!(
1267                    "accepted GPU batch evidence requires complete GPU component execution and \
1268                     zero CPU/host fallback counters outside bounded launch metadata plus \
1269                     aggregate CUDA-event timing, got \
1270                     components={}/{}, recomposition={}, cpu_candidates={}, cpu_world_views={}, \
1271                     cpu_solver_search={}, cpu_probability_recompute={}, dtoh_calls={}, \
1272                     htod_calls={}, data_plane_htod_calls={}, launch_metadata_htod_calls={}, \
1273                     round_trips={}, constraint_violations={}, aggregate_timing_recorded={}",
1274                    batch_trace.gpu_runtime_component_executions,
1275                    batch_trace.component_count,
1276                    batch_trace.cpu_recomposition_steps,
1277                    batch_trace.cpu_candidate_enumerations,
1278                    batch_trace.cpu_world_view_validations,
1279                    batch_trace.cpu_solver_search_fallbacks,
1280                    batch_trace.cpu_probability_recomputations,
1281                    batch_trace.tracked_dtoh_calls,
1282                    batch_trace.tracked_htod_calls,
1283                    batch_trace.tracked_data_plane_htod_calls,
1284                    batch_trace.tracked_launch_metadata_htod_calls,
1285                    batch_trace.per_candidate_host_round_trips,
1286                    batch_trace.violated_constraint_relations,
1287                    batch_trace.aggregate_kernel_timing.is_recorded()
1288                ),
1289            });
1290        }
1291        evidence.batch.require_trace_matches_components(construct)?;
1292
1293        let mut accepted = Vec::with_capacity(evidence.batch.results.len());
1294        for (result, assumptions) in evidence
1295            .batch
1296            .results
1297            .iter()
1298            .zip(evidence.assumptions_by_component.iter())
1299        {
1300            accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1301                provider,
1302                result,
1303                (*assumptions).to_vec(),
1304            )?);
1305        }
1306
1307        self.trace.accepted_gpu_batch_evidence_consumed = Self::checked_trace_counter_add(
1308            self.trace.accepted_gpu_batch_evidence_consumed,
1309            1,
1310            "accepted_gpu_batch_evidence_consumed",
1311        )?;
1312        self.trace.accepted_gpu_batch_component_evidence_consumed =
1313            Self::checked_trace_counter_add(
1314                self.trace.accepted_gpu_batch_component_evidence_consumed,
1315                accepted.len() as u64,
1316                "accepted_gpu_batch_component_evidence_consumed",
1317            )?;
1318
1319        Ok(accepted)
1320    }
1321
1322    #[cfg(feature = "host-io")]
1323    fn record_conditioned_evidence_counts(
1324        &mut self,
1325        counts: EpistemicProbConditionedEvidenceCounts,
1326        path: EpistemicProbConditionedEvidencePath,
1327    ) -> Result<()> {
1328        macro_rules! add_counter {
1329            ($field:ident, $delta:expr) => {
1330                self.trace.$field =
1331                    Self::checked_trace_counter_add(self.trace.$field, $delta, stringify!($field))?;
1332            };
1333        }
1334
1335        add_counter!(accepted_conditioned_world_view_evidence_consumed, 1);
1336        add_counter!(gpu_conditioned_evidence_facts, counts.total as u64);
1337        add_counter!(
1338            gpu_conditioned_nonzero_arity_evidence_facts,
1339            counts.nonzero_arity as u64
1340        );
1341        self.trace.gpu_conditioned_max_evidence_arity = self
1342            .trace
1343            .gpu_conditioned_max_evidence_arity
1344            .max(counts.max_arity);
1345        add_counter!(
1346            gpu_conditioned_negative_evidence_facts,
1347            counts.negative as u64
1348        );
1349        match path {
1350            EpistemicProbConditionedEvidencePath::Source => {
1351                add_counter!(accepted_source_conditioned_world_view_evidence_consumed, 1);
1352                add_counter!(gpu_source_conditioned_evidence_facts, counts.total as u64);
1353                add_counter!(
1354                    gpu_source_conditioned_nonzero_arity_evidence_facts,
1355                    counts.nonzero_arity as u64
1356                );
1357                self.trace.gpu_source_conditioned_max_evidence_arity = self
1358                    .trace
1359                    .gpu_source_conditioned_max_evidence_arity
1360                    .max(counts.max_arity);
1361                add_counter!(
1362                    gpu_source_conditioned_negative_evidence_facts,
1363                    counts.negative as u64
1364                );
1365                add_counter!(
1366                    gpu_source_conditioned_know_evidence_facts,
1367                    counts.know as u64
1368                );
1369                add_counter!(
1370                    gpu_source_conditioned_possible_evidence_facts,
1371                    counts.possible as u64
1372                );
1373                add_counter!(
1374                    gpu_source_conditioned_not_known_evidence_facts,
1375                    counts.not_known as u64
1376                );
1377                add_counter!(
1378                    gpu_source_conditioned_not_possible_evidence_facts,
1379                    counts.not_possible as u64
1380                );
1381            }
1382            EpistemicProbConditionedEvidencePath::Program => {
1383                add_counter!(accepted_program_conditioned_world_view_evidence_consumed, 1);
1384                add_counter!(gpu_program_conditioned_evidence_facts, counts.total as u64);
1385                add_counter!(
1386                    gpu_program_conditioned_nonzero_arity_evidence_facts,
1387                    counts.nonzero_arity as u64
1388                );
1389                self.trace.gpu_program_conditioned_max_evidence_arity = self
1390                    .trace
1391                    .gpu_program_conditioned_max_evidence_arity
1392                    .max(counts.max_arity);
1393                add_counter!(
1394                    gpu_program_conditioned_negative_evidence_facts,
1395                    counts.negative as u64
1396                );
1397                add_counter!(
1398                    gpu_program_conditioned_know_evidence_facts,
1399                    counts.know as u64
1400                );
1401                add_counter!(
1402                    gpu_program_conditioned_possible_evidence_facts,
1403                    counts.possible as u64
1404                );
1405                add_counter!(
1406                    gpu_program_conditioned_not_known_evidence_facts,
1407                    counts.not_known as u64
1408                );
1409                add_counter!(
1410                    gpu_program_conditioned_not_possible_evidence_facts,
1411                    counts.not_possible as u64
1412                );
1413            }
1414        }
1415        add_counter!(gpu_conditioned_know_evidence_facts, counts.know as u64);
1416        add_counter!(
1417            gpu_conditioned_possible_evidence_facts,
1418            counts.possible as u64
1419        );
1420        add_counter!(
1421            gpu_conditioned_not_known_evidence_facts,
1422            counts.not_known as u64
1423        );
1424        add_counter!(
1425            gpu_conditioned_not_possible_evidence_facts,
1426            counts.not_possible as u64
1427        );
1428        Ok(())
1429    }
1430
1431    fn record_accepted_gpu_production_path_events_since(
1432        &mut self,
1433        events_before: u64,
1434    ) -> Result<()> {
1435        let events_after = self.trace.checked_gpu_production_path_events()?;
1436        let delta = events_after.checked_sub(events_before).ok_or_else(|| {
1437            XlogError::UnsupportedEpistemicConstruct {
1438                construct: "epistemic probabilistic production trace accounting".to_string(),
1439                context: format!(
1440                    "accepted GPU probability production events decreased from {events_before} to \
1441                     {events_after}"
1442                ),
1443            }
1444        })?;
1445        self.trace.accepted_gpu_production_path_events = Self::checked_trace_counter_add(
1446            self.trace.accepted_gpu_production_path_events,
1447            delta,
1448            "accepted_gpu_production_path_events",
1449        )?;
1450        Ok(())
1451    }
1452
1453    /// Compile source through the existing GPU-native exact/provenance path.
1454    pub fn compile_source_with_accepted_world_view(
1455        &mut self,
1456        source: &str,
1457        evidence: &AcceptedWorldViewEvidence,
1458    ) -> Result<ExactDdnnfProgram> {
1459        epistemic_prob_trace_transaction!(self, {
1460            self.require_accepted_evidence(evidence)?;
1461            let production_events_before = self.trace.checked_gpu_production_path_events()?;
1462            let program = ExactDdnnfProgram::compile_source_with_gpu(source, self.config)?;
1463            require_gpu_exact_backend(&program, "epistemic probabilistic source exact compile")?;
1464            checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
1465            self.record_accepted_gpu_production_path_events_since(production_events_before)?;
1466            self.record_accepted_evidence(evidence)?;
1467            self.trace.require_zero_cpu_recompute()?;
1468            Ok(program)
1469        })
1470    }
1471
1472    /// Compile source through the GPU exact path after accepted GPU epistemic execution.
1473    pub fn compile_source_with_gpu_execution_result(
1474        &mut self,
1475        source: &str,
1476        provider: &CudaKernelProvider,
1477        result: &EpistemicGpuExecutionResult,
1478        assumptions: Vec<EpistemicAssumption>,
1479    ) -> Result<ExactDdnnfProgram> {
1480        let evidence =
1481            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1482        self.compile_source_with_accepted_world_view(source, &evidence)
1483    }
1484
1485    /// Compile source once per accepted GPU epistemic execution result.
1486    pub fn compile_source_for_gpu_execution_results(
1487        &mut self,
1488        source: &str,
1489        provider: &CudaKernelProvider,
1490        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1491    ) -> Result<Vec<ExactDdnnfProgram>> {
1492        epistemic_prob_trace_transaction!(self, {
1493            if evidence_records.is_empty() {
1494                return Err(XlogError::UnsupportedEpistemicConstruct {
1495                    construct: "epistemic probabilistic source exact compile batch".to_string(),
1496                    context:
1497                        "batched source exact compile requires at least one accepted GPU result"
1498                            .to_string(),
1499                });
1500            }
1501
1502            let mut accepted = Vec::with_capacity(evidence_records.len());
1503            for record in evidence_records {
1504                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1505                    provider,
1506                    record.result,
1507                    record.assumptions.to_vec(),
1508                )?);
1509            }
1510
1511            let mut programs = Vec::with_capacity(accepted.len());
1512            for evidence in &accepted {
1513                programs.push(self.compile_source_with_accepted_world_view(source, evidence)?);
1514            }
1515            Ok(programs)
1516        })
1517    }
1518
1519    /// Compile source once per accepted split/batch GPU epistemic component.
1520    pub fn compile_source_for_gpu_batch_execution_result(
1521        &mut self,
1522        source: &str,
1523        provider: &CudaKernelProvider,
1524        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1525    ) -> Result<Vec<ExactDdnnfProgram>> {
1526        epistemic_prob_trace_transaction!(self, {
1527            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1528                provider,
1529                evidence,
1530                "epistemic probabilistic source exact compile batch production",
1531            )?;
1532
1533            let mut programs = Vec::with_capacity(accepted.len());
1534            for evidence in &accepted {
1535                programs.push(self.compile_source_with_accepted_world_view(source, evidence)?);
1536            }
1537            Ok(programs)
1538        })
1539    }
1540
1541    /// Compile a parsed program through the existing GPU-native exact/provenance path.
1542    pub fn compile_program_with_accepted_world_view(
1543        &mut self,
1544        program: &Program,
1545        evidence: &AcceptedWorldViewEvidence,
1546    ) -> Result<ExactDdnnfProgram> {
1547        epistemic_prob_trace_transaction!(self, {
1548            self.require_accepted_evidence(evidence)?;
1549            let production_events_before = self.trace.checked_gpu_production_path_events()?;
1550            let exact = ExactDdnnfProgram::compile_from_program(program, self.config)?;
1551            require_gpu_exact_backend(
1552                &exact,
1553                "epistemic probabilistic parsed-program exact compile",
1554            )?;
1555            checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
1556            self.record_accepted_gpu_production_path_events_since(production_events_before)?;
1557            self.record_accepted_evidence(evidence)?;
1558            self.trace.require_zero_cpu_recompute()?;
1559            Ok(exact)
1560        })
1561    }
1562
1563    /// Compile a parsed program through the GPU exact path after accepted GPU epistemic execution.
1564    pub fn compile_program_with_gpu_execution_result(
1565        &mut self,
1566        program: &Program,
1567        provider: &CudaKernelProvider,
1568        result: &EpistemicGpuExecutionResult,
1569        assumptions: Vec<EpistemicAssumption>,
1570    ) -> Result<ExactDdnnfProgram> {
1571        let evidence =
1572            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1573        self.compile_program_with_accepted_world_view(program, &evidence)
1574    }
1575
1576    /// Compile a parsed program once per accepted GPU epistemic execution result.
1577    pub fn compile_program_for_gpu_execution_results(
1578        &mut self,
1579        program: &Program,
1580        provider: &CudaKernelProvider,
1581        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1582    ) -> Result<Vec<ExactDdnnfProgram>> {
1583        epistemic_prob_trace_transaction!(self, {
1584            if evidence_records.is_empty() {
1585                return Err(XlogError::UnsupportedEpistemicConstruct {
1586                    construct: "epistemic probabilistic parsed-program exact compile batch"
1587                        .to_string(),
1588                    context: "batched parsed-program exact compile requires at least one accepted GPU result"
1589                        .to_string(),
1590                });
1591            }
1592
1593            let mut accepted = Vec::with_capacity(evidence_records.len());
1594            for record in evidence_records {
1595                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1596                    provider,
1597                    record.result,
1598                    record.assumptions.to_vec(),
1599                )?);
1600            }
1601
1602            let mut programs = Vec::with_capacity(accepted.len());
1603            for evidence in &accepted {
1604                programs.push(self.compile_program_with_accepted_world_view(program, evidence)?);
1605            }
1606            Ok(programs)
1607        })
1608    }
1609
1610    /// Compile a parsed program once per accepted split/batch GPU epistemic component.
1611    pub fn compile_program_for_gpu_batch_execution_result(
1612        &mut self,
1613        program: &Program,
1614        provider: &CudaKernelProvider,
1615        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1616    ) -> Result<Vec<ExactDdnnfProgram>> {
1617        epistemic_prob_trace_transaction!(self, {
1618            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1619                provider,
1620                evidence,
1621                "epistemic probabilistic parsed-program exact compile batch production",
1622            )?;
1623
1624            let mut programs = Vec::with_capacity(accepted.len());
1625            for evidence in &accepted {
1626                programs.push(self.compile_program_with_accepted_world_view(program, evidence)?);
1627            }
1628            Ok(programs)
1629        })
1630    }
1631
1632    /// Compile source and evaluate queries through the existing GPU exact path after one accepted gate.
1633    #[cfg(feature = "host-io")]
1634    pub fn compile_and_evaluate_source_with_accepted_world_view(
1635        &mut self,
1636        source: &str,
1637        evidence: &AcceptedWorldViewEvidence,
1638    ) -> Result<ExactResult> {
1639        epistemic_prob_trace_transaction!(self, {
1640            self.require_accepted_evidence(evidence)?;
1641            let production_events_before = self.trace.checked_gpu_production_path_events()?;
1642            let program = ExactDdnnfProgram::compile_source_with_gpu(source, self.config)?;
1643            require_gpu_exact_backend(
1644                &program,
1645                "epistemic probabilistic source exact compile/evaluate",
1646            )?;
1647            checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
1648            let result = program.evaluate()?;
1649            checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
1650            checked_prob_trace_counter_inc!(self, gpu_source_exact_query_evaluations);
1651            checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
1652            checked_prob_trace_counter_inc!(self, gpu_source_knowledge_compilation_end_to_end_runs);
1653            self.record_accepted_gpu_production_path_events_since(production_events_before)?;
1654            self.record_accepted_evidence(evidence)?;
1655            self.trace.require_zero_cpu_recompute()?;
1656            Ok(result)
1657        })
1658    }
1659
1660    /// Compile source and evaluate queries after accepted GPU epistemic execution.
1661    #[cfg(feature = "host-io")]
1662    pub fn compile_and_evaluate_source_with_gpu_execution_result(
1663        &mut self,
1664        source: &str,
1665        provider: &CudaKernelProvider,
1666        result: &EpistemicGpuExecutionResult,
1667        assumptions: Vec<EpistemicAssumption>,
1668    ) -> Result<ExactResult> {
1669        let evidence =
1670            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1671        self.compile_and_evaluate_source_with_accepted_world_view(source, &evidence)
1672    }
1673
1674    /// Compile and evaluate source once per accepted GPU epistemic execution result.
1675    #[cfg(feature = "host-io")]
1676    pub fn compile_and_evaluate_source_for_gpu_execution_results(
1677        &mut self,
1678        source: &str,
1679        provider: &CudaKernelProvider,
1680        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1681    ) -> Result<Vec<ExactResult>> {
1682        epistemic_prob_trace_transaction!(self, {
1683            if evidence_records.is_empty() {
1684                return Err(XlogError::UnsupportedEpistemicConstruct {
1685                    construct: "epistemic probabilistic production batch".to_string(),
1686                    context:
1687                        "batched knowledge compilation requires at least one accepted GPU result"
1688                            .to_string(),
1689                });
1690            }
1691
1692            let mut accepted = Vec::with_capacity(evidence_records.len());
1693            for record in evidence_records {
1694                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1695                    provider,
1696                    record.result,
1697                    record.assumptions.to_vec(),
1698                )?);
1699            }
1700
1701            let mut results = Vec::with_capacity(accepted.len());
1702            for evidence in &accepted {
1703                results.push(
1704                    self.compile_and_evaluate_source_with_accepted_world_view(source, evidence)?,
1705                );
1706            }
1707            Ok(results)
1708        })
1709    }
1710
1711    /// Compile and evaluate source once per accepted split/batch GPU epistemic component.
1712    #[cfg(feature = "host-io")]
1713    pub fn compile_and_evaluate_source_for_gpu_batch_execution_result(
1714        &mut self,
1715        source: &str,
1716        provider: &CudaKernelProvider,
1717        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1718    ) -> Result<Vec<ExactResult>> {
1719        epistemic_prob_trace_transaction!(self, {
1720            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1721                provider,
1722                evidence,
1723                "epistemic probabilistic batch production",
1724            )?;
1725
1726            let mut results = Vec::with_capacity(accepted.len());
1727            for evidence in &accepted {
1728                results.push(
1729                    self.compile_and_evaluate_source_with_accepted_world_view(source, evidence)?,
1730                );
1731            }
1732            Ok(results)
1733        })
1734    }
1735
1736    /// Compile source with accepted zero-arity epistemic assumptions as exact evidence.
1737    #[cfg(feature = "host-io")]
1738    pub fn compile_and_evaluate_conditioned_source_with_accepted_world_view(
1739        &mut self,
1740        source: &str,
1741        evidence: &AcceptedWorldViewEvidence,
1742    ) -> Result<ExactResult> {
1743        epistemic_prob_trace_transaction!(self, {
1744            let program = parse_program(source)?;
1745            let provenance = extract_from_program(&program)?;
1746            self.compile_and_evaluate_conditioned_program_with_path(
1747                &program,
1748                &provenance,
1749                evidence,
1750                EpistemicProbConditionedEvidencePath::Source,
1751                "epistemic probabilistic conditioned source exact compile/evaluate",
1752            )
1753        })
1754    }
1755
1756    /// Compile source with accepted GPU epistemic assumptions as exact evidence.
1757    #[cfg(feature = "host-io")]
1758    pub fn compile_and_evaluate_conditioned_source_with_gpu_execution_result(
1759        &mut self,
1760        source: &str,
1761        provider: &CudaKernelProvider,
1762        result: &EpistemicGpuExecutionResult,
1763        assumptions: Vec<EpistemicAssumption>,
1764    ) -> Result<ExactResult> {
1765        epistemic_prob_trace_transaction!(self, {
1766            let auto_derived = assumptions.is_empty();
1767            let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
1768                provider,
1769                result,
1770                assumptions,
1771            )?;
1772            let program = parse_program(source)?;
1773            let provenance = extract_from_program(&program)?;
1774            let filtered_evidence;
1775            let evidence = if auto_derived {
1776                filtered_evidence =
1777                    evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
1778                &filtered_evidence
1779            } else {
1780                &evidence
1781            };
1782            self.compile_and_evaluate_conditioned_program_with_path(
1783                &program,
1784                &provenance,
1785                evidence,
1786                EpistemicProbConditionedEvidencePath::Source,
1787                "epistemic probabilistic conditioned source exact compile/evaluate",
1788            )
1789        })
1790    }
1791
1792    /// Compile conditioned source once per accepted GPU epistemic execution result.
1793    #[cfg(feature = "host-io")]
1794    pub fn compile_and_evaluate_conditioned_source_for_gpu_execution_results(
1795        &mut self,
1796        source: &str,
1797        provider: &CudaKernelProvider,
1798        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1799    ) -> Result<Vec<ExactResult>> {
1800        epistemic_prob_trace_transaction!(self, {
1801            if evidence_records.is_empty() {
1802                return Err(XlogError::UnsupportedEpistemicConstruct {
1803                    construct: "epistemic probabilistic conditioned production batch".to_string(),
1804                    context: "batched conditioned knowledge compilation requires at least one accepted GPU result"
1805                        .to_string(),
1806                });
1807            }
1808
1809            let mut accepted = Vec::with_capacity(evidence_records.len());
1810            for record in evidence_records {
1811                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1812                    provider,
1813                    record.result,
1814                    record.assumptions.to_vec(),
1815                )?);
1816            }
1817
1818            let program = parse_program(source)?;
1819            let provenance = extract_from_program(&program)?;
1820            let mut results = Vec::with_capacity(accepted.len());
1821            for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
1822                let filtered_evidence;
1823                let evidence = if record.assumptions.is_empty() {
1824                    filtered_evidence =
1825                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
1826                    &filtered_evidence
1827                } else {
1828                    evidence
1829                };
1830                results.push(self.compile_and_evaluate_conditioned_program_with_path(
1831                    &program,
1832                    &provenance,
1833                    evidence,
1834                    EpistemicProbConditionedEvidencePath::Source,
1835                    "epistemic probabilistic conditioned source exact compile/evaluate",
1836                )?);
1837            }
1838            Ok(results)
1839        })
1840    }
1841
1842    /// Compile conditioned source once per accepted split/batch GPU epistemic component.
1843    #[cfg(feature = "host-io")]
1844    pub fn compile_and_evaluate_conditioned_source_for_gpu_batch_execution_result(
1845        &mut self,
1846        source: &str,
1847        provider: &CudaKernelProvider,
1848        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1849    ) -> Result<Vec<ExactResult>> {
1850        epistemic_prob_trace_transaction!(self, {
1851            let auto_derived_by_component = evidence
1852                .assumptions_by_component
1853                .iter()
1854                .map(|assumptions| assumptions.is_empty())
1855                .collect::<Vec<_>>();
1856            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1857                provider,
1858                evidence,
1859                "epistemic probabilistic batch production",
1860            )?;
1861
1862            let program = parse_program(source)?;
1863            let provenance = extract_from_program(&program)?;
1864            let mut results = Vec::with_capacity(accepted.len());
1865            for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
1866                let filtered_evidence;
1867                let evidence = if *auto_derived {
1868                    filtered_evidence =
1869                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
1870                    &filtered_evidence
1871                } else {
1872                    evidence
1873                };
1874                results.push(self.compile_and_evaluate_conditioned_program_with_path(
1875                    &program,
1876                    &provenance,
1877                    evidence,
1878                    EpistemicProbConditionedEvidencePath::Source,
1879                    "epistemic probabilistic conditioned source exact compile/evaluate",
1880                )?);
1881            }
1882            Ok(results)
1883        })
1884    }
1885
1886    /// Compile source with accepted epistemic assumptions as exact evidence and evaluate gradients.
1887    #[cfg(feature = "host-io")]
1888    pub fn compile_and_evaluate_conditioned_source_with_grads_with_accepted_world_view(
1889        &mut self,
1890        source: &str,
1891        evidence: &AcceptedWorldViewEvidence,
1892    ) -> Result<ExactResultWithGrads> {
1893        epistemic_prob_trace_transaction!(self, {
1894            let program = parse_program(source)?;
1895            let provenance = extract_from_program(&program)?;
1896            self.compile_and_evaluate_conditioned_program_with_grads_with_path(
1897                &program,
1898                &provenance,
1899                evidence,
1900                EpistemicProbConditionedEvidencePath::Source,
1901                "epistemic probabilistic conditioned source exact gradient",
1902            )
1903        })
1904    }
1905
1906    /// Compile source with accepted GPU epistemic assumptions as exact evidence and evaluate gradients.
1907    #[cfg(feature = "host-io")]
1908    pub fn compile_and_evaluate_conditioned_source_with_grads_with_gpu_execution_result(
1909        &mut self,
1910        source: &str,
1911        provider: &CudaKernelProvider,
1912        result: &EpistemicGpuExecutionResult,
1913        assumptions: Vec<EpistemicAssumption>,
1914    ) -> Result<ExactResultWithGrads> {
1915        epistemic_prob_trace_transaction!(self, {
1916            let auto_derived = assumptions.is_empty();
1917            let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
1918                provider,
1919                result,
1920                assumptions,
1921            )?;
1922            let program = parse_program(source)?;
1923            let provenance = extract_from_program(&program)?;
1924            let filtered_evidence;
1925            let evidence = if auto_derived {
1926                filtered_evidence =
1927                    evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
1928                &filtered_evidence
1929            } else {
1930                &evidence
1931            };
1932            self.compile_and_evaluate_conditioned_program_with_grads_with_path(
1933                &program,
1934                &provenance,
1935                evidence,
1936                EpistemicProbConditionedEvidencePath::Source,
1937                "epistemic probabilistic conditioned source exact gradient",
1938            )
1939        })
1940    }
1941
1942    /// Compile conditioned source gradients once per accepted GPU epistemic execution result.
1943    #[cfg(feature = "host-io")]
1944    pub fn compile_and_evaluate_conditioned_source_with_grads_for_gpu_execution_results(
1945        &mut self,
1946        source: &str,
1947        provider: &CudaKernelProvider,
1948        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1949    ) -> Result<Vec<ExactResultWithGrads>> {
1950        epistemic_prob_trace_transaction!(self, {
1951            if evidence_records.is_empty() {
1952                return Err(XlogError::UnsupportedEpistemicConstruct {
1953                    construct: "epistemic probabilistic conditioned gradient production batch"
1954                        .to_string(),
1955                    context: "batched conditioned gradient compilation requires at least one accepted GPU result"
1956                        .to_string(),
1957                });
1958            }
1959
1960            let mut accepted = Vec::with_capacity(evidence_records.len());
1961            for record in evidence_records {
1962                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1963                    provider,
1964                    record.result,
1965                    record.assumptions.to_vec(),
1966                )?);
1967            }
1968
1969            let program = parse_program(source)?;
1970            let provenance = extract_from_program(&program)?;
1971            let mut results = Vec::with_capacity(accepted.len());
1972            for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
1973                let filtered_evidence;
1974                let evidence = if record.assumptions.is_empty() {
1975                    filtered_evidence =
1976                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
1977                    &filtered_evidence
1978                } else {
1979                    evidence
1980                };
1981                results.push(
1982                    self.compile_and_evaluate_conditioned_program_with_grads_with_path(
1983                        &program,
1984                        &provenance,
1985                        evidence,
1986                        EpistemicProbConditionedEvidencePath::Source,
1987                        "epistemic probabilistic conditioned source exact gradient",
1988                    )?,
1989                );
1990            }
1991            Ok(results)
1992        })
1993    }
1994
1995    /// Compile conditioned source gradients once per accepted split/batch GPU epistemic component.
1996    #[cfg(feature = "host-io")]
1997    pub fn compile_and_evaluate_conditioned_source_with_grads_for_gpu_batch_execution_result(
1998        &mut self,
1999        source: &str,
2000        provider: &CudaKernelProvider,
2001        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2002    ) -> Result<Vec<ExactResultWithGrads>> {
2003        epistemic_prob_trace_transaction!(self, {
2004            let auto_derived_by_component = evidence
2005                .assumptions_by_component
2006                .iter()
2007                .map(|assumptions| assumptions.is_empty())
2008                .collect::<Vec<_>>();
2009            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2010                provider,
2011                evidence,
2012                "epistemic probabilistic batch production",
2013            )?;
2014
2015            let program = parse_program(source)?;
2016            let provenance = extract_from_program(&program)?;
2017            let mut results = Vec::with_capacity(accepted.len());
2018            for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2019                let filtered_evidence;
2020                let evidence = if *auto_derived {
2021                    filtered_evidence =
2022                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2023                    &filtered_evidence
2024                } else {
2025                    evidence
2026                };
2027                results.push(
2028                    self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2029                        &program,
2030                        &provenance,
2031                        evidence,
2032                        EpistemicProbConditionedEvidencePath::Source,
2033                        "epistemic probabilistic conditioned source exact gradient",
2034                    )?,
2035                );
2036            }
2037            Ok(results)
2038        })
2039    }
2040
2041    #[cfg(feature = "host-io")]
2042    fn compile_and_evaluate_conditioned_program_with_path(
2043        &mut self,
2044        program: &Program,
2045        provenance: &Provenance,
2046        evidence: &AcceptedWorldViewEvidence,
2047        path: EpistemicProbConditionedEvidencePath,
2048        backend_context: &'static str,
2049    ) -> Result<ExactResult> {
2050        self.require_accepted_evidence(evidence)?;
2051        let production_events_before = self.trace.checked_gpu_production_path_events()?;
2052        let (program, evidence_counts) = condition_program_with_accepted_evidence_using_provenance(
2053            program, provenance, evidence,
2054        )?;
2055        let exact = ExactDdnnfProgram::compile_from_program(&program, self.config)?;
2056        require_gpu_exact_backend(&exact, backend_context)?;
2057        match path {
2058            EpistemicProbConditionedEvidencePath::Source => {
2059                checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
2060            }
2061            EpistemicProbConditionedEvidencePath::Program => {
2062                checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
2063            }
2064        }
2065        self.record_conditioned_evidence_counts(evidence_counts, path)?;
2066        let result = exact.evaluate()?;
2067        checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
2068        checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
2069        match path {
2070            EpistemicProbConditionedEvidencePath::Source => {
2071                checked_prob_trace_counter_inc!(self, gpu_source_exact_query_evaluations);
2072                checked_prob_trace_counter_inc!(
2073                    self,
2074                    gpu_source_knowledge_compilation_end_to_end_runs
2075                );
2076            }
2077            EpistemicProbConditionedEvidencePath::Program => {
2078                checked_prob_trace_counter_inc!(self, gpu_program_exact_query_evaluations);
2079                checked_prob_trace_counter_inc!(
2080                    self,
2081                    gpu_program_knowledge_compilation_end_to_end_runs
2082                );
2083            }
2084        }
2085        self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2086        self.record_accepted_evidence(evidence)?;
2087        self.trace.require_zero_cpu_recompute()?;
2088        Ok(result)
2089    }
2090
2091    #[cfg(feature = "host-io")]
2092    fn compile_and_evaluate_conditioned_program_with_grads_with_path(
2093        &mut self,
2094        program: &Program,
2095        provenance: &Provenance,
2096        evidence: &AcceptedWorldViewEvidence,
2097        path: EpistemicProbConditionedEvidencePath,
2098        backend_context: &'static str,
2099    ) -> Result<ExactResultWithGrads> {
2100        self.require_accepted_evidence(evidence)?;
2101        let production_events_before = self.trace.checked_gpu_production_path_events()?;
2102        let (program, evidence_counts) = condition_program_with_accepted_evidence_using_provenance(
2103            program, provenance, evidence,
2104        )?;
2105        let exact = ExactDdnnfProgram::compile_from_program(&program, self.config)?;
2106        require_gpu_exact_backend(&exact, backend_context)?;
2107        match path {
2108            EpistemicProbConditionedEvidencePath::Source => {
2109                checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
2110            }
2111            EpistemicProbConditionedEvidencePath::Program => {
2112                checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
2113            }
2114        }
2115        self.record_conditioned_evidence_counts(evidence_counts, path)?;
2116        let result = exact.evaluate_gpu_with_grads()?;
2117        let origin = match path {
2118            EpistemicProbConditionedEvidencePath::Source => ExactProgramOrigin::Source,
2119            EpistemicProbConditionedEvidencePath::Program => ExactProgramOrigin::Program,
2120        };
2121        self.record_gpu_exact_gradient_evaluation_for_origin(origin)?;
2122        checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
2123        match path {
2124            EpistemicProbConditionedEvidencePath::Source => {
2125                checked_prob_trace_counter_inc!(self, gpu_source_conditioned_gradient_evaluations);
2126                checked_prob_trace_counter_inc!(
2127                    self,
2128                    gpu_source_knowledge_compilation_end_to_end_runs
2129                );
2130            }
2131            EpistemicProbConditionedEvidencePath::Program => {
2132                checked_prob_trace_counter_inc!(self, gpu_program_conditioned_gradient_evaluations);
2133                checked_prob_trace_counter_inc!(
2134                    self,
2135                    gpu_program_knowledge_compilation_end_to_end_runs
2136                );
2137            }
2138        }
2139        self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2140        self.record_accepted_evidence(evidence)?;
2141        self.trace.require_zero_cpu_recompute()?;
2142        Ok(result)
2143    }
2144
2145    /// Compile a parsed program with accepted epistemic assumptions as exact evidence.
2146    #[cfg(feature = "host-io")]
2147    pub fn compile_and_evaluate_conditioned_program_with_accepted_world_view(
2148        &mut self,
2149        program: &Program,
2150        evidence: &AcceptedWorldViewEvidence,
2151    ) -> Result<ExactResult> {
2152        epistemic_prob_trace_transaction!(self, {
2153            let provenance = extract_from_program(program)?;
2154            self.compile_and_evaluate_conditioned_program_with_path(
2155                program,
2156                &provenance,
2157                evidence,
2158                EpistemicProbConditionedEvidencePath::Program,
2159                "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2160            )
2161        })
2162    }
2163
2164    /// Compile a parsed program with accepted GPU epistemic assumptions as exact evidence.
2165    #[cfg(feature = "host-io")]
2166    pub fn compile_and_evaluate_conditioned_program_with_gpu_execution_result(
2167        &mut self,
2168        program: &Program,
2169        provider: &CudaKernelProvider,
2170        result: &EpistemicGpuExecutionResult,
2171        assumptions: Vec<EpistemicAssumption>,
2172    ) -> Result<ExactResult> {
2173        epistemic_prob_trace_transaction!(self, {
2174            let auto_derived = assumptions.is_empty();
2175            let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2176                provider,
2177                result,
2178                assumptions,
2179            )?;
2180            let provenance = extract_from_program(program)?;
2181            let filtered_evidence;
2182            let evidence = if auto_derived {
2183                filtered_evidence =
2184                    evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
2185                &filtered_evidence
2186            } else {
2187                &evidence
2188            };
2189            self.compile_and_evaluate_conditioned_program_with_path(
2190                program,
2191                &provenance,
2192                evidence,
2193                EpistemicProbConditionedEvidencePath::Program,
2194                "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2195            )
2196        })
2197    }
2198
2199    /// Compile conditioned parsed program once per accepted GPU epistemic execution result.
2200    #[cfg(feature = "host-io")]
2201    pub fn compile_and_evaluate_conditioned_program_for_gpu_execution_results(
2202        &mut self,
2203        program: &Program,
2204        provider: &CudaKernelProvider,
2205        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2206    ) -> Result<Vec<ExactResult>> {
2207        epistemic_prob_trace_transaction!(self, {
2208            if evidence_records.is_empty() {
2209                return Err(XlogError::UnsupportedEpistemicConstruct {
2210                    construct: "epistemic probabilistic conditioned production batch".to_string(),
2211                    context: "batched conditioned program compilation requires at least one accepted GPU result"
2212                        .to_string(),
2213                });
2214            }
2215
2216            let mut accepted = Vec::with_capacity(evidence_records.len());
2217            for record in evidence_records {
2218                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2219                    provider,
2220                    record.result,
2221                    record.assumptions.to_vec(),
2222                )?);
2223            }
2224
2225            let provenance = extract_from_program(program)?;
2226            let mut results = Vec::with_capacity(accepted.len());
2227            for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2228                let filtered_evidence;
2229                let evidence = if record.assumptions.is_empty() {
2230                    filtered_evidence =
2231                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2232                    &filtered_evidence
2233                } else {
2234                    evidence
2235                };
2236                results.push(self.compile_and_evaluate_conditioned_program_with_path(
2237                    program,
2238                    &provenance,
2239                    evidence,
2240                    EpistemicProbConditionedEvidencePath::Program,
2241                    "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2242                )?);
2243            }
2244            Ok(results)
2245        })
2246    }
2247
2248    /// Compile conditioned parsed program once per accepted split/batch GPU epistemic component.
2249    #[cfg(feature = "host-io")]
2250    pub fn compile_and_evaluate_conditioned_program_for_gpu_batch_execution_result(
2251        &mut self,
2252        program: &Program,
2253        provider: &CudaKernelProvider,
2254        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2255    ) -> Result<Vec<ExactResult>> {
2256        epistemic_prob_trace_transaction!(self, {
2257            let auto_derived_by_component = evidence
2258                .assumptions_by_component
2259                .iter()
2260                .map(|assumptions| assumptions.is_empty())
2261                .collect::<Vec<_>>();
2262            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2263                provider,
2264                evidence,
2265                "epistemic probabilistic batch production",
2266            )?;
2267
2268            let provenance = extract_from_program(program)?;
2269            let mut results = Vec::with_capacity(accepted.len());
2270            for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2271                let filtered_evidence;
2272                let evidence = if *auto_derived {
2273                    filtered_evidence =
2274                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2275                    &filtered_evidence
2276                } else {
2277                    evidence
2278                };
2279                results.push(self.compile_and_evaluate_conditioned_program_with_path(
2280                    program,
2281                    &provenance,
2282                    evidence,
2283                    EpistemicProbConditionedEvidencePath::Program,
2284                    "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2285                )?);
2286            }
2287            Ok(results)
2288        })
2289    }
2290
2291    /// Compile a parsed program with accepted epistemic assumptions as exact evidence and evaluate gradients.
2292    #[cfg(feature = "host-io")]
2293    pub fn compile_and_evaluate_conditioned_program_with_grads_with_accepted_world_view(
2294        &mut self,
2295        program: &Program,
2296        evidence: &AcceptedWorldViewEvidence,
2297    ) -> Result<ExactResultWithGrads> {
2298        epistemic_prob_trace_transaction!(self, {
2299            let provenance = extract_from_program(program)?;
2300            self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2301                program,
2302                &provenance,
2303                evidence,
2304                EpistemicProbConditionedEvidencePath::Program,
2305                "epistemic probabilistic conditioned parsed-program exact gradient",
2306            )
2307        })
2308    }
2309
2310    /// Compile a parsed program with accepted GPU epistemic assumptions as exact evidence and evaluate gradients.
2311    #[cfg(feature = "host-io")]
2312    pub fn compile_and_evaluate_conditioned_program_with_grads_with_gpu_execution_result(
2313        &mut self,
2314        program: &Program,
2315        provider: &CudaKernelProvider,
2316        result: &EpistemicGpuExecutionResult,
2317        assumptions: Vec<EpistemicAssumption>,
2318    ) -> Result<ExactResultWithGrads> {
2319        epistemic_prob_trace_transaction!(self, {
2320            let auto_derived = assumptions.is_empty();
2321            let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2322                provider,
2323                result,
2324                assumptions,
2325            )?;
2326            let provenance = extract_from_program(program)?;
2327            let filtered_evidence;
2328            let evidence = if auto_derived {
2329                filtered_evidence =
2330                    evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
2331                &filtered_evidence
2332            } else {
2333                &evidence
2334            };
2335            self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2336                program,
2337                &provenance,
2338                evidence,
2339                EpistemicProbConditionedEvidencePath::Program,
2340                "epistemic probabilistic conditioned parsed-program exact gradient",
2341            )
2342        })
2343    }
2344
2345    /// Compile conditioned parsed-program gradients once per accepted GPU epistemic execution result.
2346    #[cfg(feature = "host-io")]
2347    pub fn compile_and_evaluate_conditioned_program_with_grads_for_gpu_execution_results(
2348        &mut self,
2349        program: &Program,
2350        provider: &CudaKernelProvider,
2351        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2352    ) -> Result<Vec<ExactResultWithGrads>> {
2353        epistemic_prob_trace_transaction!(self, {
2354            if evidence_records.is_empty() {
2355                return Err(XlogError::UnsupportedEpistemicConstruct {
2356                    construct: "epistemic probabilistic conditioned gradient production batch"
2357                        .to_string(),
2358                    context: "batched conditioned program gradient compilation requires at least one accepted GPU result"
2359                        .to_string(),
2360                });
2361            }
2362
2363            let mut accepted = Vec::with_capacity(evidence_records.len());
2364            for record in evidence_records {
2365                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2366                    provider,
2367                    record.result,
2368                    record.assumptions.to_vec(),
2369                )?);
2370            }
2371
2372            let provenance = extract_from_program(program)?;
2373            let mut results = Vec::with_capacity(accepted.len());
2374            for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2375                let filtered_evidence;
2376                let evidence = if record.assumptions.is_empty() {
2377                    filtered_evidence =
2378                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2379                    &filtered_evidence
2380                } else {
2381                    evidence
2382                };
2383                results.push(
2384                    self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2385                        program,
2386                        &provenance,
2387                        evidence,
2388                        EpistemicProbConditionedEvidencePath::Program,
2389                        "epistemic probabilistic conditioned parsed-program exact gradient",
2390                    )?,
2391                );
2392            }
2393            Ok(results)
2394        })
2395    }
2396
2397    /// Compile conditioned parsed-program gradients once per accepted split/batch GPU epistemic component.
2398    #[cfg(feature = "host-io")]
2399    pub fn compile_and_evaluate_conditioned_program_with_grads_for_gpu_batch_execution_result(
2400        &mut self,
2401        program: &Program,
2402        provider: &CudaKernelProvider,
2403        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2404    ) -> Result<Vec<ExactResultWithGrads>> {
2405        epistemic_prob_trace_transaction!(self, {
2406            let auto_derived_by_component = evidence
2407                .assumptions_by_component
2408                .iter()
2409                .map(|assumptions| assumptions.is_empty())
2410                .collect::<Vec<_>>();
2411            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2412                provider,
2413                evidence,
2414                "epistemic probabilistic batch production",
2415            )?;
2416
2417            let provenance = extract_from_program(program)?;
2418            let mut results = Vec::with_capacity(accepted.len());
2419            for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2420                let filtered_evidence;
2421                let evidence = if *auto_derived {
2422                    filtered_evidence =
2423                        evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2424                    &filtered_evidence
2425                } else {
2426                    evidence
2427                };
2428                results.push(
2429                    self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2430                        program,
2431                        &provenance,
2432                        evidence,
2433                        EpistemicProbConditionedEvidencePath::Program,
2434                        "epistemic probabilistic conditioned parsed-program exact gradient",
2435                    )?,
2436                );
2437            }
2438            Ok(results)
2439        })
2440    }
2441
2442    /// Compile a parsed program and evaluate queries through the existing GPU exact path.
2443    #[cfg(feature = "host-io")]
2444    pub fn compile_and_evaluate_program_with_accepted_world_view(
2445        &mut self,
2446        program: &Program,
2447        evidence: &AcceptedWorldViewEvidence,
2448    ) -> Result<ExactResult> {
2449        epistemic_prob_trace_transaction!(self, {
2450            self.require_accepted_evidence(evidence)?;
2451            let production_events_before = self.trace.checked_gpu_production_path_events()?;
2452            let exact = ExactDdnnfProgram::compile_from_program(program, self.config)?;
2453            require_gpu_exact_backend(
2454                &exact,
2455                "epistemic probabilistic parsed-program exact compile/evaluate",
2456            )?;
2457            checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
2458            let result = exact.evaluate()?;
2459            checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
2460            checked_prob_trace_counter_inc!(self, gpu_program_exact_query_evaluations);
2461            checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
2462            checked_prob_trace_counter_inc!(
2463                self,
2464                gpu_program_knowledge_compilation_end_to_end_runs
2465            );
2466            self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2467            self.record_accepted_evidence(evidence)?;
2468            self.trace.require_zero_cpu_recompute()?;
2469            Ok(result)
2470        })
2471    }
2472
2473    /// Compile a parsed program and evaluate queries after accepted GPU epistemic execution.
2474    #[cfg(feature = "host-io")]
2475    pub fn compile_and_evaluate_program_with_gpu_execution_result(
2476        &mut self,
2477        program: &Program,
2478        provider: &CudaKernelProvider,
2479        result: &EpistemicGpuExecutionResult,
2480        assumptions: Vec<EpistemicAssumption>,
2481    ) -> Result<ExactResult> {
2482        let evidence =
2483            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
2484        self.compile_and_evaluate_program_with_accepted_world_view(program, &evidence)
2485    }
2486
2487    /// Compile and evaluate a parsed program once per accepted GPU epistemic execution result.
2488    #[cfg(feature = "host-io")]
2489    pub fn compile_and_evaluate_program_for_gpu_execution_results(
2490        &mut self,
2491        program: &Program,
2492        provider: &CudaKernelProvider,
2493        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2494    ) -> Result<Vec<ExactResult>> {
2495        epistemic_prob_trace_transaction!(self, {
2496            if evidence_records.is_empty() {
2497                return Err(XlogError::UnsupportedEpistemicConstruct {
2498                    construct: "epistemic probabilistic parsed-program production batch"
2499                        .to_string(),
2500                    context: "batched parsed-program knowledge compilation requires at least one accepted GPU result"
2501                        .to_string(),
2502                });
2503            }
2504
2505            let mut accepted = Vec::with_capacity(evidence_records.len());
2506            for record in evidence_records {
2507                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2508                    provider,
2509                    record.result,
2510                    record.assumptions.to_vec(),
2511                )?);
2512            }
2513
2514            let mut results = Vec::with_capacity(accepted.len());
2515            for evidence in &accepted {
2516                results.push(
2517                    self.compile_and_evaluate_program_with_accepted_world_view(program, evidence)?,
2518                );
2519            }
2520            Ok(results)
2521        })
2522    }
2523
2524    /// Compile and evaluate a parsed program once per accepted split/batch GPU epistemic component.
2525    #[cfg(feature = "host-io")]
2526    pub fn compile_and_evaluate_program_for_gpu_batch_execution_result(
2527        &mut self,
2528        program: &Program,
2529        provider: &CudaKernelProvider,
2530        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2531    ) -> Result<Vec<ExactResult>> {
2532        epistemic_prob_trace_transaction!(self, {
2533            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2534                provider,
2535                evidence,
2536                "epistemic probabilistic batch production",
2537            )?;
2538
2539            let mut results = Vec::with_capacity(accepted.len());
2540            for evidence in &accepted {
2541                results.push(
2542                    self.compile_and_evaluate_program_with_accepted_world_view(program, evidence)?,
2543                );
2544            }
2545            Ok(results)
2546        })
2547    }
2548
2549    /// Encode source through the existing GPU PIR and CNF production path.
2550    pub fn encode_source_pir_cnf_with_accepted_world_view(
2551        &mut self,
2552        source: &str,
2553        provider: &Arc<CudaKernelProvider>,
2554        evidence: &AcceptedWorldViewEvidence,
2555    ) -> Result<EpistemicProbPirCnfEvidence> {
2556        epistemic_prob_trace_transaction!(self, {
2557            self.require_accepted_evidence(evidence)?;
2558            let program = parse_program(source)?;
2559            let base_provenance = extract_from_program(&program)?;
2560            self.encode_program_pir_cnf_with_base_provenance(
2561                &program,
2562                &base_provenance,
2563                provider,
2564                evidence,
2565                EpistemicProbPirCnfPath::Source,
2566            )
2567        })
2568    }
2569
2570    /// Encode source PIR/CNF after accepted GPU epistemic execution.
2571    pub fn encode_source_pir_cnf_with_gpu_execution_result(
2572        &mut self,
2573        source: &str,
2574        provider: &Arc<CudaKernelProvider>,
2575        result: &EpistemicGpuExecutionResult,
2576        assumptions: Vec<EpistemicAssumption>,
2577    ) -> Result<EpistemicProbPirCnfEvidence> {
2578        epistemic_prob_trace_transaction!(self, {
2579            let auto_derived = assumptions.is_empty();
2580            let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2581                provider,
2582                result,
2583                assumptions,
2584            )?;
2585            let program = parse_program(source)?;
2586            let base_provenance = extract_from_program(&program)?;
2587            let filtered_evidence;
2588            let evidence = if auto_derived {
2589                filtered_evidence =
2590                    evidence_with_provenance_backed_assumptions(&evidence, &base_provenance)?;
2591                &filtered_evidence
2592            } else {
2593                &evidence
2594            };
2595            self.encode_program_pir_cnf_with_base_provenance(
2596                &program,
2597                &base_provenance,
2598                provider,
2599                evidence,
2600                EpistemicProbPirCnfPath::Source,
2601            )
2602        })
2603    }
2604
2605    /// Encode source PIR/CNF once per accepted GPU epistemic execution result.
2606    pub fn encode_source_pir_cnf_for_gpu_execution_results(
2607        &mut self,
2608        source: &str,
2609        provider: &Arc<CudaKernelProvider>,
2610        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2611    ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2612        epistemic_prob_trace_transaction!(self, {
2613            if evidence_records.is_empty() {
2614                return Err(XlogError::UnsupportedEpistemicConstruct {
2615                    construct: "epistemic probabilistic source PIR/CNF production batch"
2616                        .to_string(),
2617                    context:
2618                        "batched source PIR/CNF encoding requires at least one accepted GPU result"
2619                            .to_string(),
2620                });
2621            }
2622
2623            let mut accepted = Vec::with_capacity(evidence_records.len());
2624            for record in evidence_records {
2625                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2626                    provider,
2627                    record.result,
2628                    record.assumptions.to_vec(),
2629                )?);
2630            }
2631
2632            let program = parse_program(source)?;
2633            let base_provenance = extract_from_program(&program)?;
2634            let mut results = Vec::with_capacity(accepted.len());
2635            for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2636                let filtered_evidence;
2637                let evidence = if record.assumptions.is_empty() {
2638                    filtered_evidence =
2639                        evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2640                    &filtered_evidence
2641                } else {
2642                    evidence
2643                };
2644                results.push(self.encode_program_pir_cnf_with_base_provenance(
2645                    &program,
2646                    &base_provenance,
2647                    provider,
2648                    evidence,
2649                    EpistemicProbPirCnfPath::Source,
2650                )?);
2651            }
2652            Ok(results)
2653        })
2654    }
2655
2656    /// Encode source PIR/CNF once per accepted split/batch GPU epistemic component.
2657    pub fn encode_source_pir_cnf_for_gpu_batch_execution_result(
2658        &mut self,
2659        source: &str,
2660        provider: &Arc<CudaKernelProvider>,
2661        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2662    ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2663        epistemic_prob_trace_transaction!(self, {
2664            let auto_derived_by_component = evidence
2665                .assumptions_by_component
2666                .iter()
2667                .map(|assumptions| assumptions.is_empty())
2668                .collect::<Vec<_>>();
2669            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2670                provider.as_ref(),
2671                evidence,
2672                "epistemic probabilistic source PIR/CNF batch production",
2673            )?;
2674
2675            let program = parse_program(source)?;
2676            let base_provenance = extract_from_program(&program)?;
2677            let mut results = Vec::with_capacity(accepted.len());
2678            for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2679                let filtered_evidence;
2680                let evidence = if *auto_derived {
2681                    filtered_evidence =
2682                        evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2683                    &filtered_evidence
2684                } else {
2685                    evidence
2686                };
2687                results.push(self.encode_program_pir_cnf_with_base_provenance(
2688                    &program,
2689                    &base_provenance,
2690                    provider,
2691                    evidence,
2692                    EpistemicProbPirCnfPath::Source,
2693                )?);
2694            }
2695            Ok(results)
2696        })
2697    }
2698
2699    /// Encode a parsed program through the existing GPU PIR and CNF production path.
2700    pub fn encode_program_pir_cnf_with_accepted_world_view(
2701        &mut self,
2702        program: &Program,
2703        provider: &Arc<CudaKernelProvider>,
2704        evidence: &AcceptedWorldViewEvidence,
2705    ) -> Result<EpistemicProbPirCnfEvidence> {
2706        epistemic_prob_trace_transaction!(self, {
2707            self.require_accepted_evidence(evidence)?;
2708            let base_provenance = extract_from_program(program)?;
2709            self.encode_program_pir_cnf_with_base_provenance(
2710                program,
2711                &base_provenance,
2712                provider,
2713                evidence,
2714                EpistemicProbPirCnfPath::Program,
2715            )
2716        })
2717    }
2718
2719    /// Encode parsed-program PIR/CNF after accepted GPU epistemic execution.
2720    pub fn encode_program_pir_cnf_with_gpu_execution_result(
2721        &mut self,
2722        program: &Program,
2723        provider: &Arc<CudaKernelProvider>,
2724        result: &EpistemicGpuExecutionResult,
2725        assumptions: Vec<EpistemicAssumption>,
2726    ) -> Result<EpistemicProbPirCnfEvidence> {
2727        epistemic_prob_trace_transaction!(self, {
2728            let auto_derived = assumptions.is_empty();
2729            let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2730                provider,
2731                result,
2732                assumptions,
2733            )?;
2734            let base_provenance = extract_from_program(program)?;
2735            let filtered_evidence;
2736            let evidence = if auto_derived {
2737                filtered_evidence =
2738                    evidence_with_provenance_backed_assumptions(&evidence, &base_provenance)?;
2739                &filtered_evidence
2740            } else {
2741                &evidence
2742            };
2743            self.encode_program_pir_cnf_with_base_provenance(
2744                program,
2745                &base_provenance,
2746                provider,
2747                evidence,
2748                EpistemicProbPirCnfPath::Program,
2749            )
2750        })
2751    }
2752
2753    /// Encode parsed-program PIR/CNF once per accepted GPU epistemic execution result.
2754    pub fn encode_program_pir_cnf_for_gpu_execution_results(
2755        &mut self,
2756        program: &Program,
2757        provider: &Arc<CudaKernelProvider>,
2758        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2759    ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2760        epistemic_prob_trace_transaction!(self, {
2761            if evidence_records.is_empty() {
2762                return Err(XlogError::UnsupportedEpistemicConstruct {
2763                    construct: "epistemic probabilistic parsed-program PIR/CNF production batch"
2764                        .to_string(),
2765                    context:
2766                        "batched parsed-program PIR/CNF encoding requires at least one accepted GPU result"
2767                            .to_string(),
2768                });
2769            }
2770
2771            let mut accepted = Vec::with_capacity(evidence_records.len());
2772            for record in evidence_records {
2773                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2774                    provider,
2775                    record.result,
2776                    record.assumptions.to_vec(),
2777                )?);
2778            }
2779
2780            let base_provenance = extract_from_program(program)?;
2781            let mut results = Vec::with_capacity(accepted.len());
2782            for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2783                let filtered_evidence;
2784                let evidence = if record.assumptions.is_empty() {
2785                    filtered_evidence =
2786                        evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2787                    &filtered_evidence
2788                } else {
2789                    evidence
2790                };
2791                results.push(self.encode_program_pir_cnf_with_base_provenance(
2792                    program,
2793                    &base_provenance,
2794                    provider,
2795                    evidence,
2796                    EpistemicProbPirCnfPath::Program,
2797                )?);
2798            }
2799            Ok(results)
2800        })
2801    }
2802
2803    /// Encode parsed-program PIR/CNF once per accepted split/batch GPU epistemic component.
2804    pub fn encode_program_pir_cnf_for_gpu_batch_execution_result(
2805        &mut self,
2806        program: &Program,
2807        provider: &Arc<CudaKernelProvider>,
2808        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2809    ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2810        epistemic_prob_trace_transaction!(self, {
2811            let auto_derived_by_component = evidence
2812                .assumptions_by_component
2813                .iter()
2814                .map(|assumptions| assumptions.is_empty())
2815                .collect::<Vec<_>>();
2816            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2817                provider.as_ref(),
2818                evidence,
2819                "epistemic probabilistic parsed-program PIR/CNF batch production",
2820            )?;
2821
2822            let base_provenance = extract_from_program(program)?;
2823            let mut results = Vec::with_capacity(accepted.len());
2824            for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2825                let filtered_evidence;
2826                let evidence = if *auto_derived {
2827                    filtered_evidence =
2828                        evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2829                    &filtered_evidence
2830                } else {
2831                    evidence
2832                };
2833                results.push(self.encode_program_pir_cnf_with_base_provenance(
2834                    program,
2835                    &base_provenance,
2836                    provider,
2837                    evidence,
2838                    EpistemicProbPirCnfPath::Program,
2839                )?);
2840            }
2841            Ok(results)
2842        })
2843    }
2844
2845    /// Evaluate GPU exact query probabilities after accepted world-view evidence was consumed.
2846    #[cfg(feature = "host-io")]
2847    pub fn evaluate(
2848        &mut self,
2849        program: &ExactDdnnfProgram,
2850        evidence: &AcceptedWorldViewEvidence,
2851    ) -> Result<ExactResult> {
2852        epistemic_prob_trace_transaction!(self, {
2853            self.require_accepted_evidence(evidence)?;
2854            let production_events_before = self.trace.checked_gpu_production_path_events()?;
2855            require_gpu_exact_backend(program, "epistemic probabilistic exact query evaluation")?;
2856            let result = program.evaluate()?;
2857            self.record_gpu_exact_query_evaluation(program)?;
2858            self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2859            self.record_accepted_evidence(evidence)?;
2860            self.trace.require_zero_cpu_recompute()?;
2861            Ok(result)
2862        })
2863    }
2864
2865    /// Evaluate GPU exact query probabilities after accepted GPU epistemic execution.
2866    #[cfg(feature = "host-io")]
2867    pub fn evaluate_with_gpu_execution_result(
2868        &mut self,
2869        program: &ExactDdnnfProgram,
2870        provider: &CudaKernelProvider,
2871        result: &EpistemicGpuExecutionResult,
2872        assumptions: Vec<EpistemicAssumption>,
2873    ) -> Result<ExactResult> {
2874        let evidence =
2875            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
2876        self.evaluate(program, &evidence)
2877    }
2878
2879    /// Evaluate GPU exact query probabilities once per accepted GPU epistemic execution result.
2880    #[cfg(feature = "host-io")]
2881    pub fn evaluate_for_gpu_execution_results(
2882        &mut self,
2883        program: &ExactDdnnfProgram,
2884        provider: &CudaKernelProvider,
2885        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2886    ) -> Result<Vec<ExactResult>> {
2887        epistemic_prob_trace_transaction!(self, {
2888            if evidence_records.is_empty() {
2889                return Err(XlogError::UnsupportedEpistemicConstruct {
2890                    construct: "epistemic probabilistic query evaluation production batch"
2891                        .to_string(),
2892                    context: "batched query evaluation requires at least one accepted GPU result"
2893                        .to_string(),
2894                });
2895            }
2896
2897            let mut accepted = Vec::with_capacity(evidence_records.len());
2898            for record in evidence_records {
2899                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2900                    provider,
2901                    record.result,
2902                    record.assumptions.to_vec(),
2903                )?);
2904            }
2905
2906            let mut results = Vec::with_capacity(accepted.len());
2907            for evidence in &accepted {
2908                results.push(self.evaluate(program, evidence)?);
2909            }
2910            Ok(results)
2911        })
2912    }
2913
2914    /// Evaluate GPU exact query probabilities once per accepted split/batch GPU epistemic component.
2915    #[cfg(feature = "host-io")]
2916    pub fn evaluate_for_gpu_batch_execution_result(
2917        &mut self,
2918        program: &ExactDdnnfProgram,
2919        provider: &CudaKernelProvider,
2920        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2921    ) -> Result<Vec<ExactResult>> {
2922        epistemic_prob_trace_transaction!(self, {
2923            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2924                provider,
2925                evidence,
2926                "epistemic probabilistic query evaluation batch production",
2927            )?;
2928
2929            let mut results = Vec::with_capacity(accepted.len());
2930            for evidence in &accepted {
2931                results.push(self.evaluate(program, evidence)?);
2932            }
2933            Ok(results)
2934        })
2935    }
2936
2937    /// Evaluate GPU exact gradients after accepted world-view evidence was consumed.
2938    #[cfg(feature = "host-io")]
2939    pub fn evaluate_gpu_with_grads(
2940        &mut self,
2941        program: &ExactDdnnfProgram,
2942        evidence: &AcceptedWorldViewEvidence,
2943    ) -> Result<ExactResultWithGrads> {
2944        epistemic_prob_trace_transaction!(self, {
2945            self.require_accepted_evidence(evidence)?;
2946            let production_events_before = self.trace.checked_gpu_production_path_events()?;
2947            require_gpu_exact_backend(
2948                program,
2949                "epistemic probabilistic exact gradient evaluation",
2950            )?;
2951            let result = program.evaluate_gpu_with_grads()?;
2952            self.record_gpu_exact_gradient_evaluation(program)?;
2953            self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2954            self.record_accepted_evidence(evidence)?;
2955            self.trace.require_zero_cpu_recompute()?;
2956            Ok(result)
2957        })
2958    }
2959
2960    /// Evaluate GPU exact gradients after accepted GPU epistemic execution.
2961    #[cfg(feature = "host-io")]
2962    pub fn evaluate_gpu_with_grads_with_gpu_execution_result(
2963        &mut self,
2964        program: &ExactDdnnfProgram,
2965        provider: &CudaKernelProvider,
2966        result: &EpistemicGpuExecutionResult,
2967        assumptions: Vec<EpistemicAssumption>,
2968    ) -> Result<ExactResultWithGrads> {
2969        let evidence =
2970            AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
2971        self.evaluate_gpu_with_grads(program, &evidence)
2972    }
2973
2974    /// Evaluate GPU exact gradients once per accepted GPU epistemic execution result.
2975    #[cfg(feature = "host-io")]
2976    pub fn evaluate_gpu_with_grads_for_gpu_execution_results(
2977        &mut self,
2978        program: &ExactDdnnfProgram,
2979        provider: &CudaKernelProvider,
2980        evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2981    ) -> Result<Vec<ExactResultWithGrads>> {
2982        epistemic_prob_trace_transaction!(self, {
2983            if evidence_records.is_empty() {
2984                return Err(XlogError::UnsupportedEpistemicConstruct {
2985                    construct: "epistemic probabilistic gradient evaluation production batch"
2986                        .to_string(),
2987                    context:
2988                        "batched gradient evaluation requires at least one accepted GPU result"
2989                            .to_string(),
2990                });
2991            }
2992
2993            let mut accepted = Vec::with_capacity(evidence_records.len());
2994            for record in evidence_records {
2995                accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2996                    provider,
2997                    record.result,
2998                    record.assumptions.to_vec(),
2999                )?);
3000            }
3001
3002            let mut results = Vec::with_capacity(accepted.len());
3003            for evidence in &accepted {
3004                results.push(self.evaluate_gpu_with_grads(program, evidence)?);
3005            }
3006            Ok(results)
3007        })
3008    }
3009
3010    /// Evaluate GPU exact gradients once per accepted split/batch GPU epistemic component.
3011    #[cfg(feature = "host-io")]
3012    pub fn evaluate_gpu_with_grads_for_gpu_batch_execution_result(
3013        &mut self,
3014        program: &ExactDdnnfProgram,
3015        provider: &CudaKernelProvider,
3016        evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
3017    ) -> Result<Vec<ExactResultWithGrads>> {
3018        epistemic_prob_trace_transaction!(self, {
3019            let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
3020                provider,
3021                evidence,
3022                "epistemic probabilistic gradient evaluation batch production",
3023            )?;
3024
3025            let mut results = Vec::with_capacity(accepted.len());
3026            for evidence in &accepted {
3027                results.push(self.evaluate_gpu_with_grads(program, evidence)?);
3028            }
3029            Ok(results)
3030        })
3031    }
3032
3033    fn consume_accepted_evidence(&mut self, evidence: &AcceptedWorldViewEvidence) -> Result<()> {
3034        self.require_accepted_evidence(evidence)?;
3035        self.record_accepted_evidence(evidence)?;
3036        self.trace.require_zero_cpu_recompute()
3037    }
3038
3039    fn require_accepted_evidence(&self, evidence: &AcceptedWorldViewEvidence) -> Result<()> {
3040        if evidence.world_count() == 0 {
3041            return Err(XlogError::UnsupportedEpistemicConstruct {
3042                construct: "accepted world-view evidence".to_string(),
3043                context: "probabilistic production path requires a non-empty accepted world view"
3044                    .to_string(),
3045            });
3046        }
3047        if evidence.gpu_epistemic_mode().is_none() {
3048            return Err(XlogError::UnsupportedEpistemicConstruct {
3049                construct: "accepted world-view evidence".to_string(),
3050                context: "probabilistic production path requires GPU execution evidence; CPU \
3051                     world-view evidence is oracle-only"
3052                    .to_string(),
3053            });
3054        }
3055        self.trace.require_zero_cpu_recompute()
3056    }
3057
3058    fn record_accepted_evidence(&mut self, evidence: &AcceptedWorldViewEvidence) -> Result<()> {
3059        self.trace.accepted_world_view_evidence_consumed = Self::checked_trace_counter_add(
3060            self.trace.accepted_world_view_evidence_consumed,
3061            1,
3062            "accepted_world_view_evidence_consumed",
3063        )?;
3064        match evidence.gpu_epistemic_mode() {
3065            Some(EirEpistemicMode::G91) => {
3066                self.trace.accepted_g91_world_view_evidence_consumed =
3067                    Self::checked_trace_counter_add(
3068                        self.trace.accepted_g91_world_view_evidence_consumed,
3069                        1,
3070                        "accepted_g91_world_view_evidence_consumed",
3071                    )?;
3072            }
3073            Some(EirEpistemicMode::Faeel) => {
3074                self.trace.accepted_faeel_world_view_evidence_consumed =
3075                    Self::checked_trace_counter_add(
3076                        self.trace.accepted_faeel_world_view_evidence_consumed,
3077                        1,
3078                        "accepted_faeel_world_view_evidence_consumed",
3079                    )?;
3080            }
3081            None => {}
3082        }
3083        self.trace.accepted_evidence_assumptions_consumed = Self::checked_trace_counter_add(
3084            self.trace.accepted_evidence_assumptions_consumed,
3085            evidence.assumption_count() as u64,
3086            "accepted_evidence_assumptions_consumed",
3087        )?;
3088        self.trace
3089            .accepted_gpu_nonzero_arity_evidence_assumptions_consumed =
3090            Self::checked_trace_counter_add(
3091                self.trace
3092                    .accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
3093                evidence.nonzero_arity_assumption_count() as u64,
3094                "accepted_gpu_nonzero_arity_evidence_assumptions_consumed",
3095            )?;
3096        if evidence.max_assumption_arity() > u32::MAX as usize {
3097            return Err(XlogError::ResourceExhausted {
3098                context: "accepted GPU probability evidence max arity".to_string(),
3099                estimated_bytes: evidence.max_assumption_arity() as u64,
3100                budget_bytes: u32::MAX as u64,
3101            });
3102        }
3103        self.trace.accepted_gpu_max_evidence_arity_consumed = self
3104            .trace
3105            .accepted_gpu_max_evidence_arity_consumed
3106            .max(evidence.max_assumption_arity() as u32);
3107        self.trace.accepted_gpu_tuple_key_column_reads_consumed = Self::checked_trace_counter_add(
3108            self.trace.accepted_gpu_tuple_key_column_reads_consumed,
3109            evidence.gpu_tuple_key_column_reads() as u64,
3110            "accepted_gpu_tuple_key_column_reads_consumed",
3111        )?;
3112        self.trace.accepted_gpu_final_tuple_row_filters_consumed = Self::checked_trace_counter_add(
3113            self.trace.accepted_gpu_final_tuple_row_filters_consumed,
3114            evidence.gpu_final_tuple_row_filters() as u64,
3115            "accepted_gpu_final_tuple_row_filters_consumed",
3116        )?;
3117        self.trace
3118            .accepted_gpu_final_tuple_negated_row_filters_consumed =
3119            Self::checked_trace_counter_add(
3120                self.trace
3121                    .accepted_gpu_final_tuple_negated_row_filters_consumed,
3122                evidence.gpu_final_tuple_negated_row_filters() as u64,
3123                "accepted_gpu_final_tuple_negated_row_filters_consumed",
3124            )?;
3125        self.trace
3126            .accepted_gpu_row_specific_membership_row_capacity_consumed =
3127            Self::checked_trace_counter_add(
3128                self.trace
3129                    .accepted_gpu_row_specific_membership_row_capacity_consumed,
3130                evidence.gpu_row_specific_membership_row_capacity() as u64,
3131                "accepted_gpu_row_specific_membership_row_capacity_consumed",
3132            )?;
3133        self.trace
3134            .accepted_gpu_row_filter_fallback_row_capacity_consumed =
3135            Self::checked_trace_counter_add(
3136                self.trace
3137                    .accepted_gpu_row_filter_fallback_row_capacity_consumed,
3138                evidence.gpu_row_filter_fallback_row_capacity() as u64,
3139                "accepted_gpu_row_filter_fallback_row_capacity_consumed",
3140            )?;
3141        self.trace
3142            .accepted_gpu_constraint_relations_checked_consumed = Self::checked_trace_counter_add(
3143            self.trace
3144                .accepted_gpu_constraint_relations_checked_consumed,
3145            evidence.gpu_checked_constraint_relations() as u64,
3146            "accepted_gpu_constraint_relations_checked_consumed",
3147        )?;
3148        self.trace
3149            .accepted_gpu_constraint_row_count_device_reads_consumed =
3150            Self::checked_trace_counter_add(
3151                self.trace
3152                    .accepted_gpu_constraint_row_count_device_reads_consumed,
3153                evidence.gpu_constraint_row_count_device_reads() as u64,
3154                "accepted_gpu_constraint_row_count_device_reads_consumed",
3155            )?;
3156        Ok(())
3157    }
3158
3159    fn encode_program_pir_cnf_with_base_provenance(
3160        &mut self,
3161        program: &Program,
3162        base_provenance: &Provenance,
3163        provider: &Arc<CudaKernelProvider>,
3164        evidence: &AcceptedWorldViewEvidence,
3165        path: EpistemicProbPirCnfPath,
3166    ) -> Result<EpistemicProbPirCnfEvidence> {
3167        self.require_accepted_evidence(evidence)?;
3168        let conditioned_provenance = if evidence.assumptions().is_empty() {
3169            None
3170        } else {
3171            let conditioned_program = condition_program_with_available_evidence_using_provenance(
3172                program,
3173                base_provenance,
3174                evidence,
3175            )?;
3176            Some(extract_from_program(&conditioned_program)?)
3177        };
3178        let provenance = conditioned_provenance.as_ref().unwrap_or(base_provenance);
3179        self.encode_provenance_pir_cnf_with_accepted_world_view(
3180            provenance, provider, evidence, path,
3181        )
3182    }
3183
3184    fn encode_provenance_pir_cnf_with_accepted_world_view(
3185        &mut self,
3186        provenance: &Provenance,
3187        provider: &Arc<CudaKernelProvider>,
3188        evidence: &AcceptedWorldViewEvidence,
3189        path: EpistemicProbPirCnfPath,
3190    ) -> Result<EpistemicProbPirCnfEvidence> {
3191        self.require_accepted_evidence(evidence)?;
3192        let production_events_before = self.trace.checked_gpu_production_path_events()?;
3193        let roots = production_pir_roots(provenance)?;
3194        if roots.is_empty() {
3195            return Err(XlogError::UnsupportedEpistemicConstruct {
3196                construct: "accepted probabilistic PIR/CNF production path".to_string(),
3197                context: "GPU PIR/CNF evidence requires at least one query, evidence, or probabilistic variable root".to_string(),
3198            });
3199        }
3200        let gpu_pir = GpuPirGraph::from_host(&provenance.pir, provider)?;
3201        checked_prob_trace_counter_inc!(self, gpu_pir_graph_uploads);
3202        match path {
3203            EpistemicProbPirCnfPath::Source => {
3204                checked_prob_trace_counter_inc!(self, gpu_source_pir_graph_uploads);
3205            }
3206            EpistemicProbPirCnfPath::Program => {
3207                checked_prob_trace_counter_inc!(self, gpu_program_pir_graph_uploads);
3208            }
3209        }
3210        let gpu_roots = GpuPirRoots::from_host(&roots, provider)?;
3211        let encoding = encode_cnf_gpu(&gpu_pir, &gpu_roots, provider)?;
3212        checked_prob_trace_counter_inc!(self, gpu_cnf_encodes);
3213        match path {
3214            EpistemicProbPirCnfPath::Source => {
3215                checked_prob_trace_counter_inc!(self, gpu_source_cnf_encodes);
3216            }
3217            EpistemicProbPirCnfPath::Program => {
3218                checked_prob_trace_counter_inc!(self, gpu_program_cnf_encodes);
3219            }
3220        }
3221        let pir_cnf_evidence = EpistemicProbPirCnfEvidence {
3222            pir_nodes: provenance.pir.len(),
3223            root_count: roots.len(),
3224            cnf_var_cap: encoding.cnf.var_cap,
3225            cnf_clause_cap: encoding.cnf.clause_cap,
3226            cnf_lit_cap: encoding.cnf.lit_cap,
3227        };
3228        self.record_accepted_gpu_production_path_events_since(production_events_before)?;
3229        self.record_accepted_evidence(evidence)?;
3230        self.trace.require_zero_cpu_recompute()?;
3231        Ok(pir_cnf_evidence)
3232    }
3233}
3234
3235fn require_gpu_exact_backend(program: &ExactDdnnfProgram, construct: &'static str) -> Result<()> {
3236    if !program.uses_gpu_production_backend() {
3237        return Err(XlogError::UnsupportedEpistemicConstruct {
3238            construct: construct.to_string(),
3239            context:
3240                "production probability metrics require a compiled GPU-native Decision-DNNF exact/provenance/PIR/CNF backend; \
3241                      empty roots and count-lift-only evaluation cannot satisfy accepted epistemic probability reuse"
3242                    .to_string(),
3243        });
3244    }
3245    Ok(())
3246}
3247
3248#[cfg(feature = "host-io")]
3249#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
3250struct EpistemicProbConditionedEvidenceCounts {
3251    total: usize,
3252    nonzero_arity: usize,
3253    max_arity: u32,
3254    negative: usize,
3255    know: usize,
3256    possible: usize,
3257    not_known: usize,
3258    not_possible: usize,
3259}
3260
3261fn condition_program_with_available_evidence_using_provenance(
3262    program: &Program,
3263    base_provenance: &Provenance,
3264    evidence: &AcceptedWorldViewEvidence,
3265) -> Result<Program> {
3266    if evidence.assumptions().is_empty() {
3267        return Ok(program.clone());
3268    }
3269
3270    let mut program = program.clone();
3271    let mut applied = 0usize;
3272    for assumption in evidence.assumptions() {
3273        validate_conditioned_assumption_shape(assumption)?;
3274        let Some(atom) = conditioned_evidence_atom_for_assumption(base_provenance, assumption)
3275        else {
3276            return Err(XlogError::UnsupportedEpistemicConstruct {
3277                construct: "accepted probabilistic PIR/CNF evidence conditioning".to_string(),
3278                context: format!(
3279                    "accepted {} PIR/CNF evidence for {}/{} has no provenance formula; partial \
3280                     world-view evidence cannot satisfy production conditioning metrics",
3281                    assumption.evidence_literal(),
3282                    assumption.predicate,
3283                    assumption.arity
3284                ),
3285            });
3286        };
3287        program.evidence.push(Evidence {
3288            atom,
3289            value: assumption.value,
3290        });
3291        applied += 1;
3292    }
3293
3294    if applied == 0 {
3295        return Err(XlogError::UnsupportedEpistemicConstruct {
3296            construct: "accepted probabilistic PIR/CNF evidence conditioning".to_string(),
3297            context: "PIR/CNF encoding requires at least one accepted epistemic assumption to match existing probabilistic provenance"
3298                .to_string(),
3299        });
3300    }
3301
3302    Ok(program)
3303}
3304
3305#[cfg(feature = "host-io")]
3306fn condition_program_with_accepted_evidence_using_provenance(
3307    program: &Program,
3308    provenance: &Provenance,
3309    evidence: &AcceptedWorldViewEvidence,
3310) -> Result<(Program, EpistemicProbConditionedEvidenceCounts)> {
3311    if evidence.assumptions().is_empty() {
3312        return Err(XlogError::UnsupportedEpistemicConstruct {
3313            construct: "accepted probabilistic evidence conditioning".to_string(),
3314            context: "conditioned exact path requires at least one accepted epistemic assumption"
3315                .to_string(),
3316        });
3317    }
3318
3319    let mut counts = EpistemicProbConditionedEvidenceCounts::default();
3320    for assumption in evidence.assumptions() {
3321        validate_conditioned_assumption_shape(assumption)?;
3322        record_conditioned_assumption_counts(&mut counts, assumption);
3323    }
3324    let mut program = program.clone();
3325    for assumption in evidence.assumptions() {
3326        let Some(atom) = conditioned_evidence_atom_for_assumption(provenance, assumption) else {
3327            return Err(XlogError::UnsupportedEpistemicConstruct {
3328                construct: "accepted probabilistic evidence conditioning".to_string(),
3329                context: format!(
3330                    "accepted {} exact evidence for {}/{} has no provenance formula; \
3331                     vacuous evidence cannot satisfy production conditioning metrics",
3332                    assumption.evidence_literal(),
3333                    assumption.predicate,
3334                    assumption.arity
3335                ),
3336            });
3337        };
3338        program.evidence.push(Evidence {
3339            atom,
3340            value: assumption.value,
3341        });
3342    }
3343
3344    Ok((program, counts))
3345}
3346
3347fn validate_conditioned_assumption_shape(assumption: &EpistemicAssumption) -> Result<()> {
3348    if assumption.arity == 0 {
3349        if !assumption.terms.is_empty() {
3350            return Err(XlogError::UnsupportedEpistemicConstruct {
3351                construct: "accepted probabilistic evidence conditioning".to_string(),
3352                context: format!(
3353                    "zero-arity exact evidence must not carry tuple terms, got {}/{}",
3354                    assumption.predicate, assumption.arity
3355                ),
3356            });
3357        }
3358    } else if assumption.terms.len() != assumption.arity {
3359        return Err(XlogError::UnsupportedEpistemicConstruct {
3360            construct: "accepted probabilistic evidence conditioning".to_string(),
3361            context: format!(
3362                "nonzero exact evidence conditioning requires {} concrete tuple terms, got {} for {}/{}",
3363                assumption.arity,
3364                assumption.terms.len(),
3365                assumption.predicate,
3366                assumption.arity
3367            ),
3368        });
3369    }
3370    Ok(())
3371}
3372
3373#[cfg(feature = "host-io")]
3374fn record_conditioned_assumption_counts(
3375    counts: &mut EpistemicProbConditionedEvidenceCounts,
3376    assumption: &EpistemicAssumption,
3377) {
3378    counts.total += 1;
3379    if assumption.arity > 0 {
3380        counts.nonzero_arity += 1;
3381        counts.max_arity = counts.max_arity.max(assumption.arity as u32);
3382    }
3383    if !assumption.value {
3384        counts.negative += 1;
3385    }
3386    match (assumption.kind, assumption.value) {
3387        (EpistemicAssumptionKind::Know, true) => counts.know += 1,
3388        (EpistemicAssumptionKind::Possible, true) => counts.possible += 1,
3389        (EpistemicAssumptionKind::Know, false) => counts.not_known += 1,
3390        (EpistemicAssumptionKind::Possible, false) => counts.not_possible += 1,
3391    }
3392}
3393
3394fn evidence_term_variants(term: &EpistemicEvidenceTerm) -> Vec<(Value, Term)> {
3395    match term {
3396        EpistemicEvidenceTerm::Integer(value) => vec![(Value::I64(*value), Term::Integer(*value))],
3397        EpistemicEvidenceTerm::String(value) => {
3398            let symbol_id = symbol::intern(value);
3399            vec![
3400                (Value::String(value.clone()), Term::String(value.clone())),
3401                (Value::Symbol(symbol_id), Term::Symbol(symbol_id)),
3402            ]
3403        }
3404        EpistemicEvidenceTerm::Symbol(value) => {
3405            let string_value = symbol::resolve(*value);
3406            vec![
3407                (Value::Symbol(*value), Term::Symbol(*value)),
3408                (
3409                    Value::String(string_value.clone()),
3410                    Term::String(string_value),
3411                ),
3412            ]
3413        }
3414    }
3415}
3416
3417fn conditioned_evidence_atom_for_assumption(
3418    provenance: &Provenance,
3419    assumption: &EpistemicAssumption,
3420) -> Option<Atom> {
3421    if assumption.terms.is_empty() {
3422        if provenance
3423            .query_formula(&assumption.predicate, &[])
3424            .is_some()
3425        {
3426            return Some(Atom {
3427                predicate: assumption.predicate.clone(),
3428                terms: Vec::new(),
3429            });
3430        }
3431        return None;
3432    }
3433
3434    let variants = assumption
3435        .terms
3436        .iter()
3437        .map(evidence_term_variants)
3438        .collect::<Vec<_>>();
3439    let mut values = Vec::with_capacity(variants.len());
3440    let mut terms = Vec::with_capacity(variants.len());
3441    conditioned_evidence_atom_from_variants(
3442        provenance,
3443        assumption,
3444        &variants,
3445        0,
3446        &mut values,
3447        &mut terms,
3448    )
3449}
3450
3451fn conditioned_evidence_atom_from_variants(
3452    provenance: &Provenance,
3453    assumption: &EpistemicAssumption,
3454    variants: &[Vec<(Value, Term)>],
3455    index: usize,
3456    values: &mut Vec<Value>,
3457    terms: &mut Vec<Term>,
3458) -> Option<Atom> {
3459    if index == variants.len() {
3460        if provenance
3461            .query_formula(&assumption.predicate, values)
3462            .is_some()
3463        {
3464            return Some(Atom {
3465                predicate: assumption.predicate.clone(),
3466                terms: terms.clone(),
3467            });
3468        }
3469        return None;
3470    }
3471
3472    for (value, term) in &variants[index] {
3473        values.push(value.clone());
3474        terms.push(term.clone());
3475        if let Some(atom) = conditioned_evidence_atom_from_variants(
3476            provenance,
3477            assumption,
3478            variants,
3479            index + 1,
3480            values,
3481            terms,
3482        ) {
3483            return Some(atom);
3484        }
3485        values.pop();
3486        terms.pop();
3487    }
3488    None
3489}
3490
3491fn assumption_has_provenance_formula(
3492    provenance: &Provenance,
3493    assumption: &EpistemicAssumption,
3494) -> bool {
3495    conditioned_evidence_atom_for_assumption(provenance, assumption).is_some()
3496}
3497
3498fn evidence_with_provenance_backed_assumptions(
3499    evidence: &AcceptedWorldViewEvidence,
3500    provenance: &Provenance,
3501) -> Result<AcceptedWorldViewEvidence> {
3502    let assumptions = evidence
3503        .assumptions()
3504        .iter()
3505        .filter(|assumption| assumption_has_provenance_formula(provenance, assumption))
3506        .cloned()
3507        .collect::<Vec<_>>();
3508    if assumptions.is_empty() {
3509        return Err(XlogError::UnsupportedEpistemicConstruct {
3510            construct: "accepted probabilistic PIR/CNF evidence conditioning".to_string(),
3511            context: "PIR/CNF encoding requires at least one accepted epistemic assumption to match existing probabilistic provenance"
3512                .to_string(),
3513        });
3514    }
3515    Ok(evidence.with_assumptions(assumptions))
3516}
3517
3518fn production_pir_roots(provenance: &Provenance) -> Result<Vec<PirNodeId>> {
3519    let mut roots = BTreeSet::new();
3520
3521    for (atom, value) in &provenance.evidence {
3522        if let Some(id) = provenance.query_formula(&atom.predicate, &atom.args) {
3523            roots.insert(id);
3524        } else if *value {
3525            return Err(XlogError::Execution(format!(
3526                "Exact inference error: evidence atom is never derivable: {}",
3527                atom.predicate
3528            )));
3529        }
3530    }
3531
3532    for atom in &provenance.queries {
3533        if let Some(id) = provenance.query_formula(&atom.predicate, &atom.args) {
3534            roots.insert(id);
3535        }
3536    }
3537
3538    for (idx, node) in provenance.pir.nodes().iter().enumerate() {
3539        if matches!(
3540            node,
3541            PirNode::Decision { .. } | PirNode::Lit { .. } | PirNode::NegLit { .. }
3542        ) {
3543            roots.insert(PirNodeId::from_u32(idx as u32));
3544        }
3545    }
3546
3547    Ok(roots.into_iter().collect())
3548}