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