Skip to main content

xlog_cuda/
semantic_transition.rs

1//! Fixed-roster device-resident semantic action sampling.
2//!
3//! Inputs are bound before capture. Launch and replay do not observe the device;
4//! terminal observation is explicit. RNG successors remain pending, not published
5//! world state. Descriptor meanings belong to the retained semantic admission.
6
7use crate::semantic_work::{ExecutionWork, ModelWorkEvent, ModelWorkKind, ModelWorkRecording};
8mod learning_phase;
9#[cfg(feature = "semantic-policy")]
10mod model_evaluation;
11mod prepared_replay;
12pub use learning_phase::{
13    SemanticLearningCopyReset, SemanticLearningPhase, SemanticLearningPhaseRecord,
14    SemanticLearningPhaseTransition,
15};
16#[cfg(feature = "semantic-policy")]
17pub use model_evaluation::{
18    SemanticCompletedModelEvaluation, SemanticEvaluationCohort, SemanticModelEvaluation,
19    SemanticModelEvaluationResult,
20};
21#[cfg(feature = "semantic-policy")]
22pub use prepared_replay::SemanticCompletedReplayMaterials;
23use prepared_replay::{PreparedReplayCustody, PreparedReplayDescriptor};
24use sha2::{Digest, Sha256};
25use std::{
26    collections::{BTreeMap, BTreeSet},
27    fmt,
28    mem::size_of,
29    sync::Arc,
30};
31
32use cudarc::driver::sys;
33use xlog_core::{Result as XlogResult, XlogError};
34
35use crate::cuda_graph::CapturedCudaGraph;
36use crate::dlpack::DlpackManagedTensor;
37use crate::launch::{CudaEnqueue, LaunchEnqueueError, LaunchRecorder};
38use crate::memory::TrackedCudaSlice;
39use crate::memory::{
40    CudaColumn, DeviceAllocationProvenance, DeviceMemoryView, DeviceRead, GpuMemoryReservation,
41};
42use crate::provider::resident_schedule::{validate_execution_domain, ResidentExecutionDomain};
43use crate::semantic_hypergraph::{
44    material_bytes, material_u32, material_u64, SemanticMaterialReader, SemanticRootMaterial,
45};
46#[cfg(feature = "semantic-policy")]
47use crate::semantic_hypergraph::{
48    material_statement_key, SemanticStatementIdentity, SemanticSupportIdentity,
49};
50#[cfg(feature = "semantic-policy")]
51use crate::semantic_training_view::SemanticTrainingCanaryRefusalReason;
52use crate::semantic_training_view::{
53    frozen_training_coefficients, SemanticSelectedTrainingView,
54    SemanticTrainingCanaryRefusalRecord, SemanticTrainingCanaryResultRecord,
55    SemanticTrainingDomain, SemanticTrainingObjective, SemanticTrainingViewArena,
56    SemanticTrainingViewOrigin, SemanticTrainingViewOriginRecord, SemanticTrainingViewPort,
57    SemanticTrainingViewRow, SemanticTrainingViewSelection,
58};
59use crate::{
60    CudaFunction, CudaKernelProvider, CudaStream, DeviceRepr, LaunchAsync, LaunchConfig,
61    SemanticAdmission, SemanticAdmissionLimits, SemanticAdmissionRecords, SemanticHypergraph,
62    SemanticHypergraphCapacities, SemanticHypergraphError, SemanticInsertOutcome,
63    SemanticRecordRole, SemanticRootHandle, SemanticRootSnapshot,
64};
65
66#[cfg(feature = "semantic-policy")]
67type PreparedPolicyStorage = (
68    PolicyBuffers,
69    TrackedCudaSlice<u8>,
70    TrackedCudaSlice<SemanticTransitionReceipt>,
71    TrackedCudaSlice<DeviceState>,
72);
73
74/// Canonical 256-bit identity, preserving byte order without native-word conversion.
75#[repr(transparent)]
76#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
77pub struct Identity256([u8; 32]);
78
79impl Identity256 {
80    pub const fn from_bytes(bytes: [u8; 32]) -> Self {
81        Self(bytes)
82    }
83    pub const fn as_bytes(&self) -> &[u8; 32] {
84        &self.0
85    }
86}
87
88/// A native observer executed during cold task binding. Implementations belong to
89/// the program executor, not the CUDA substrate. Python accepts executable XLOG
90/// source through that executor, never caller-provided answers or receipts.
91/// A successful observation must complete all submitted work before returning
92/// host results. An error may follow device submission, so the calling session
93/// is poisoned and cannot reuse its previous task binding.
94pub trait SemanticTaskProgram: fmt::Debug + Send + Sync {
95    /// A cold, independently admitted mutable source bank. The observer may
96    /// report expected truth but never chooses editable rules or fact order.
97    fn editable_program(&self) -> Option<&crate::SemanticProgramAdmission> {
98        None
99    }
100
101    fn observe(
102        &self,
103        provider: Arc<CudaKernelProvider>,
104    ) -> Result<SemanticTaskObservation, SemanticTransitionError>;
105}
106
107/// Actual native observer output and the exact source/input/result custody used
108/// to derive it. These bytes describe execution; they grant no application rights.
109pub struct SemanticTaskObservation {
110    pub program_source: Vec<u8>,
111    pub input_bytes: Vec<u8>,
112    pub result_bytes: Vec<u8>,
113    pub expected_truth: [crate::SemanticTruth; 3],
114}
115
116/// Independently recomputable identities of the exact semantic task content.
117/// These values carry no use authority. They let retained symbolic training
118/// rows bind the ordered query, admitted theory plus executed observer program,
119/// and observed four-valued result to the task that the native owner actually
120/// executed during cold binding.
121#[derive(Clone, Copy, Debug, PartialEq, Eq)]
122pub struct SemanticTaskContentIdentity {
123    pub query: Identity256,
124    pub theory_program: Identity256,
125    pub result: Identity256,
126}
127
128/// Explicit nonnegative coefficients for query agreement and measured work.
129/// These coefficients determine the measured value and final return; ordered
130/// task priorities, agreement, and cost select the candidate in that order.
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
132pub struct SemanticTaskScoring {
133    pub correct_weight: u32,
134    pub all_correct_weight: u32,
135    pub work_weight: u32,
136    pub improvement_weight: u32,
137    pub refusal_weight: u32,
138    pub spent_weight: u32,
139}
140
141/// Task-independent unit and finite cap for native structural work. The unit
142/// names the versioned counting law and the resident program mode, not the
143/// authority, task identity, or outcome of a sampled candidate.
144#[derive(Clone, Copy, Debug, PartialEq, Eq)]
145pub struct SemanticStructuralCostDescriptor {
146    pub unit: Identity256,
147    pub cap: u64,
148}
149
150/// Evaluator interval and objective coefficients frozen by the native task
151/// before actions, independently of any future training-group membership.
152#[derive(Clone, Copy, Debug, PartialEq)]
153pub struct SemanticTaskObjectiveLaw {
154    pub return_bound: i64,
155    pub evaluator_min: f64,
156    pub evaluator_max: f64,
157    pub coefficients: [f32; 9],
158    pub structural_cost: SemanticStructuralCostDescriptor,
159}
160
161impl SemanticTaskObjectiveLaw {
162    fn require_objective(
163        self,
164        objective: &SemanticTrainingObjective,
165    ) -> Result<(), SemanticTransitionError> {
166        if objective.evaluator_min.to_bits() != self.evaluator_min.to_bits()
167            || objective.evaluator_max.to_bits() != self.evaluator_max.to_bits()
168            || objective.coefficients.map(f32::to_bits) != self.coefficients.map(f32::to_bits)
169            || objective.cost_unit != self.structural_cost.unit
170            || objective.cost_cap != self.structural_cost.cap
171        {
172            return Err(publication_input_error(
173                "training objective differs from the evaluator, coefficients or cost law frozen before actions",
174            ));
175        }
176        Ok(())
177    }
178}
179
180/// The only structural-cost law accepted by a cold training objective.
181pub fn semantic_structural_cost_descriptor(
182    editable_program: bool,
183) -> SemanticStructuralCostDescriptor {
184    let (support_cap, truth_change_cap) = if editable_program {
185        (
186            crate::semantic_program::RESIDENT_PROGRAM_FACT_CAPACITY as u64,
187            3u64,
188        )
189    } else {
190        (2u64, 2u64)
191    };
192    let cap = 2 + support_cap + truth_change_cap;
193    let mut hash = Sha256::new();
194    hash.update(b"xlog.semantic.structural-cost.v1\0");
195    for word in [
196        u64::from(editable_program),
197        2,
198        support_cap,
199        truth_change_cap,
200        cap,
201    ] {
202        hash.update(word.to_le_bytes());
203    }
204    SemanticStructuralCostDescriptor {
205        unit: Identity256::from_bytes(hash.finalize().into()),
206        cap,
207    }
208}
209
210/// One normalized truth-match objective within an ordered task priority level.
211/// The native query result contributes one when it equals `target_truth`, zero
212/// otherwise; candidate progress subtracts the acquired base's contribution.
213#[derive(Clone, Copy, Debug, PartialEq, Eq)]
214pub struct SemanticTaskPriorityGoal {
215    pub query: u8,
216    pub target_truth: u8,
217    pub weight: u32,
218}
219
220#[derive(Clone, Debug, PartialEq, Eq)]
221pub struct SemanticTaskPriorityLevel {
222    pub goals: Vec<SemanticTaskPriorityGoal>,
223}
224
225impl SemanticTaskScoring {
226    fn words(self) -> [u64; 6] {
227        [
228            self.correct_weight,
229            self.all_correct_weight,
230            self.work_weight,
231            self.improvement_weight,
232            self.refusal_weight,
233            self.spent_weight,
234        ]
235        .map(u64::from)
236    }
237
238    fn return_bound(self, editable_program: bool) -> Result<i64, SemanticTransitionError> {
239        // A rule may derive many facts from one command. Successful resident
240        // materialization caps the fact bank at 4096, and a candidate can also
241        // change all three query truths. The graph-only path retains its smaller
242        // support-attachment cap. Priority selection need not maximize value,
243        // so both signs of selected-minus-base value must fit.
244        let max_cost = u128::from(semantic_structural_cost_descriptor(editable_program).cap);
245        let max_spent = if editable_program { 19 } else { 17 };
246        let value_span = 3 * u128::from(self.correct_weight)
247            + u128::from(self.all_correct_weight)
248            + max_cost * u128::from(self.work_weight);
249        i64::try_from(value_span)
250            .map_err(|_| publication_input_error("task value can overflow signed arithmetic"))?;
251        let return_bound = value_span * u128::from(self.improvement_weight)
252            + 2 * u128::from(self.refusal_weight)
253            + max_spent * u128::from(self.spent_weight);
254        i64::try_from(return_bound)
255            .map_err(|_| publication_input_error("task scoring can overflow the signed return"))
256    }
257
258    fn validate(self, editable_program: bool) -> Result<(), SemanticTransitionError> {
259        self.return_bound(editable_program).map(|_| ())
260    }
261
262    fn objective_law(
263        self,
264        editable_program: bool,
265    ) -> Result<SemanticTaskObjectiveLaw, SemanticTransitionError> {
266        let return_bound = self.return_bound(editable_program)?;
267        let mut evaluator_max = return_bound as f64;
268        // The integer return bound may exceed exact FP64 integer precision.
269        // Never narrow the proven interval when rounding its upper endpoint.
270        if (evaluator_max as u128) < return_bound as u128 {
271            evaluator_max = f64::from_bits(evaluator_max.to_bits() + 1);
272        }
273        let evaluator_min = -evaluator_max;
274        Ok(SemanticTaskObjectiveLaw {
275            return_bound,
276            evaluator_min,
277            evaluator_max,
278            coefficients: frozen_training_coefficients(evaluator_min, evaluator_max),
279            structural_cost: semantic_structural_cost_descriptor(editable_program),
280        })
281    }
282
283    #[cfg(feature = "semantic-policy")]
284    fn completed_law_bytes(
285        self,
286        task_identity: Identity256,
287        editable_program: bool,
288    ) -> Result<Vec<u8>, SemanticTransitionError> {
289        let mut bytes = b"XLOG-TASK-SCORING-LAW\0".to_vec();
290        material_u64(&mut bytes, 2);
291        bytes.extend_from_slice(task_identity.as_bytes());
292        let structural_cost = semantic_structural_cost_descriptor(editable_program);
293        bytes.extend_from_slice(structural_cost.unit.as_bytes());
294        material_u64(&mut bytes, structural_cost.cap);
295        for weight in self.words() {
296            material_u64(&mut bytes, weight);
297        }
298        bytes.extend_from_slice(&self.return_bound(editable_program)?.to_le_bytes());
299        Ok(bytes)
300    }
301}
302
303fn checkpoint_scoring_law_identity(
304    scoring: SemanticTaskScoring,
305    task_content: SemanticTaskContentIdentity,
306    objective_law: SemanticTaskObjectiveLaw,
307    training_domain: Option<&SemanticTrainingDomain>,
308) -> Identity256 {
309    let mut hash = Sha256::new();
310    hash.update(b"xlog.semantic.checkpoint.scoring-law.v4\0");
311    // Arena transfer advances authority, not the task's content or evaluator.
312    // The checkpoint binds that authority separately from this immutable law.
313    for identity in [
314        task_content.query,
315        task_content.theory_program,
316        task_content.result,
317    ] {
318        hash.update(identity.as_bytes());
319    }
320    for weight in scoring.words() {
321        hash.update(weight.to_le_bytes());
322    }
323    hash.update(objective_law.return_bound.to_le_bytes());
324    hash.update(objective_law.structural_cost.unit.as_bytes());
325    hash.update(objective_law.structural_cost.cap.to_le_bytes());
326    hash.update(objective_law.evaluator_min.to_bits().to_le_bytes());
327    hash.update(objective_law.evaluator_max.to_bits().to_le_bytes());
328    for coefficient in objective_law.coefficients {
329        hash.update(coefficient.to_bits().to_le_bytes());
330    }
331    hash.update([u8::from(training_domain.is_some())]);
332    if let Some(domain) = training_domain {
333        hash.update(domain.identity().as_bytes());
334    }
335    Identity256::from_bytes(hash.finalize().into())
336}
337
338#[cfg(feature = "semantic-policy")]
339#[expect(
340    clippy::too_many_arguments,
341    reason = "completed scoring checks independent task, work, refusal, and result fields"
342)]
343fn validate_completed_task_scoring(
344    scoring: SemanticTaskScoring,
345    editable_program: bool,
346    priority_levels: &[SemanticTaskPriorityLevel],
347    facts: &[SemanticTaskFacts; 3],
348    work: &[SemanticTransitionWork; 2],
349    lane_refusal: [u64; 2],
350    query_count: u64,
351    winner: u64,
352    return_value: i64,
353) -> bool {
354    if scoring.validate(editable_program).is_err()
355        || query_count > 9
356        || winner > 2
357        || lane_refusal.iter().any(|&refusal| refusal > 4)
358        || (!editable_program && lane_refusal.iter().any(|&refusal| refusal >= 3))
359        || work.iter().any(|work| !work.is_valid(editable_program))
360        || facts
361            .iter()
362            .any(|facts| facts.g > 3 || facts.p > 1 || facts.eligible > 1)
363    {
364        return false;
365    }
366    for (slot, facts) in facts.iter().enumerate() {
367        let measured = if slot == 0 {
368            0
369        } else {
370            let work = work[slot - 1];
371            work.raw_structural_cost()
372        };
373        let value = i128::from(scoring.correct_weight) * i128::from(facts.g)
374            + i128::from(scoring.all_correct_weight) * i128::from(facts.p)
375            - i128::from(scoring.work_weight) * i128::from(measured);
376        if facts.c != measured || i128::from(facts.v) != value {
377            return false;
378        }
379    }
380    let mut selected = 0;
381    for slot in 1..3 {
382        if facts[slot].eligible == 1
383            && (facts[selected].eligible == 0
384                || task_candidate_better(priority_levels, facts, slot, selected))
385        {
386            selected = slot;
387        }
388    }
389    if winner as usize != selected || facts[selected].eligible != 1 {
390        return false;
391    }
392    let refusals = lane_refusal.iter().filter(|&&refusal| refusal != 0).count() as i128;
393    let spent = i128::from(query_count)
394        + work
395            .iter()
396            .enumerate()
397            .filter(|(lane, _)| lane + 1 != selected)
398            .map(|(_, work)| i128::from(work.edit_commands + work.defined_truth_changes))
399            .sum::<i128>();
400    let expected_return = i128::from(scoring.improvement_weight)
401        * (i128::from(facts[selected].v) - i128::from(facts[0].v))
402        - i128::from(scoring.refusal_weight) * refusals
403        - i128::from(scoring.spent_weight) * spent;
404    i128::from(return_value) == expected_return
405}
406
407#[cfg(feature = "semantic-policy")]
408fn task_candidate_better(
409    priority_levels: &[SemanticTaskPriorityLevel],
410    facts: &[SemanticTaskFacts; 3],
411    candidate: usize,
412    incumbent: usize,
413) -> bool {
414    for level in priority_levels {
415        let score = |slot: usize| -> i64 {
416            level
417                .goals
418                .iter()
419                .map(|goal| {
420                    let query = usize::from(goal.query);
421                    let target = u64::from(goal.target_truth);
422                    let achieved = i64::from(facts[slot].truth[query] == target);
423                    let base = i64::from(facts[0].truth[query] == target);
424                    i64::from(goal.weight) * (achieved - base)
425                })
426                .sum()
427        };
428        let candidate_score = score(candidate);
429        let incumbent_score = score(incumbent);
430        if candidate_score != incumbent_score {
431            return candidate_score > incumbent_score;
432        }
433    }
434    facts[candidate].g > facts[incumbent].g
435        || (facts[candidate].g == facts[incumbent].g && facts[candidate].c < facts[incumbent].c)
436}
437
438/// Three ordered query selections for the bounded transition ABI. Predicate,
439/// arguments, observer program, eligibility, and scoring are application inputs.
440/// This specification carries no authority; only the application controller may
441/// attach an authorized task to its retained semantic session.
442#[derive(Clone, Debug)]
443pub struct SemanticTaskEvaluationSpec {
444    /// Original statement records in the retained admission, in observer order.
445    pub statement_records: [u32; 3],
446    /// Admitted support records, each retaining its original statement association.
447    pub allowed_support_records: Vec<u32>,
448    pub program: Arc<dyn SemanticTaskProgram>,
449    pub scoring: SemanticTaskScoring,
450    /// Ordered, task-local lexicographic levels; an explicit empty list leaves
451    /// predictive agreement and measured cost as the selection cascade.
452    pub priority_levels: Vec<SemanticTaskPriorityLevel>,
453    /// Bit n permits Truth4 value n for the corresponding candidate query.
454    pub admissible_truth_masks: [u8; 3],
455    /// Application-owned ex-ante decision that this episode may contribute an
456    /// actor term. It is frozen with the task before any action draw.
457    pub actor_eligible: bool,
458    /// Original sealed inputs and complete loader geometry, fixed before draw.
459    /// None denotes a task with no prospective training arena, not a fallback
460    /// domain: subsequent training admission requires an original Some binding.
461    pub training_domain: Option<SemanticTrainingDomain>,
462}
463
464/// Owner-validated cold read coverage for a task's queried semantic heads.
465/// These records grant no use or mutation rights and are not current device
466/// query receipts. Runtime feedback must still establish its actual live view.
467#[derive(Clone, Debug, PartialEq, Eq)]
468pub struct SemanticTaskObservationRoots {
469    /// Logical root whose canonical insertion material was inspected.
470    pub root_digest: Identity256,
471    pub root_extents: [u32; 3],
472    /// Original admitted query selections, retaining their order.
473    pub query_records: [u32; 3],
474    /// Query ordinal, genuine original insertion target (absent for a derived
475    /// target), and original support record. Ordered by query, then insertion.
476    /// A matching query value never supplies an absent original target.
477    pub contributors: Vec<(u32, Option<u32>, u32)>,
478}
479
480/// Native seal of the independently validated goal authority carried by the
481/// controller. The semantic root is the exact XLOG root inspected for the task;
482/// the remaining roots bind the complete mandatory dependency and constraint
483/// closures. These values are derived by the trusted controller after its
484/// closure checks, never supplied by the model-update consumer.
485#[derive(Clone, Copy, Debug, PartialEq, Eq)]
486pub struct SemanticTaskGoalWitness {
487    pub semantic_root: Identity256,
488    pub authority_root: Identity256,
489    pub mandatory_links_root: Identity256,
490    pub constraints_root: Identity256,
491    pub mandatory_link_count: u64,
492    pub constraint_count: u64,
493}
494
495impl SemanticTaskEvaluationSpec {
496    fn validate_records(
497        &self,
498        records: &SemanticAdmissionRecords,
499    ) -> Result<(), SemanticTransitionError> {
500        let invalid = |detail: &str| SemanticTransitionError::InvalidInput {
501            detail: format!("task binding: {detail}"),
502        };
503        self.scoring
504            .validate(self.program.editable_program().is_some())?;
505        if let Some(domain) = &self.training_domain {
506            domain.validate()?;
507        }
508        if self.priority_levels.len() > 3 {
509            return Err(invalid("task priorities exceed the three-query bank"));
510        }
511        let mut seen_queries = [false; 3];
512        let mut goal_count = 0usize;
513        for level in &self.priority_levels {
514            if level.goals.is_empty() {
515                return Err(invalid("task priority level must contain a goal"));
516            }
517            goal_count += level.goals.len();
518            if goal_count > 3 {
519                return Err(invalid("task priorities exceed the three-query bank"));
520            }
521            for goal in &level.goals {
522                let query = usize::from(goal.query);
523                if query >= 3 || goal.target_truth > 3 || goal.weight == 0 {
524                    return Err(invalid(
525                        "task priority goal has invalid query, truth or weight",
526                    ));
527                }
528                if std::mem::replace(&mut seen_queries[query], true) {
529                    return Err(invalid("task priority query appears more than once"));
530                }
531                if self.admissible_truth_masks[query] & (1 << goal.target_truth) == 0 {
532                    return Err(invalid(
533                        "task priority target is forbidden by hard truth mask",
534                    ));
535                }
536            }
537        }
538        if self
539            .admissible_truth_masks
540            .iter()
541            .any(|mask| *mask == 0 || *mask & !15 != 0)
542        {
543            return Err(invalid(
544                "truth eligibility requires a nonempty four-valued mask",
545            ));
546        }
547        for index in self.statement_records {
548            let record = records
549                .records
550                .get(index as usize)
551                .ok_or_else(|| invalid("query statement is outside the admission"))?;
552            let predicate = records
553                .predicates
554                .iter()
555                .find(|predicate| predicate.predicate == record.predicate)
556                .ok_or_else(|| invalid("query predicate is outside the admission"))?;
557            if predicate.role != SemanticRecordRole::Statement {
558                return Err(invalid("query selection is not a statement"));
559            }
560        }
561        if self.allowed_support_records.len() > records.supports.len() {
562            return Err(invalid(
563                "support selections exceed the admitted support bank",
564            ));
565        }
566        for &index in &self.allowed_support_records {
567            let support = records
568                .supports
569                .get(index as usize)
570                .ok_or_else(|| invalid("support selection is outside the admission"))?;
571            if !self.statement_records.contains(&support.statement) {
572                return Err(invalid(
573                    "support belongs to a statement outside the task scope",
574                ));
575            }
576        }
577        Ok(())
578    }
579}
580
581fn feedback_statement_payload(
582    records: &SemanticAdmissionRecords,
583    encoded: &[crate::semantic_hypergraph::SemanticRecordEncoding],
584    record: u32,
585) -> Result<Vec<u8>, SemanticTransitionError> {
586    let statement = records
587        .records
588        .get(record as usize)
589        .ok_or(SemanticTransitionError::InvalidTaskBank)?;
590    let mut payload = Vec::new();
591    let append = |payload: &mut Vec<u8>, index: u32| -> Result<(), SemanticTransitionError> {
592        let atom = encoded
593            .get(index as usize)
594            .ok_or(SemanticTransitionError::InvalidTaskBank)?;
595        // Canonical admission retains exact argument ranges. The predicate and
596        // arity occupy the eight bytes immediately before the first argument;
597        // zero-argument atoms end immediately after those same two u32 values.
598        // No symbol lookup, numeric conversion, domain or digest enters features.
599        let argument_begin = atom
600            .arguments
601            .first()
602            .map_or(atom.bytes.len(), |range| range.start);
603        let value_begin = argument_begin
604            .checked_sub(8)
605            .ok_or(SemanticTransitionError::InvalidTaskBank)?;
606        let values = atom
607            .bytes
608            .get(value_begin..)
609            .ok_or(SemanticTransitionError::InvalidTaskBank)?;
610        payload.extend_from_slice(&(values.len() as u64).to_le_bytes());
611        payload.extend_from_slice(values);
612        Ok(())
613    };
614    append(&mut payload, record)?;
615    let qualifier_count = u32::try_from(statement.qualifiers.len())
616        .map_err(|_| SemanticTransitionError::InvalidTaskBank)?;
617    payload.extend_from_slice(&qualifier_count.to_le_bytes());
618    for &qualifier in &statement.qualifiers {
619        append(&mut payload, qualifier)?;
620    }
621    Ok(payload)
622}
623
624/// Immutable native task content, separate from the controller's authority and
625/// from every operand visible to the proposal policy.
626pub(crate) struct TaskEvaluationBinding {
627    admission_identity: Identity256,
628    schema_generation: Identity256,
629    spec: SemanticTaskEvaluationSpec,
630    statements: [crate::SemanticStatementKey; 3],
631    statement_bytes: BTreeMap<u32, Vec<u8>>,
632    allowed_supports: Vec<(u32, [u8; 32])>,
633    observation: SemanticTaskObservation,
634    goal_witness: Option<SemanticTaskGoalWitness>,
635    objective_law: SemanticTaskObjectiveLaw,
636}
637
638type TaskContentSelection = (
639    [crate::SemanticStatementKey; 3],
640    BTreeMap<u32, Vec<u8>>,
641    Vec<(u32, [u8; 32])>,
642);
643
644fn task_content_selection(
645    admission: &SemanticAdmission,
646    statement_records: [u32; 3],
647    allowed_support_records: &[u32],
648) -> Result<TaskContentSelection, SemanticTransitionError> {
649    let statements = statement_records.map(|record| {
650        admission
651            .statement_key(record)
652            .map_err(SemanticTransitionError::Semantic)
653    });
654    let statements = statements.into_iter().collect::<Result<Vec<_>, _>>()?;
655    let statements: [_; 3] = statements
656        .try_into()
657        .expect("three selected task statements");
658    let mut statement_bytes = BTreeMap::new();
659    for record in statement_records {
660        statement_bytes.insert(
661            record,
662            feedback_statement_payload(admission.records(), &admission.encoded_records, record)?,
663        );
664    }
665    let mut allowed_supports = BTreeSet::new();
666    for &index in allowed_support_records {
667        let record = admission
668            .records()
669            .supports
670            .get(index as usize)
671            .ok_or(SemanticTransitionError::InvalidTaskBank)?;
672        if !statement_records.contains(&record.statement) {
673            return Err(SemanticTransitionError::InvalidTaskBank);
674        }
675        let statement = admission
676            .statement_key(record.statement)
677            .map_err(SemanticTransitionError::Semantic)?;
678        let event = admission
679            .support_event(index)
680            .map_err(SemanticTransitionError::Semantic)?;
681        allowed_supports.insert((index, *event.identity(statement.identity()).as_bytes()));
682    }
683    Ok((
684        statements,
685        statement_bytes,
686        allowed_supports.into_iter().collect(),
687    ))
688}
689
690#[expect(
691    clippy::too_many_arguments,
692    reason = "task content identity binds independent admitted and observed materials"
693)]
694fn task_content_identity(
695    admission_identity: Identity256,
696    schema_generation: Identity256,
697    statement_records: [u32; 3],
698    statements: [crate::SemanticStatementKey; 3],
699    statement_bytes: &BTreeMap<u32, Vec<u8>>,
700    allowed_supports: &[(u32, [u8; 32])],
701    observation: &SemanticTaskObservation,
702    editable: Option<&crate::SemanticProgramAdmission>,
703) -> SemanticTaskContentIdentity {
704    let append_bytes = |hash: &mut Sha256, bytes: &[u8]| {
705        hash.update((bytes.len() as u64).to_le_bytes());
706        hash.update(bytes);
707    };
708
709    let mut query = Sha256::new();
710    query.update(b"xlog.semantic.task-query.v1\0");
711    query.update((statement_records.len() as u64).to_le_bytes());
712    for (record, statement) in statement_records.into_iter().zip(statements) {
713        query.update(record.to_le_bytes());
714        query.update(statement.identity().as_bytes());
715        append_bytes(
716            &mut query,
717            statement_bytes
718                .get(&record)
719                .expect("bound query statement retains canonical bytes"),
720        );
721    }
722    append_bytes(&mut query, &observation.input_bytes);
723    let query = Identity256::from_bytes(query.finalize().into());
724
725    let mut theory_program = Sha256::new();
726    theory_program.update(b"xlog.semantic.task-theory-program.v1\0");
727    theory_program.update(admission_identity.as_bytes());
728    theory_program.update(schema_generation.as_bytes());
729    theory_program.update((allowed_supports.len() as u64).to_le_bytes());
730    for (record, support) in allowed_supports {
731        theory_program.update(record.to_le_bytes());
732        theory_program.update(support);
733    }
734    append_bytes(&mut theory_program, &observation.program_source);
735    if let Some(editable) = editable {
736        theory_program.update(b"xlog.semantic.editable-program.v1\0");
737        for word in editable.words() {
738            theory_program.update(word.to_le_bytes());
739        }
740    }
741    let theory_program = Identity256::from_bytes(theory_program.finalize().into());
742
743    let mut result = Sha256::new();
744    result.update(b"xlog.semantic.task-four-valued-result.v1\0");
745    result.update(query.as_bytes());
746    result.update(theory_program.as_bytes());
747    append_bytes(&mut result, &observation.result_bytes);
748    for truth in observation.expected_truth {
749        result.update((truth as u64).to_le_bytes());
750    }
751
752    SemanticTaskContentIdentity {
753        query,
754        theory_program,
755        result: Identity256::from_bytes(result.finalize().into()),
756    }
757}
758
759impl TaskEvaluationBinding {
760    pub(crate) fn bind(
761        admission: &SemanticAdmission,
762        spec: SemanticTaskEvaluationSpec,
763        observation: SemanticTaskObservation,
764    ) -> Result<Self, SemanticTransitionError> {
765        spec.validate_records(admission.records())?;
766        if let Some(program) = spec.program.editable_program() {
767            program
768                .validate()
769                .map_err(|detail| SemanticTransitionError::InvalidInput {
770                    detail: format!("task binding: {detail}"),
771                })?;
772        }
773        let (statements, statement_bytes, allowed_supports) = task_content_selection(
774            admission,
775            spec.statement_records,
776            &spec.allowed_support_records,
777        )?;
778        if observation.program_source.is_empty() || observation.result_bytes.is_empty() {
779            return Err(publication_input_error(
780                "native task observer omitted source or result custody",
781            ));
782        }
783        let objective_law = spec
784            .scoring
785            .objective_law(spec.program.editable_program().is_some())?;
786        Ok(Self {
787            admission_identity: admission.identity(),
788            schema_generation: admission.schema_generation(),
789            spec,
790            statements,
791            statement_bytes,
792            allowed_supports,
793            observation,
794            goal_witness: None,
795            objective_law,
796        })
797    }
798
799    pub(crate) fn identity(&self) -> Identity256 {
800        let mut hash = Sha256::new();
801        hash.update(if self.spec.program.editable_program().is_some() {
802            b"xlog.semantic.task-evaluation.v12\0".as_slice()
803        } else {
804            b"xlog.semantic.task-evaluation.v11\0".as_slice()
805        });
806        hash.update(self.admission_identity.as_bytes());
807        hash.update(self.schema_generation.as_bytes());
808        // Keep source occurrence and explicit selection order separate from
809        // the distinct original support records consumed by the device policy.
810        hash.update((self.spec.statement_records.len() as u64).to_le_bytes());
811        for index in self.spec.statement_records {
812            hash.update(index.to_le_bytes());
813        }
814        hash.update((self.spec.allowed_support_records.len() as u64).to_le_bytes());
815        for index in &self.spec.allowed_support_records {
816            hash.update(index.to_le_bytes());
817        }
818        hash.update((self.observation.program_source.len() as u64).to_le_bytes());
819        hash.update(&self.observation.program_source);
820        hash.update((self.observation.input_bytes.len() as u64).to_le_bytes());
821        hash.update(&self.observation.input_bytes);
822        hash.update((self.observation.result_bytes.len() as u64).to_le_bytes());
823        hash.update(&self.observation.result_bytes);
824        for truth in self.observation.expected_truth {
825            hash.update((truth as u64).to_le_bytes());
826        }
827        hash.update(self.spec.admissible_truth_masks);
828        hash.update([u8::from(self.spec.actor_eligible)]);
829        for weight in self.spec.scoring.words() {
830            hash.update(weight.to_le_bytes());
831        }
832        // Checkpoint task/scoring identities retain these cold numerical bits.
833        // Restore must reproduce them before an arena or publication is usable.
834        hash.update(self.objective_law.evaluator_min.to_bits().to_le_bytes());
835        hash.update(self.objective_law.evaluator_max.to_bits().to_le_bytes());
836        for coefficient in self.objective_law.coefficients {
837            hash.update(coefficient.to_bits().to_le_bytes());
838        }
839        hash.update(self.objective_law.structural_cost.unit.as_bytes());
840        hash.update(self.objective_law.structural_cost.cap.to_le_bytes());
841        hash.update([u8::from(self.spec.training_domain.is_some())]);
842        if let Some(domain) = &self.spec.training_domain {
843            hash.update(domain.identity().as_bytes());
844        }
845        hash.update(b"xlog.semantic.task-priorities.v1\0");
846        hash.update((self.spec.priority_levels.len() as u64).to_le_bytes());
847        for level in &self.spec.priority_levels {
848            hash.update((level.goals.len() as u64).to_le_bytes());
849            for goal in &level.goals {
850                hash.update([goal.query, goal.target_truth]);
851                hash.update(goal.weight.to_le_bytes());
852            }
853        }
854        if let Some(editable) = self.spec.program.editable_program() {
855            hash.update(b"xlog.semantic.editable-program.v1\0");
856            for word in editable.words() {
857                hash.update(word.to_le_bytes());
858            }
859        }
860        for statement in self.statements {
861            hash.update(statement.identity().as_bytes());
862        }
863        hash.update((self.allowed_supports.len() as u64).to_le_bytes());
864        for (record, support) in &self.allowed_supports {
865            hash.update(record.to_le_bytes());
866            hash.update(support);
867        }
868        if let Some(witness) = self.goal_witness {
869            hash.update(b"xlog.semantic.goal-witness.v1\0");
870            hash.update(witness.semantic_root.as_bytes());
871            hash.update(witness.authority_root.as_bytes());
872            hash.update(witness.mandatory_links_root.as_bytes());
873            hash.update(witness.constraints_root.as_bytes());
874            hash.update(witness.mandatory_link_count.to_le_bytes());
875            hash.update(witness.constraint_count.to_le_bytes());
876        }
877        Identity256::from_bytes(hash.finalize().into())
878    }
879
880    pub(crate) fn content_identity(&self) -> SemanticTaskContentIdentity {
881        task_content_identity(
882            self.admission_identity,
883            self.schema_generation,
884            self.spec.statement_records,
885            self.statements,
886            &self.statement_bytes,
887            &self.allowed_supports,
888            &self.observation,
889            self.spec.program.editable_program(),
890        )
891    }
892
893    pub(crate) fn cold_content(
894        admission: &SemanticAdmission,
895        statement_records: [u32; 3],
896        allowed_support_records: &[u32],
897        editable: Option<&crate::SemanticProgramAdmission>,
898        observation: SemanticTaskObservation,
899    ) -> Result<(SemanticTaskContentIdentity, [crate::SemanticTruth; 3]), SemanticTransitionError>
900    {
901        if observation.program_source.is_empty() || observation.result_bytes.is_empty() {
902            return Err(publication_input_error(
903                "native task observer omitted source or result custody",
904            ));
905        }
906        if let Some(program) = editable {
907            program
908                .validate()
909                .map_err(|detail| SemanticTransitionError::InvalidInput {
910                    detail: format!("task binding: {detail}"),
911                })?;
912        }
913        let (statements, statement_bytes, allowed_supports) =
914            task_content_selection(admission, statement_records, allowed_support_records)?;
915        let content = task_content_identity(
916            admission.identity(),
917            admission.schema_generation(),
918            statement_records,
919            statements,
920            &statement_bytes,
921            &allowed_supports,
922            &observation,
923            editable,
924        );
925        Ok((content, observation.expected_truth))
926    }
927
928    pub(crate) fn expected_truth(&self) -> [crate::SemanticTruth; 3] {
929        self.observation.expected_truth
930    }
931
932    #[cfg(feature = "semantic-policy")]
933    fn goal_witness(&self) -> Option<SemanticTaskGoalWitness> {
934        self.goal_witness
935    }
936
937    pub(crate) fn content(&self) -> (SemanticTaskContentIdentity, [crate::SemanticTruth; 3]) {
938        (self.content_identity(), self.expected_truth())
939    }
940
941    #[cfg(feature = "semantic-policy")]
942    fn completed_result_material(&self) -> SemanticCompletedStepWitnessMaterial {
943        let identities = self.content_identity();
944        let mut bytes = Vec::new();
945        bytes.extend_from_slice(b"xlog.semantic.task-four-valued-result.v1\0");
946        bytes.extend_from_slice(identities.query.as_bytes());
947        bytes.extend_from_slice(identities.theory_program.as_bytes());
948        material_u64(&mut bytes, self.observation.result_bytes.len() as u64);
949        bytes.extend_from_slice(&self.observation.result_bytes);
950        for truth in self.observation.expected_truth {
951            material_u64(&mut bytes, truth as u64);
952        }
953        SemanticCompletedStepWitnessMaterial {
954            identity: identities.result,
955            bytes,
956        }
957    }
958
959    pub(crate) fn spec(&self) -> &SemanticTaskEvaluationSpec {
960        &self.spec
961    }
962
963    pub(crate) fn priority_levels(&self) -> &[SemanticTaskPriorityLevel] {
964        &self.spec.priority_levels
965    }
966
967    pub(crate) fn words(&self, owner: u64) -> Vec<u64> {
968        let mut words = vec![6, owner];
969        words.extend(identity_words(*self.identity().as_bytes()));
970        for statement in self.statements {
971            words.extend(identity_words(*statement.identity().as_bytes()));
972        }
973        words.extend(self.observation.expected_truth.map(|truth| truth as u64));
974        words.push(self.allowed_supports.len() as u64);
975        words.extend(self.spec.statement_records.map(u64::from));
976        words.extend(self.spec.scoring.words());
977        words.extend(self.spec.admissible_truth_masks.map(u64::from));
978        for (record, support) in &self.allowed_supports {
979            words.push(u64::from(*record));
980            words.extend(identity_words(*support));
981        }
982        if let Some(witness) = self.goal_witness {
983            words.extend(identity_words(*witness.semantic_root.as_bytes()));
984            words.extend(identity_words(*witness.authority_root.as_bytes()));
985            words.extend(identity_words(*witness.mandatory_links_root.as_bytes()));
986            words.extend(identity_words(*witness.constraints_root.as_bytes()));
987            words.push(witness.mandatory_link_count);
988            words.push(witness.constraint_count);
989        } else {
990            words.extend([0; 18]);
991        }
992        words.push(u64::from(self.spec.actor_eligible));
993        words.push(self.spec.priority_levels.len() as u64);
994        for level in self.spec.priority_levels.iter().take(3) {
995            words.push(level.goals.len() as u64);
996        }
997        words.resize(words.len() + 3 - self.spec.priority_levels.len(), 0);
998        let mut goals = 0;
999        for level in &self.spec.priority_levels {
1000            for goal in &level.goals {
1001                words.extend([
1002                    u64::from(goal.query),
1003                    u64::from(goal.target_truth),
1004                    u64::from(goal.weight),
1005                ]);
1006                goals += 1;
1007            }
1008        }
1009        words.resize(words.len() + (3 - goals) * 3, 0);
1010        if let Some(editable) = self.spec.program.editable_program() {
1011            let bank = editable.words();
1012            words.extend([1, bank.len() as u64]);
1013            words.extend(bank);
1014        }
1015        words
1016    }
1017}
1018
1019/// One row of the generated roster. Text fields are text positions; edit fields
1020/// index the eighteen-field action signature. Offsets count input elements.
1021#[repr(C)]
1022#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1023pub struct SemanticComponent {
1024    pub offset: u64,
1025    pub ordinal: u32,
1026    pub lane: u32,
1027    pub slot: u32,
1028    pub field: u32,
1029    pub kind: u32,
1030    pub cardinality: u32,
1031}
1032
1033impl SemanticComponent {
1034    pub const fn is_text(&self) -> bool {
1035        self.kind == COMPONENT_KIND_TEXT as u32
1036    }
1037}
1038
1039/// Field codebook role and NULL-only cold cardinality in this catalogue.
1040pub struct SemanticCatalogueField {
1041    pub ordinal: u32,
1042    pub cardinality: u32,
1043    pub name: &'static str,
1044    pub role: &'static str,
1045}
1046
1047/// Declarative action/opcode signature, including dependent opcode selection.
1048pub struct SemanticCatalogueSignature {
1049    pub value: u32,
1050    pub kind: &'static str,
1051    pub name: &'static str,
1052    pub signature: &'static str,
1053}
1054
1055include!(concat!(
1056    env!("OUT_DIR"),
1057    "/semantic_transition_catalogue.rs"
1058));
1059
1060pub const SEMANTIC_TRANSITION_GENERATION: u64 = CATALOGUE_GENERATION;
1061pub const SEMANTIC_TRANSITION_COMPONENT_COUNT: usize = COMPONENT_COUNT;
1062
1063#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1064pub struct SemanticCatalogueBinding {
1065    pub generation: u64,
1066    pub digest: Identity256,
1067}
1068
1069/// The sole built-in action law; both Rust and CUDA are generated from its declaration.
1070pub struct SemanticActionCatalogue;
1071
1072impl SemanticActionCatalogue {
1073    pub const fn current() -> Self {
1074        Self
1075    }
1076    pub const fn binding(&self) -> SemanticCatalogueBinding {
1077        SemanticCatalogueBinding {
1078            generation: CATALOGUE_GENERATION,
1079            digest: Identity256::from_bytes(CATALOGUE_DIGEST),
1080        }
1081    }
1082    pub const fn canonical_bytes(&self) -> &'static [u8] {
1083        CATALOGUE_ENCODING
1084    }
1085    #[cfg(feature = "semantic-policy")]
1086    fn completed_material(&self) -> SemanticCompletedStepWitnessMaterial {
1087        SemanticCompletedStepWitnessMaterial {
1088            identity: self.binding().digest,
1089            bytes: self.canonical_bytes().to_vec(),
1090        }
1091    }
1092    pub const fn components(&self) -> &'static [SemanticComponent] {
1093        COMPONENTS
1094    }
1095    pub const fn fields(&self) -> &'static [SemanticCatalogueField] {
1096        CATALOGUE_FIELDS
1097    }
1098    pub const fn signatures(&self) -> &'static [SemanticCatalogueSignature] {
1099        CATALOGUE_SIGNATURES
1100    }
1101    pub const fn text_cardinality(&self) -> usize {
1102        TEXT_CARDINALITY
1103    }
1104    pub const fn scratch_bytes(&self) -> usize {
1105        SCRATCH_BYTES
1106    }
1107    /// (active fields, forced-NULL fields) for NO_EDIT, INSERT_SUPPORT and INSERT_RULE.
1108    pub const fn field_masks(&self) -> [(u32, u32); 3] {
1109        [
1110            (NO_EDIT_ACTIVE_MASK as u32, NO_EDIT_NULL_MASK as u32),
1111            (
1112                INSERT_SUPPORT_ACTIVE_MASK as u32,
1113                INSERT_SUPPORT_NULL_MASK as u32,
1114            ),
1115            (INSERT_RULE_ACTIVE_MASK as u32, INSERT_RULE_NULL_MASK as u32),
1116        ]
1117    }
1118}
1119
1120/// Cold-bound FP32 logits and binary product support in original category order.
1121pub struct SemanticComponentInput {
1122    pub logits: Vec<f32>,
1123    pub product_support: Vec<u8>,
1124}
1125
1126/// FP32 element ranges for one field in the native policy parameter snapshot.
1127/// NULL is a category, but has no stored embedding row. The action-class field
1128/// has no NULL: its category zero is the trainable no-edit action.
1129#[derive(Clone, Debug, PartialEq, Eq)]
1130pub struct SemanticPolicyFieldLayout {
1131    pub embeddings: std::ops::Range<usize>,
1132    pub biases: std::ops::Range<usize>,
1133    pub cardinality: usize,
1134    pub null_category: Option<usize>,
1135}
1136
1137/// Packing of the immutable policy inputs consumed by the serial component loop.
1138/// These ranges describe storage, not authority to substitute a model generation.
1139/// A session derives the layout from its retained admission's actual codebooks.
1140#[derive(Clone, Debug, PartialEq, Eq)]
1141pub struct SemanticPolicyLayout {
1142    pub z: std::ops::Range<usize>,
1143    pub recurrence: std::ops::Range<usize>,
1144    pub positions: std::ops::Range<usize>,
1145    pub fields: Vec<SemanticPolicyFieldLayout>,
1146    pub parameter_cells: usize,
1147}
1148
1149impl SemanticPolicyLayout {
1150    fn from_components(components: &[SemanticComponent]) -> Result<Self, SemanticTransitionError> {
1151        let invalid = || SemanticTransitionError::InvalidInput {
1152            detail: "policy layout requires the complete native component roster".into(),
1153        };
1154        if components.len() != COMPONENT_COUNT {
1155            return Err(invalid());
1156        }
1157        let z = 0usize..4 * 128;
1158        let recurrence = z.end..z.end + 128 * 128;
1159        let positions = recurrence.end..recurrence.end + 18 * 128;
1160        let mut cursor = positions.end;
1161        let mut fields = Vec::with_capacity(18);
1162        for field in 0..18 {
1163            let cardinality = components[32 + field].cardinality as usize;
1164            if cardinality == 0 {
1165                return Err(invalid());
1166            }
1167            for lane in 0..2 {
1168                for slot in 0..2 {
1169                    let component = components[lane * 68 + 32 + slot * 18 + field];
1170                    if component.kind != COMPONENT_KIND_EDIT as u32
1171                        || component.field as usize != field
1172                        || component.lane as usize != lane + 1
1173                        || component.slot as usize != slot
1174                        || component.cardinality as usize != cardinality
1175                    {
1176                        return Err(invalid());
1177                    }
1178                }
1179            }
1180            let null_category = (field != 0).then_some(0);
1181            let embedding_cells = (cardinality - usize::from(null_category.is_some()))
1182                .checked_mul(128)
1183                .ok_or_else(invalid)?;
1184            let end = cursor.checked_add(embedding_cells).ok_or_else(invalid)?;
1185            let embeddings = cursor..end;
1186            cursor = end;
1187            let bias_cells = if null_category.is_some() && cardinality == 1 {
1188                0
1189            } else {
1190                cardinality
1191            };
1192            let end = cursor.checked_add(bias_cells).ok_or_else(invalid)?;
1193            let biases = cursor..end;
1194            cursor = end;
1195            fields.push(SemanticPolicyFieldLayout {
1196                embeddings,
1197                biases,
1198                cardinality,
1199                null_category,
1200            });
1201        }
1202        Ok(Self {
1203            z,
1204            recurrence,
1205            positions,
1206            fields,
1207            parameter_cells: cursor,
1208        })
1209    }
1210
1211    /// Both lanes retain the initial state and all thirty-six field successors.
1212    pub const fn recurrent_cells(&self) -> usize {
1213        2 * 37 * 128
1214    }
1215
1216    /// The same score bank is reused serially by every structural component.
1217    pub fn score_cells(&self) -> usize {
1218        self.fields
1219            .iter()
1220            .map(|field| field.cardinality)
1221            .max()
1222            .unwrap_or(0)
1223    }
1224
1225    #[cfg(feature = "semantic-policy")]
1226    fn retained_score_stride(&self) -> usize {
1227        self.fields.iter().map(|field| field.cardinality).sum()
1228    }
1229
1230    #[cfg(feature = "semantic-policy")]
1231    fn retained_score_cells(&self) -> usize {
1232        4 * self.retained_score_stride()
1233    }
1234}
1235
1236/// Immutable descriptor meanings derived from the graph's admitted records.
1237/// Category zero is NULL. Nonzero categories are sorted by logical typed bytes,
1238/// independent of arena slots and digests. Equal-valued support records retain
1239/// separate categories, ordered by their original admission index.
1240#[derive(Clone, Debug, PartialEq, Eq)]
1241pub enum SemanticActionDescriptor {
1242    Target {
1243        predicate: xlog_core::RelId,
1244    },
1245    Operand {
1246        scalar_type: xlog_core::ScalarType,
1247        sort_label: String,
1248        encoded_value: Vec<u8>,
1249    },
1250    QualifierBundle {
1251        records: Vec<u32>,
1252    },
1253    SupportEvent {
1254        source_record: u32,
1255    },
1256    RulePredicate {
1257        predicate: u32,
1258    },
1259    RuleVariable {
1260        index: u32,
1261    },
1262}
1263
1264#[cfg(feature = "semantic-policy")]
1265struct SemanticDecodedSupportInsertion {
1266    statement: SemanticStatementIdentity,
1267    support: SemanticSupportIdentity,
1268    source_event: u32,
1269    reconstruction: [u32; 10],
1270    bytes: Vec<u8>,
1271}
1272
1273struct SemanticDecodedRuleInsertion {
1274    rule: crate::SemanticProgramRule,
1275    #[cfg(any(feature = "semantic-policy", test))]
1276    bytes: Vec<u8>,
1277}
1278
1279fn semantic_program_rule_words(rule: crate::SemanticProgramRule) -> [u64; 10] {
1280    [
1281        rule.head_predicate,
1282        rule.left_predicate,
1283        rule.right_predicate,
1284        rule.body_count,
1285        rule.head_variables[0],
1286        rule.head_variables[1],
1287        rule.left_variables[0],
1288        rule.left_variables[1],
1289        rule.right_variables[0],
1290        rule.right_variables[1],
1291    ]
1292    .map(u64::from)
1293}
1294
1295struct ActionCodebooks {
1296    words: Vec<u64>,
1297    targets: Vec<SemanticActionDescriptor>,
1298    operands: Vec<SemanticActionDescriptor>,
1299    qualifiers: Vec<SemanticActionDescriptor>,
1300    leaves: Vec<SemanticActionDescriptor>,
1301    components: Vec<SemanticComponent>,
1302    binding: SemanticCatalogueBinding,
1303    program_binding: Option<Identity256>,
1304    input_cells: usize,
1305}
1306
1307impl ActionCodebooks {
1308    fn program_binding(program: &crate::SemanticProgramAdmission) -> Identity256 {
1309        let mut hash = Sha256::new();
1310        hash.update(b"xlog.semantic.rule-codebook.program.v1\0");
1311        for word in program.words() {
1312            hash.update(word.to_le_bytes());
1313        }
1314        Identity256::from_bytes(hash.finalize().into())
1315    }
1316
1317    fn decoded_rule_insertion(
1318        &self,
1319        program: &crate::SemanticProgramAdmission,
1320        choices: &[u32; 18],
1321    ) -> Result<SemanticDecodedRuleInsertion, SemanticTransitionError> {
1322        if self.program_binding != Some(Self::program_binding(program))
1323            || choices[0] != 1
1324            || choices[1] != 2
1325            || choices[11..].iter().any(|&choice| choice != 0)
1326        {
1327            return Err(SemanticTransitionError::ObservationMismatch);
1328        }
1329        fn chosen(
1330            entries: &[SemanticActionDescriptor],
1331            choice: u32,
1332        ) -> Result<&SemanticActionDescriptor, SemanticTransitionError> {
1333            choice
1334                .checked_sub(1)
1335                .and_then(|index| entries.get(index as usize))
1336                .ok_or(SemanticTransitionError::ObservationMismatch)
1337        }
1338        let predicate = |entry: &SemanticActionDescriptor| match entry {
1339            SemanticActionDescriptor::RulePredicate { predicate }
1340                if *predicate < program.predicate_count =>
1341            {
1342                Ok(*predicate)
1343            }
1344            _ => Err(SemanticTransitionError::ObservationMismatch),
1345        };
1346        let variable = |entry: &SemanticActionDescriptor| match entry {
1347            SemanticActionDescriptor::RuleVariable { index } if *index < 4 => Ok(*index),
1348            _ => Err(SemanticTransitionError::ObservationMismatch),
1349        };
1350        let rule = crate::SemanticProgramRule {
1351            head_predicate: predicate(chosen(&self.targets, choices[2])?)?,
1352            left_predicate: predicate(chosen(&self.operands, choices[3])?)?,
1353            right_predicate: predicate(chosen(&self.operands, choices[4])?)?,
1354            body_count: 2,
1355            head_variables: [
1356                variable(chosen(&self.operands, choices[5])?)?,
1357                variable(chosen(&self.operands, choices[6])?)?,
1358            ],
1359            left_variables: [
1360                variable(chosen(&self.operands, choices[7])?)?,
1361                variable(chosen(&self.operands, choices[8])?)?,
1362            ],
1363            right_variables: [
1364                variable(chosen(&self.operands, choices[9])?)?,
1365                variable(chosen(&self.operands, choices[10])?)?,
1366            ],
1367        };
1368        let bound = rule
1369            .left_variables
1370            .into_iter()
1371            .chain(rule.right_variables)
1372            .fold(0u8, |set, index| set | (1 << index));
1373        if rule
1374            .head_variables
1375            .iter()
1376            .any(|index| bound & (1 << index) == 0)
1377        {
1378            return Err(SemanticTransitionError::ObservationMismatch);
1379        }
1380        #[cfg(any(feature = "semantic-policy", test))]
1381        let bytes = {
1382            let mut bytes = Vec::new();
1383            bytes.extend_from_slice(b"XLOG-DECODED-RULE-INSERTION\0");
1384            material_u64(&mut bytes, 1);
1385            bytes.extend_from_slice(self.binding.digest.as_bytes());
1386            bytes.extend_from_slice(Self::program_binding(program).as_bytes());
1387            for &choice in choices {
1388                material_u32(&mut bytes, choice);
1389            }
1390            for field in semantic_program_rule_words(rule) {
1391                material_u32(&mut bytes, field as u32);
1392            }
1393            bytes
1394        };
1395        Ok(SemanticDecodedRuleInsertion {
1396            rule,
1397            #[cfg(any(feature = "semantic-policy", test))]
1398            bytes,
1399        })
1400    }
1401
1402    #[cfg(feature = "semantic-policy")]
1403    fn decoded_support_insertion(
1404        &self,
1405        admission: &SemanticAdmission,
1406        choices: &[u32; 18],
1407    ) -> Result<Option<SemanticDecodedSupportInsertion>, SemanticTransitionError> {
1408        if choices[0] == 0 {
1409            return Ok(None);
1410        }
1411        if choices[0] != 1 || choices[1] != 1 {
1412            return Err(SemanticTransitionError::ObservationMismatch);
1413        }
1414        let chosen = |count: usize, choice: u32| {
1415            usize::try_from(choice)
1416                .ok()
1417                .and_then(|choice| choice.checked_sub(1))
1418                .filter(|&index| index < count)
1419                .ok_or(SemanticTransitionError::ObservationMismatch)
1420        };
1421        let target = chosen(self.targets.len(), choices[2])?;
1422        let predicate = match self.targets[target] {
1423            SemanticActionDescriptor::Target { predicate } => predicate,
1424            _ => return Err(SemanticTransitionError::ObservationMismatch),
1425        };
1426        let arity = admission
1427            .records()
1428            .predicates
1429            .iter()
1430            .find(|entry| entry.predicate == predicate)
1431            .ok_or(SemanticTransitionError::ObservationMismatch)?
1432            .schema
1433            .arity();
1434        let mut reconstruction = [0u32; 10];
1435        reconstruction[0] = predicate.0;
1436        for argument in 0..arity {
1437            let choice = choices[3 + argument];
1438            chosen(self.operands.len(), choice)?;
1439            let offset = self.words[2] as usize + 6 * choice as usize;
1440            reconstruction[1 + 2 * argument] = self.words[offset + 4] as u32;
1441            reconstruction[2 + 2 * argument] = self.words[offset + 5] as u32;
1442        }
1443        let qualifier = choices[11];
1444        chosen(self.qualifiers.len(), qualifier)?;
1445        reconstruction[9] = self.words[self.words[4] as usize + 3 * qualifier as usize + 2] as u32;
1446        let leaf = chosen(self.leaves.len(), choices[17])?;
1447        let source_event = match self.leaves[leaf] {
1448            SemanticActionDescriptor::SupportEvent { source_record } => source_record,
1449            _ => return Err(SemanticTransitionError::ObservationMismatch),
1450        };
1451        let statement = material_statement_key(admission, None, &reconstruction)
1452            .map_err(SemanticTransitionError::Semantic)?
1453            .identity();
1454        let support = admission
1455            .support_event(source_event)
1456            .map_err(SemanticTransitionError::Semantic)?
1457            .identity(statement);
1458        let mut bytes = Vec::new();
1459        bytes.extend_from_slice(b"XLOG-DECODED-SUPPORT-INSERTION\0");
1460        material_u64(&mut bytes, 1);
1461        bytes.extend_from_slice(self.binding.digest.as_bytes());
1462        for &choice in choices {
1463            material_u32(&mut bytes, choice);
1464        }
1465        bytes.extend_from_slice(statement.as_bytes());
1466        bytes.extend_from_slice(support.as_bytes());
1467        material_u32(&mut bytes, source_event);
1468        for reference in reconstruction {
1469            material_u32(&mut bytes, reference);
1470        }
1471        Ok(Some(SemanticDecodedSupportInsertion {
1472            statement,
1473            support,
1474            source_event,
1475            reconstruction,
1476            bytes,
1477        }))
1478    }
1479
1480    #[cfg(feature = "semantic-policy")]
1481    fn completed_material(&self) -> SemanticCompletedStepWitnessMaterial {
1482        SemanticCompletedStepWitnessMaterial {
1483            identity: self.binding.digest,
1484            bytes: publication_abi_bytes(&self.words),
1485        }
1486    }
1487
1488    #[cfg(feature = "semantic-policy")]
1489    fn completed_roster_material(&self) -> SemanticCompletedStepWitnessMaterial {
1490        let mut bytes = Vec::with_capacity(
1491            b"xlog.semantic-action-roster.v1\0".len() + 32 + 8 + self.components.len() * 7 * 8,
1492        );
1493        bytes.extend_from_slice(b"xlog.semantic-action-roster.v1\0");
1494        bytes.extend_from_slice(self.binding.digest.as_bytes());
1495        material_u64(&mut bytes, self.components.len() as u64);
1496        for component in &self.components {
1497            for value in [
1498                component.offset,
1499                component.ordinal as u64,
1500                component.lane as u64,
1501                component.slot as u64,
1502                component.field as u64,
1503                component.kind as u64,
1504                component.cardinality as u64,
1505            ] {
1506                material_u64(&mut bytes, value);
1507            }
1508        }
1509        SemanticCompletedStepWitnessMaterial {
1510            identity: Identity256::from_bytes(Sha256::digest(&bytes).into()),
1511            bytes,
1512        }
1513    }
1514
1515    fn support_layout(&self) -> (Vec<std::ops::Range<usize>>, usize) {
1516        (
1517            self.components
1518                .iter()
1519                .map(|component| {
1520                    component.offset as usize
1521                        ..component.offset as usize + component.cardinality as usize
1522                })
1523                .collect(),
1524            self.input_cells,
1525        )
1526    }
1527
1528    fn derive(
1529        admission: &SemanticAdmission,
1530        owner: u64,
1531        program: Option<&crate::SemanticProgramAdmission>,
1532    ) -> Result<Self, SemanticTransitionError> {
1533        if let Some(program) = program {
1534            program
1535                .validate()
1536                .map_err(|detail| SemanticTransitionError::InvalidInput {
1537                    detail: detail.into(),
1538                })?;
1539        }
1540        let records = admission.records();
1541        let predicates: BTreeMap<_, _> = records
1542            .predicates
1543            .iter()
1544            .map(|p| (p.predicate.0, p))
1545            .collect();
1546        let sorts: BTreeSet<_> = records
1547            .predicates
1548            .iter()
1549            .flat_map(|p| p.schema.sort_labels().iter().cloned())
1550            .collect();
1551        let sorts: BTreeMap<_, _> = sorts
1552            .into_iter()
1553            .enumerate()
1554            .map(|(i, s)| (s, i as u64 + 1))
1555            .collect();
1556        let mut targets = BTreeMap::new();
1557        for p in predicates
1558            .values()
1559            .filter(|p| p.role == SemanticRecordRole::Statement && p.schema.arity() <= 4)
1560        {
1561            let mut row = vec![p.predicate.0 as u64, p.schema.arity() as u64];
1562            row.extend((0..4).map(|i| {
1563                p.schema
1564                    .columns
1565                    .get(i)
1566                    .map_or(0, |(_, t)| t.to_code() as u64 + 1)
1567            }));
1568            row.extend((0..4).map(|i| p.schema.sort_labels().get(i).map_or(0, |s| sorts[s])));
1569            targets.insert(
1570                p.predicate.0.to_le_bytes(),
1571                (
1572                    row,
1573                    SemanticActionDescriptor::Target {
1574                        predicate: p.predicate,
1575                    },
1576                ),
1577            );
1578        }
1579        let mut operands = BTreeMap::new();
1580        for (record_index, (record, encoded)) in records
1581            .records
1582            .iter()
1583            .zip(&admission.encoded_records)
1584            .enumerate()
1585        {
1586            let schema = &predicates[&record.predicate.0].schema;
1587            for (i, range) in encoded.arguments.iter().enumerate() {
1588                let value = encoded.bytes[range.clone()].to_vec();
1589                let label = &schema.sort_labels()[i];
1590                let mut key = value.clone();
1591                key.extend_from_slice(&(label.len() as u64).to_le_bytes());
1592                key.extend_from_slice(label.as_bytes());
1593                operands.entry(key).or_insert_with(|| {
1594                    (
1595                        value.clone(),
1596                        schema.columns[i].1.to_code() as u64 + 1,
1597                        sorts[label],
1598                        record_index as u64,
1599                        i as u64,
1600                        SemanticActionDescriptor::Operand {
1601                            scalar_type: schema.columns[i].1,
1602                            sort_label: label.clone(),
1603                            encoded_value: value,
1604                        },
1605                    )
1606                });
1607            }
1608        }
1609        let logical = |indices: &[u32]| {
1610            let mut bytes = (indices.len() as u32).to_le_bytes().to_vec();
1611            for &index in indices {
1612                let atom = &admission.encoded_records[index as usize].bytes;
1613                bytes.extend_from_slice(&(atom.len() as u64).to_le_bytes());
1614                bytes.extend_from_slice(atom);
1615            }
1616            bytes
1617        };
1618        let mut qualifiers = BTreeMap::new();
1619        qualifiers.insert(logical(&[]), (Vec::new(), u32::MAX));
1620        for (index, record) in records.records.iter().enumerate() {
1621            if predicates[&record.predicate.0].role == SemanticRecordRole::Statement {
1622                qualifiers
1623                    .entry(logical(&record.qualifiers))
1624                    .or_insert_with(|| (record.qualifiers.clone(), index as u32));
1625            }
1626        }
1627        let mut leaves = BTreeMap::new();
1628        for (index, support) in records.supports.iter().enumerate() {
1629            let polarity = match support.polarity {
1630                crate::SemanticPolarity::Pro => 1u64,
1631                crate::SemanticPolarity::Contra => 2,
1632            };
1633            let refs = [
1634                support.provenance,
1635                support.source,
1636                support.context,
1637                support.scope,
1638            ];
1639            let mut key = polarity.to_le_bytes().to_vec();
1640            key.extend(logical(&refs));
1641            let mut words = vec![polarity];
1642            for record in refs {
1643                words.extend(identity_words(
1644                    Sha256::digest(&admission.encoded_records[record as usize].bytes).into(),
1645                ));
1646            }
1647            words.push(index as u64);
1648            leaves.insert(
1649                (key, index),
1650                (
1651                    words,
1652                    SemanticActionDescriptor::SupportEvent {
1653                        source_record: index as u32,
1654                    },
1655                ),
1656            );
1657        }
1658        let additional_targets = program
1659            .map(|program| program.predicate_count as usize)
1660            .unwrap_or(0);
1661        let additional_operands = program
1662            .map(|program| program.predicate_count as usize + 4)
1663            .unwrap_or(0);
1664        if [
1665            targets.len().saturating_add(additional_targets),
1666            operands.len().saturating_add(additional_operands),
1667            qualifiers.len(),
1668            leaves.len(),
1669        ]
1670        .into_iter()
1671        .any(|n| n >= 65536)
1672        {
1673            return Err(SemanticTransitionError::InvalidInput {
1674                detail: "descriptor codebook exceeds 65535 non-NULL entries".into(),
1675            });
1676        }
1677        let mut words = vec![0; 25];
1678        let mut bytes = Vec::new();
1679        words[0] = words.len() as u64;
1680        words[1] = (targets.len() + additional_targets) as u64 + 1;
1681        words.extend([0; 10]);
1682        let mut target_views: Vec<SemanticActionDescriptor> = targets
1683            .into_values()
1684            .map(|(row, view)| {
1685                words.extend(row);
1686                view
1687            })
1688            .collect();
1689        if let Some(program) = program {
1690            for predicate in 0..program.predicate_count {
1691                words.extend([u64::from(predicate), u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0]);
1692                target_views.push(SemanticActionDescriptor::RulePredicate { predicate });
1693            }
1694        }
1695        words[2] = words.len() as u64;
1696        words[3] = (operands.len() + additional_operands) as u64 + 1;
1697        words.extend([0; 6]);
1698        let mut operand_views: Vec<SemanticActionDescriptor> = operands
1699            .into_values()
1700            .map(|(value, ty, sort, record, argument, view)| {
1701                words.extend([
1702                    bytes.len() as u64,
1703                    value.len() as u64,
1704                    ty,
1705                    sort,
1706                    record,
1707                    argument,
1708                ]);
1709                bytes.extend(value);
1710                view
1711            })
1712            .collect();
1713        if let Some(program) = program {
1714            for predicate in 0..program.predicate_count {
1715                words.extend([0, 0, 0, 1, u64::from(predicate), 0]);
1716                operand_views.push(SemanticActionDescriptor::RulePredicate { predicate });
1717            }
1718            for index in 0..4 {
1719                words.extend([0, 0, 0, 2, u64::from(index), 0]);
1720                operand_views.push(SemanticActionDescriptor::RuleVariable { index });
1721            }
1722        }
1723        words[4] = words.len() as u64;
1724        words[5] = qualifiers.len() as u64 + 1;
1725        words.extend([0; 3]);
1726        let qualifier_views = qualifiers
1727            .into_values()
1728            .map(|(refs, source)| {
1729                let offset = bytes.len();
1730                bytes.extend_from_slice(&(refs.len() as u32).to_le_bytes());
1731                for &index in &refs {
1732                    bytes.extend_from_slice(&Sha256::digest(
1733                        &admission.encoded_records[index as usize].bytes,
1734                    ));
1735                }
1736                words.extend([
1737                    offset as u64,
1738                    (bytes.len() - offset) as u64,
1739                    u64::from(source),
1740                ]);
1741                SemanticActionDescriptor::QualifierBundle { records: refs }
1742            })
1743            .collect();
1744        words[6] = words.len() as u64;
1745        words[7] = leaves.len() as u64 + 1;
1746        words.extend([0; 18]);
1747        let leaf_views = leaves
1748            .into_values()
1749            .map(|(row, view)| {
1750                words.extend(row);
1751                view
1752            })
1753            .collect();
1754        words[8] = words.len() as u64 * 8;
1755        words[9] = bytes.len() as u64;
1756        words[10..14].copy_from_slice(&identity_words(*admission.schema_generation().as_bytes()));
1757        words[14] = owner;
1758        words[15] = admission.base().slot() as u64;
1759        words[16] = admission.base().generation();
1760        words[17..21].copy_from_slice(&identity_words(
1761            *admission.base_snapshot().digest().as_bytes(),
1762        ));
1763        bytes.resize(bytes.len().div_ceil(8) * 8, 0);
1764        words.extend(
1765            bytes
1766                .as_chunks::<8>()
1767                .0
1768                .iter()
1769                .map(|v| u64::from_le_bytes(*v)),
1770        );
1771        let mut hash = Sha256::new();
1772        hash.update(b"xlog.semantic.action-binding.v4\0");
1773        hash.update(CATALOGUE_DIGEST);
1774        hash.update(admission.identity().as_bytes());
1775        let program_binding = program.map(Self::program_binding);
1776        if let Some(identity) = program_binding {
1777            hash.update(identity.as_bytes());
1778        }
1779        for &word in &words {
1780            hash.update(word.to_le_bytes());
1781        }
1782        let digest = Identity256::from_bytes(hash.finalize().into());
1783        words[21..25].copy_from_slice(&identity_words(*digest.as_bytes()));
1784        let mut offset = 0u64;
1785        let components = COMPONENTS
1786            .iter()
1787            .map(|&c| {
1788                let cardinality = if c.is_text() {
1789                    c.cardinality
1790                } else {
1791                    match c.field {
1792                        2 => words[1] as u32,
1793                        3..=6 => words[3] as u32,
1794                        7..=10 if program.is_some() => words[3] as u32,
1795                        1 if program.is_none() => 2,
1796                        11 => words[5] as u32,
1797                        17 => words[7] as u32,
1798                        _ => c.cardinality,
1799                    }
1800                };
1801                let result = SemanticComponent {
1802                    offset,
1803                    cardinality,
1804                    ..c
1805                };
1806                offset += cardinality as u64;
1807                result
1808            })
1809            .collect();
1810        Ok(Self {
1811            words,
1812            targets: target_views,
1813            operands: operand_views,
1814            qualifiers: qualifier_views,
1815            leaves: leaf_views,
1816            components,
1817            binding: SemanticCatalogueBinding {
1818                generation: CATALOGUE_GENERATION,
1819                digest,
1820            },
1821            program_binding,
1822            input_cells: offset as usize,
1823        })
1824    }
1825}
1826
1827fn identity_words(bytes: [u8; 32]) -> [u64; 4] {
1828    std::array::from_fn(|i| u64::from_le_bytes(bytes[8 * i..8 * i + 8].try_into().unwrap()))
1829}
1830
1831// SAFETY: fixed C layout, integral fields only.
1832unsafe impl DeviceRepr for SemanticComponent {}
1833
1834#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1835pub struct SemanticRngBinding {
1836    pub model_generation: u32,
1837    pub stream_serial: u64,
1838    pub family_id: u8,
1839    pub proposal: u32,
1840}
1841
1842/// Device-produced receipt. Integers use three little-endian 64-bit limbs.
1843/// The exact probability is p/q; the exact importance factor is
1844/// p/factor_denominator. Singleton rows canonically use 1/1 for both.
1845#[repr(C)]
1846#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1847pub struct SemanticTransitionReceipt {
1848    pub proposal: u64,
1849    pub catalogue_generation: u64,
1850    pub catalogue_digest: Identity256,
1851    /// Binds the retained admission, acquired base, owner and logical codebooks.
1852    pub admission_binding: Identity256,
1853    pub ordinal: u32,
1854    pub lane: u32,
1855    pub slot: u32,
1856    pub field: u32,
1857    pub kind: u32,
1858    pub choice: u32,
1859    pub legal_count: u32,
1860    pub active_count: u32,
1861    pub selected_rank: u32,
1862    pub reserved: u32,
1863    pub key: [u32; 2],
1864    pub counter: [u32; 4],
1865    pub random_words: [u32; 4],
1866    pub draw: u64,
1867    pub cdf_start: u64,
1868    pub cdf_end: u64,
1869    pub mass: u64,
1870    pub p: [u64; 3],
1871    pub q: [u64; 3],
1872    pub factor_denominator: [u64; 3],
1873    pub cumulative_mass_below: [u64; 3],
1874    pub active_fields: u32,
1875    pub null_fields: u32,
1876}
1877
1878// SAFETY: C layout, integral fields only; all bit patterns are valid.
1879unsafe impl DeviceRepr for SemanticTransitionReceipt {}
1880
1881fn canonical_text_null(receipt: &SemanticTransitionReceipt) -> bool {
1882    receipt.kind == COMPONENT_KIND_TEXT as u32
1883        && receipt.choice == TEXT_NULL as u32
1884        && receipt.legal_count == 1
1885        && receipt.active_count == 1
1886        && receipt.selected_rank == 0
1887        && receipt.cumulative_mass_below == [0, 0, 0]
1888        && receipt.active_fields == 0
1889        && receipt.null_fields == 0
1890        && receipt.p == [1, 0, 0]
1891        && receipt.q == [1, 0, 0]
1892        && receipt.factor_denominator == [1, 0, 0]
1893        && receipt.cdf_start == 0
1894        && receipt.cdf_end == 1 << 63
1895        && receipt.mass == 1 << 63
1896}
1897
1898/// Device-computed facts, using the three actual canonical truth-query results.
1899#[repr(C)]
1900#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1901pub struct SemanticTaskFacts {
1902    /// Ordered actual Truth4 codes for the three task queries. A task-refused
1903    /// lane has no executed truth outcome; its terminal refusal is authoritative.
1904    pub truth: [u64; 3],
1905    /// Equality of each actual Truth4 answer to the protected observer result.
1906    pub correct: [u64; 3],
1907    /// Number of correct subgoals, in the inclusive range zero to three.
1908    pub g: u64,
1909    /// Parent completion: all three subgoals are correct (zero or one).
1910    pub p: u64,
1911    /// Actual edit commands plus added supports plus defined truth changes.
1912    pub c: u64,
1913    /// Query agreement minus measured work, using the bound task coefficients.
1914    pub v: i64,
1915    /// Whether the candidate satisfies the task scope and hard constraints.
1916    pub eligible: u64,
1917}
1918
1919#[repr(C)]
1920#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1921struct DeviceTaskEvaluation {
1922    lane_refusal: [u64; 2],
1923    query_receipts: [[[u64; 42]; 3]; 3],
1924    query_count: u64,
1925    winner: u64,
1926    return_value: i64,
1927    facts: [SemanticTaskFacts; 3],
1928}
1929
1930/// Exact piecewise-linear cell selected by the device policy forward pass.
1931/// The separate retained masks carry the categorical support and active set.
1932#[repr(C)]
1933#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1934struct SemanticPolicyPwlCell {
1935    abi: u64,
1936    ordinal: u64,
1937    cardinality: u64,
1938    legal_count: u64,
1939    active_count: u64,
1940    selected_rank: u64,
1941    maximum_bits: u64,
1942    singleton: u64,
1943    g: [u64; 3],
1944    active_sum: [u64; 3],
1945    selected_probability: [u64; 3],
1946    probability_denominator: [u64; 3],
1947}
1948
1949/// Producer-owned selected-score differential operator retained by the forward
1950/// pass. Together with the exact active set it determines the categorical VJP.
1951#[repr(C)]
1952#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1953struct SemanticPolicySelectedScoreVjp {
1954    abi: u64,
1955    ordinal: u64,
1956    choice: u64,
1957    active_count: u64,
1958    selected_active: u64,
1959    singleton: u64,
1960    probability_numerator: [u64; 3],
1961    probability_denominator: [u64; 3],
1962}
1963
1964/// Device-sealed receipt for the complete action batch. The root is SHA-256 of
1965/// these exact bytes and therefore cannot be substituted by a task identity or
1966/// a digest of component receipts alone.
1967#[repr(C)]
1968#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1969struct SemanticActionBatchReceipt {
1970    abi: u64,
1971    proposal: u64,
1972    stream_serial: u64,
1973    family_id: u64,
1974    action_law_generation: u64,
1975    model_generation: u64,
1976    actor_eligible: u64,
1977    component_count: u64,
1978    candidate_count: u64,
1979    winner: u64,
1980    total_return_bits: u64,
1981    base_word: u64,
1982    next_word: u64,
1983    rng_base: u64,
1984    rng_span: u64,
1985    rng_successor: u64,
1986    catalogue_digest: Identity256,
1987    component_receipts_digest: Identity256,
1988    semantic_receipts_digest: Identity256,
1989    candidate_roots: [Identity256; 3],
1990    base_logical_digest: Identity256,
1991    execution_work: ExecutionWork,
1992}
1993
1994#[repr(C)]
1995#[derive(Clone, Copy)]
1996struct DeviceState {
1997    model_generation: u32,
1998    family_id: u32,
1999    stream_serial: u64,
2000    proposal: u64,
2001    next_proposal: u64,
2002    blocks: u64,
2003    status: u64,
2004    catalogue_generation: u64,
2005    catalogue_digest: Identity256,
2006    binding_digest: Identity256,
2007    semantic_receipts: [[u64; 42]; 7],
2008    work: [SemanticTransitionWork; 2],
2009    importance_weight: f64,
2010    retired_roots_mask: u64,
2011    cleanup_receipts: [[u64; 42]; 3],
2012    task_evaluation: DeviceTaskEvaluation,
2013    actor_eligible: u64,
2014    execution_work: ExecutionWork,
2015    action_batch: SemanticActionBatchReceipt,
2016    action_batch_root: Identity256,
2017}
2018
2019impl Default for DeviceState {
2020    fn default() -> Self {
2021        // SAFETY: the scalar ABI admits every bit pattern; zero initializes all
2022        // integers and the floating-point importance weight.
2023        unsafe { std::mem::zeroed() }
2024    }
2025}
2026
2027// SAFETY: C layout, integer and FP64 fields; all bit patterns are valid.
2028unsafe impl DeviceRepr for DeviceState {}
2029unsafe impl DeviceRepr for SemanticPolicyPwlCell {}
2030unsafe impl DeviceRepr for SemanticPolicySelectedScoreVjp {}
2031unsafe impl DeviceRepr for SemanticActionBatchReceipt {}
2032
2033const _: () = assert!(size_of::<SemanticPolicyPwlCell>() == 160);
2034const _: () = assert!(size_of::<SemanticPolicySelectedScoreVjp>() == 96);
2035const _: () = assert!(size_of::<SemanticActionBatchReceipt>() == 504);
2036
2037/// Original active-ring source slot. Kind and provenance are independent: a
2038/// filled model-input row is not an assertion that the token was observed.
2039#[repr(C)]
2040#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2041pub struct SemanticTextSlot {
2042    pub token: u64,
2043    pub logical_position: u64,
2044    /// Padding = 0, filled = 1, mask = 2. Active validity is derived from kind.
2045    pub kind: u64,
2046    /// Absent = 0, source = 1, generated = 2; only filled rows have a subtype.
2047    pub provenance: u64,
2048    pub valid: u64,
2049    pub committed: u64,
2050    pub recomputed: u64,
2051    /// Row in the retained full source-provenance table, not an authority bit.
2052    pub provenance_record: u64,
2053}
2054
2055type SourceSlot = SemanticTextSlot;
2056
2057// SAFETY: C layout containing only u64 values; all bit patterns are valid.
2058unsafe impl DeviceRepr for SourceSlot {}
2059
2060/// Semantic role of a retained state range. Indices name actual layers, tensors,
2061/// or records inside the cold-bound role roster, never arbitrary device pointers.
2062#[repr(u64)]
2063#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
2064pub enum SemanticStateRole {
2065    PrefixSource = 1,
2066    TokenProvenanceRecords = 2,
2067    PrefixIdentity = 3,
2068    AttentionKeys = 4,
2069    AttentionValues = 5,
2070    ConvolutionState = 6,
2071    RecurrentState = 7,
2072    ValueRunningMax = 8,
2073    ValueDenominator = 9,
2074    ValueNumerator = 10,
2075    EditRunningMax = 11,
2076    EditDenominator = 12,
2077    EditNumerator = 13,
2078    CompletionCoverage = 14,
2079    RawFeedback = 15,
2080    FeedbackStatements = 16,
2081    FeedbackSupportProvenance = 17,
2082    SlowWeights = 18,
2083    FastAdapters = 19,
2084    SymbolicHeads = 20,
2085    OptimizerState = 21,
2086    LossScaler = 22,
2087    TrainingSchedule = 23,
2088    Gradients = 24,
2089    GradientAccumulation = 25,
2090    OtherRng = 26,
2091    ReplayEntries = 27,
2092    ReplayPayload = 28,
2093    TrainingView = 29,
2094    IntentEntries = 30,
2095    IntentPayload = 31,
2096    Acknowledgements = 32,
2097    AttemptReceipt = 33,
2098    GoalState = 34,
2099    WorldLineage = 35,
2100    EditJournal = 36,
2101    Environment = 37,
2102    AuthorityEnvelope = 38,
2103    AuthorityDecisions = 39,
2104    CheckpointLineage = 40,
2105    SchemaContract = 41,
2106    TokenizerContract = 42,
2107    RuntimeContract = 43,
2108    ModelContract = 44,
2109    TopologyContract = 45,
2110    PositionTable = 46,
2111    ActionCatalogue = 47,
2112    ActionCodebooks = 48,
2113    ProofRecords = 49,
2114    LearningCopyReset = 50,
2115    ActiveAttentionKeys = 51,
2116    ActiveAttentionValues = 52,
2117    ActiveConvolution = 53,
2118    ActiveRecurrent = 54,
2119    TensorLayout = 55,
2120}
2121
2122impl SemanticStateRole {
2123    pub fn from_code(code: u64) -> Option<Self> {
2124        const ROLES: [SemanticStateRole; 55] = [
2125            SemanticStateRole::PrefixSource,
2126            SemanticStateRole::TokenProvenanceRecords,
2127            SemanticStateRole::PrefixIdentity,
2128            SemanticStateRole::AttentionKeys,
2129            SemanticStateRole::AttentionValues,
2130            SemanticStateRole::ConvolutionState,
2131            SemanticStateRole::RecurrentState,
2132            SemanticStateRole::ValueRunningMax,
2133            SemanticStateRole::ValueDenominator,
2134            SemanticStateRole::ValueNumerator,
2135            SemanticStateRole::EditRunningMax,
2136            SemanticStateRole::EditDenominator,
2137            SemanticStateRole::EditNumerator,
2138            SemanticStateRole::CompletionCoverage,
2139            SemanticStateRole::RawFeedback,
2140            SemanticStateRole::FeedbackStatements,
2141            SemanticStateRole::FeedbackSupportProvenance,
2142            SemanticStateRole::SlowWeights,
2143            SemanticStateRole::FastAdapters,
2144            SemanticStateRole::SymbolicHeads,
2145            SemanticStateRole::OptimizerState,
2146            SemanticStateRole::LossScaler,
2147            SemanticStateRole::TrainingSchedule,
2148            SemanticStateRole::Gradients,
2149            SemanticStateRole::GradientAccumulation,
2150            SemanticStateRole::OtherRng,
2151            SemanticStateRole::ReplayEntries,
2152            SemanticStateRole::ReplayPayload,
2153            SemanticStateRole::TrainingView,
2154            SemanticStateRole::IntentEntries,
2155            SemanticStateRole::IntentPayload,
2156            SemanticStateRole::Acknowledgements,
2157            SemanticStateRole::AttemptReceipt,
2158            SemanticStateRole::GoalState,
2159            SemanticStateRole::WorldLineage,
2160            SemanticStateRole::EditJournal,
2161            SemanticStateRole::Environment,
2162            SemanticStateRole::AuthorityEnvelope,
2163            SemanticStateRole::AuthorityDecisions,
2164            SemanticStateRole::CheckpointLineage,
2165            SemanticStateRole::SchemaContract,
2166            SemanticStateRole::TokenizerContract,
2167            SemanticStateRole::RuntimeContract,
2168            SemanticStateRole::ModelContract,
2169            SemanticStateRole::TopologyContract,
2170            SemanticStateRole::PositionTable,
2171            SemanticStateRole::ActionCatalogue,
2172            SemanticStateRole::ActionCodebooks,
2173            SemanticStateRole::ProofRecords,
2174            SemanticStateRole::LearningCopyReset,
2175            SemanticStateRole::ActiveAttentionKeys,
2176            SemanticStateRole::ActiveAttentionValues,
2177            SemanticStateRole::ActiveConvolution,
2178            SemanticStateRole::ActiveRecurrent,
2179            SemanticStateRole::TensorLayout,
2180        ];
2181        let index = usize::try_from(code.checked_sub(1)?).ok()?;
2182        ROLES.get(index).copied()
2183    }
2184}
2185
2186/// One actual canonical control record or queue payload retained by a parent.
2187/// Mutable queue capacity is explicit; bytes contain the real encoded header
2188/// and entries, including an empty queue's header rather than an invented state.
2189pub struct SemanticStateRecord {
2190    pub role: SemanticStateRole,
2191    pub index: u64,
2192    pub bytes: Vec<u8>,
2193    pub capacity_bytes: usize,
2194}
2195
2196/// Byte spans in the producer's one ModelContract record. The native owner
2197/// hashes the immutable schema bytes without interpreting their format, then
2198/// binds them to the actual model generation and device numerical identity.
2199/// Digest fields are raw 32 bytes; generation is an unaligned little-endian u64.
2200#[repr(C)]
2201#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2202pub struct SemanticModelContractLayout {
2203    pub schema_begin: u64,
2204    pub schema_bytes: u64,
2205    pub schema_digest_offset: u64,
2206    pub generation_offset: u64,
2207    pub numerical_digest_offset: u64,
2208    pub identity_offset: u64,
2209}
2210
2211impl SemanticModelContractLayout {
2212    fn validate(self, record_bytes: u64) -> Result<(), SemanticTransitionError> {
2213        let spans = [
2214            (self.schema_begin, self.schema_bytes),
2215            (self.schema_digest_offset, 32),
2216            (self.generation_offset, 8),
2217            (self.numerical_digest_offset, 32),
2218            (self.identity_offset, 32),
2219        ];
2220        for (index, &(begin, bytes)) in spans.iter().enumerate() {
2221            if bytes == 0
2222                || begin > record_bytes
2223                || bytes > record_bytes - begin
2224                || spans[..index]
2225                    .iter()
2226                    .any(|&(other, length)| begin < other + length && other < begin + bytes)
2227            {
2228                return Err(publication_input_error(
2229                    "model contract spans must be nonempty, disjoint and within its actual bytes",
2230                ));
2231            }
2232        }
2233        Ok(())
2234    }
2235}
2236
2237/// A genuine producer-owned model tensor and its exact cold model contract.
2238/// No numeric conversion occurs. Logical intervals describe covered positions;
2239/// non-positional weights and optimizer state use the explicit interval 0..0.
2240pub struct SemanticTensorInput {
2241    pub layout: SemanticTensorLayout,
2242    pub logical_begin: u64,
2243    pub logical_end: u64,
2244    pub tensor: DlpackManagedTensor,
2245    /// Retained native allocation origin of this actual producer, if any.
2246    /// This is not a reader grant or a tensor version-counter identity.
2247    pub native_allocation: Option<DeviceAllocationProvenance>,
2248}
2249
2250/// Retained original tensor producers for one prepared bank's autograd
2251/// delivery boundary. The binding owns the consumed DLPack records until the
2252/// Python-side delivery owner is retired; it grants no publication authority.
2253pub struct SemanticGradientDeliveryBinding {
2254    _tensors: Vec<PreparedSemanticTensor>,
2255}
2256
2257/// A producer-declared storage object within one complete backing allocation.
2258/// Storage identity is its ordinal, not an address or a tensor version counter.
2259#[derive(Clone, Debug, PartialEq, Eq)]
2260pub struct SemanticModelStorage {
2261    pub allocation: u64,
2262    pub byte_offset: u64,
2263    pub span_bytes: u64,
2264}
2265
2266/// A typed publication coordinate within a producer-declared storage object.
2267#[derive(Clone, Debug, PartialEq, Eq)]
2268pub struct SemanticModelView {
2269    pub role: u64,
2270    pub index: u64,
2271    pub storage: u64,
2272    pub byte_offset: u64,
2273}
2274
2275/// Full producer-owned backing buffers and their independent storage/view map.
2276/// Allocation inputs are contiguous U8 vectors with role zero and ordinal index.
2277/// Tensor and version-counter identities remain in the opaque model contract.
2278pub struct SemanticModelMemory {
2279    pub allocations: Vec<SemanticTensorInput>,
2280    pub storages: Vec<SemanticModelStorage>,
2281    pub views: Vec<SemanticModelView>,
2282}
2283
2284#[derive(Clone, Debug, Default, PartialEq, Eq)]
2285struct ModelMemoryGeometry {
2286    allocation_bytes: Vec<u64>,
2287    storages: Vec<SemanticModelStorage>,
2288    views: Vec<SemanticModelView>,
2289}
2290
2291impl ModelMemoryGeometry {
2292    fn location(&self, role: u64, index: u64) -> Result<(usize, usize), SemanticTransitionError> {
2293        let view = self
2294            .views
2295            .iter()
2296            .find(|view| (view.role, view.index) == (role, index))
2297            .ok_or_else(|| {
2298                publication_input_error("model tensor lacks its producer storage view")
2299            })?;
2300        let storage = usize::try_from(view.storage)
2301            .ok()
2302            .and_then(|index| self.storages.get(index))
2303            .ok_or_else(|| publication_input_error("model view names an absent storage object"))?;
2304        let allocation = usize::try_from(storage.allocation)
2305            .ok()
2306            .filter(|&index| index < self.allocation_bytes.len())
2307            .ok_or_else(|| {
2308                publication_input_error("model storage names an absent backing allocation")
2309            })?;
2310        let offset = storage
2311            .byte_offset
2312            .checked_add(view.byte_offset)
2313            .and_then(|offset| usize::try_from(offset).ok())
2314            .ok_or_else(|| publication_input_error("model storage view offset overflows"))?;
2315        Ok((allocation, offset))
2316    }
2317
2318    fn validate(
2319        &self,
2320        layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
2321    ) -> Result<(), SemanticTransitionError> {
2322        let mut allocations = BTreeSet::new();
2323        for storage in &self.storages {
2324            let capacity = usize::try_from(storage.allocation)
2325                .ok()
2326                .and_then(|index| self.allocation_bytes.get(index))
2327                .ok_or_else(|| publication_input_error("model storage allocation is absent"))?;
2328            if usize::try_from(*capacity).is_err()
2329                || storage
2330                    .byte_offset
2331                    .checked_add(storage.span_bytes)
2332                    .is_none_or(|end| end > *capacity)
2333            {
2334                return Err(publication_input_error(
2335                    "model storage exceeds its complete backing allocation",
2336                ));
2337            }
2338            allocations.insert(storage.allocation);
2339        }
2340        let mut storages = BTreeSet::new();
2341        let mut previous = None;
2342        for view in &self.views {
2343            let key = (view.role, view.index);
2344            if !matches!(view.role, 18..=25) || previous.is_some_and(|previous| previous >= key) {
2345                return Err(publication_input_error(
2346                    "model views must enumerate unique model tensor coordinates in order",
2347                ));
2348            }
2349            previous = Some(key);
2350            let layout = layouts.get(&key).ok_or_else(|| {
2351                publication_input_error("model storage view lacks its original tensor layout")
2352            })?;
2353            let (_, offset) = self.location(view.role, view.index)?;
2354            let storage = &self.storages[view.storage as usize];
2355            let span = tensor_layout_bytes(layout)? as u64;
2356            if layout.logical_axis != u64::MAX
2357                || !(offset as u64).is_multiple_of(layout.element_bytes)
2358                || view
2359                    .byte_offset
2360                    .checked_add(span)
2361                    .is_none_or(|end| end > storage.span_bytes)
2362            {
2363                return Err(publication_input_error(
2364                    "typed model view exceeds or misaligns its declared storage",
2365                ));
2366            }
2367            storages.insert(view.storage);
2368        }
2369        if allocations.len() != self.allocation_bytes.len()
2370            || storages.len() != self.storages.len()
2371            || self.views.len()
2372                != layouts
2373                    .values()
2374                    .filter(|layout| matches!(layout.role, 18..=25))
2375                    .count()
2376        {
2377            return Err(publication_input_error(
2378                "model memory map omits a tensor or contains unreachable storage",
2379            ));
2380        }
2381        Ok(())
2382    }
2383
2384    fn encode_into(&self, bytes: &mut Vec<u8>) -> Result<(), SemanticTransitionError> {
2385        for count in [
2386            self.allocation_bytes.len(),
2387            self.storages.len(),
2388            self.views.len(),
2389        ] {
2390            material_u32(
2391                bytes,
2392                u32::try_from(count).map_err(|_| SemanticTransitionError::GenerationExhausted)?,
2393            );
2394        }
2395        for &extent in &self.allocation_bytes {
2396            material_u64(bytes, extent);
2397        }
2398        for storage in &self.storages {
2399            for field in [storage.allocation, storage.byte_offset, storage.span_bytes] {
2400                material_u64(bytes, field);
2401            }
2402        }
2403        for view in &self.views {
2404            for field in [view.role, view.index, view.storage, view.byte_offset] {
2405                material_u64(bytes, field);
2406            }
2407        }
2408        Ok(())
2409    }
2410
2411    fn digest(
2412        &self,
2413        layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
2414    ) -> Result<Identity256, SemanticTransitionError> {
2415        self.validate(layouts)?;
2416        let mut bytes = b"xlog.semantic.model-memory.v1\0".to_vec();
2417        self.encode_into(&mut bytes)?;
2418        let model = layouts
2419            .values()
2420            .filter(|layout| matches!(layout.role, 18..=25));
2421        material_u64(&mut bytes, model.clone().count() as u64);
2422        for layout in model {
2423            for field in [
2424                layout.role,
2425                layout.index,
2426                layout.element_bytes,
2427                layout.scalar_type,
2428                layout.rank,
2429                layout.logical_axis,
2430            ]
2431            .into_iter()
2432            .chain(layout.dimensions)
2433            .chain(layout.strides_bytes)
2434            {
2435                material_u64(&mut bytes, field);
2436            }
2437        }
2438        Ok(Identity256::from_bytes(Sha256::digest(&bytes).into()))
2439    }
2440
2441    fn decode_from(
2442        reader: &mut SemanticMaterialReader<'_>,
2443    ) -> Result<Self, SemanticTransitionError> {
2444        let allocations = reader.count(8).map_err(SemanticTransitionError::Semantic)?;
2445        let storages = reader
2446            .count(24)
2447            .map_err(SemanticTransitionError::Semantic)?;
2448        let views = reader
2449            .count(32)
2450            .map_err(SemanticTransitionError::Semantic)?;
2451        let mut geometry = Self::default();
2452        for _ in 0..allocations {
2453            geometry
2454                .allocation_bytes
2455                .push(reader.u64().map_err(SemanticTransitionError::Semantic)?);
2456        }
2457        for _ in 0..storages {
2458            geometry.storages.push(SemanticModelStorage {
2459                allocation: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2460                byte_offset: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2461                span_bytes: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2462            });
2463        }
2464        for _ in 0..views {
2465            geometry.views.push(SemanticModelView {
2466                role: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2467                index: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2468                storage: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2469                byte_offset: reader.u64().map_err(SemanticTransitionError::Semantic)?,
2470            });
2471        }
2472        Ok(geometry)
2473    }
2474}
2475
2476fn prepare_model_memory(
2477    allocations: &[PreparedSemanticTensor],
2478    storages: Vec<SemanticModelStorage>,
2479    views: Vec<SemanticModelView>,
2480    tensors: &[PreparedSemanticTensor],
2481) -> Result<ModelMemoryGeometry, SemanticTransitionError> {
2482    let mut geometry = ModelMemoryGeometry {
2483        allocation_bytes: Vec::new(),
2484        storages,
2485        views,
2486    };
2487    for (index, allocation) in allocations.iter().enumerate() {
2488        let layout = allocation.layout;
2489        if layout.role != 0
2490            || layout.index != index as u64
2491            || layout.rank != 1
2492            || layout.scalar_type != 1
2493            || layout.element_bytes != 1
2494            || layout.logical_axis != u64::MAX
2495            || layout.strides_bytes != [1, 0, 0, 0]
2496            || allocation.logical_begin != 0
2497            || allocation.logical_end != 0
2498        {
2499            return Err(publication_input_error(
2500                "model backing producer must be its complete ordinal U8 vector",
2501            ));
2502        }
2503        let bytes = tensor_layout_bytes(&layout)? as u64;
2504        let end = allocation
2505            .data
2506            .checked_add(bytes)
2507            .ok_or(SemanticTransitionError::GenerationExhausted)?;
2508        // Validate distinct declared owners; never infer identity from addresses.
2509        for (prior, &prior_bytes) in allocations[..index].iter().zip(&geometry.allocation_bytes) {
2510            if bytes != 0
2511                && prior_bytes != 0
2512                && allocation.data < prior.data + prior_bytes
2513                && prior.data < end
2514            {
2515                return Err(publication_input_error(
2516                    "declared model backing allocations overlap",
2517                ));
2518            }
2519        }
2520        geometry.allocation_bytes.push(bytes);
2521    }
2522    let layouts = tensors
2523        .iter()
2524        .map(|tensor| ((tensor.layout.role, tensor.layout.index), tensor.layout))
2525        .collect();
2526    geometry.validate(&layouts)?;
2527    for tensor in tensors
2528        .iter()
2529        .filter(|tensor| matches!(tensor.layout.role, 18..=25))
2530    {
2531        let (allocation, offset) = geometry.location(tensor.layout.role, tensor.layout.index)?;
2532        if allocations[allocation].data.checked_add(offset as u64) != Some(tensor.data) {
2533            return Err(publication_input_error(
2534                "original tensor does not occupy its producer-declared backing view",
2535            ));
2536        }
2537    }
2538    Ok(geometry)
2539}
2540
2541/// Initial canonical parent only. A model continuation cannot be supplied here:
2542/// it is admitted after a real Acquire and a forward using that acquired parent.
2543/// PrefixIdentity is native-owned: fresh publication derives its 32 bytes from
2544/// the actual PrefixSource. Supplying a caller record for that role is an error.
2545pub struct SemanticParentBinding {
2546    pub recovered_instance: Option<Identity256>,
2547    pub source: [SemanticTextSlot; 32],
2548    pub prefix: Vec<SemanticTextSlot>,
2549    pub ring_head: u64,
2550    pub provenance_records: u64,
2551    pub prefix_capacity: u64,
2552    pub feedback_capacity: u64,
2553    pub max_position: u64,
2554    pub pad_token: u64,
2555    pub terminal_tokens: Vec<u64>,
2556    pub final_intent_payload_bytes: u64,
2557    /// Actual application effect descriptor. The native owner constructs the
2558    /// empty intent queue; callers never encode its private header or entries.
2559    pub intent_effect: Vec<u8>,
2560    pub intent_entry_capacity: u64,
2561    pub intent_payload_capacity_bytes: usize,
2562    pub acknowledgement_payload_capacity_bytes: usize,
2563    pub model_generation: u64,
2564    /// Complete versioned numerical-mode contribution from the model owner.
2565    /// The Python binding uses exact canonical ColdValue metadata, not a digest
2566    /// or repr. Native code owns the surrounding RuntimeContract record.
2567    pub model_numerical_mode: Vec<u8>,
2568    pub model_contract_layout: SemanticModelContractLayout,
2569    pub policy_generation: u64,
2570    pub neural_generation: u64,
2571    pub cache_generation: u64,
2572    pub authority_generation: u64,
2573    pub training_cursor: u64,
2574    pub training_rng: [u64; 4],
2575    pub fuel: u64,
2576    pub rng: SemanticRngBinding,
2577    pub topology_identity: Identity256,
2578    pub table_identity: Identity256,
2579    /// Every one of the 55 roles is explicit, including actual zero tensor counts.
2580    pub role_counts: [u64; 55],
2581    pub records: Vec<SemanticStateRecord>,
2582    pub tensors: Vec<SemanticTensorInput>,
2583    pub model_memory: SemanticModelMemory,
2584    /// Model-declared 51..54 capacities only; no active output exists before
2585    /// Acquire and the original forward. Initial ranges are unreachable.
2586    pub active_layouts: Vec<SemanticTensorLayout>,
2587}
2588
2589/// An observed token payload admitted by the trusted application controller.
2590/// `origin` retains the complete source/manifest/transformation record, not an
2591/// independently supplied native digest or a model-generated provenance row.
2592#[derive(Clone, Debug)]
2593pub struct SemanticObservedSource {
2594    pub identity: String,
2595    pub tokens: Vec<u64>,
2596    pub origin: Vec<u8>,
2597}
2598
2599/// A token is selected only by offset into its admitted observed payload.
2600#[derive(Clone, Debug)]
2601pub struct SemanticSourceMapping {
2602    pub source: String,
2603    pub offset: u64,
2604    pub logical_position: u64,
2605}
2606
2607/// Initial source geometry issued from the admitted observation mapping before
2608/// the model computes its prefix cache. The rows retain zero provenance indices;
2609/// parent binding constructs and verifies the private ledger after prefill.
2610#[derive(Clone)]
2611pub struct SemanticInitialSourceLayout {
2612    pub source: [SemanticTextSlot; 32],
2613    pub prefix: Vec<SemanticTextSlot>,
2614    pub prefill_tokens: Vec<u64>,
2615    pub ring_head: u64,
2616    #[cfg(feature = "semantic-policy")]
2617    prefill_mapping: Vec<SemanticSourceMapping>,
2618    provenance_bytes: Vec<u8>,
2619    provenance_capacity_bytes: usize,
2620    provenance_records: u64,
2621}
2622
2623/// One imported task's pre-parent model input. Its source and owner are fixed
2624/// before the actual model call; no second stage can be issued on this Session.
2625struct InitialPrefillStage {
2626    scope: Arc<()>,
2627    task_identity: Identity256,
2628    task_epoch: u64,
2629    model_generation: u64,
2630    layout: SemanticInitialSourceLayout,
2631    expected_tokens: TrackedCudaSlice<u64>,
2632    input: Option<PreparedSemanticTensor>,
2633    model_content: Option<TensorContentBuffers>,
2634    output_content: Option<TensorContentBuffers>,
2635    captured_content: Vec<TensorContentBuffers>,
2636    consumer_stream: Option<u64>,
2637}
2638
2639/// Content needed by the original forward after the one-use prefill stage has
2640/// joined its parent. The Session owns it until its final stream-safe release.
2641struct RetainedInitialPrefillContent {
2642    scope: Arc<()>,
2643    task_identity: Identity256,
2644    task_epoch: u64,
2645    model_generation: u64,
2646    model: TensorContentBuffers,
2647    #[cfg(feature = "semantic-policy")]
2648    output: TensorContentBuffers,
2649    #[cfg(feature = "semantic-policy")]
2650    record: InitialPrefillRecord,
2651    captured: Vec<TensorContentBuffers>,
2652}
2653
2654#[cfg(feature = "semantic-policy")]
2655#[derive(Clone)]
2656struct InitialPrefillRecord {
2657    predecessor: SemanticPublishedIdentity,
2658    semantic_root: Identity256,
2659    task_identity: Identity256,
2660    task_epoch: u64,
2661    task_content: SemanticTaskContentIdentity,
2662    model_generation: u64,
2663    tokens: Vec<u64>,
2664    mapping: Vec<SemanticSourceMapping>,
2665}
2666
2667struct CheckpointInitialPrefill {
2668    original: SemanticPublishedIdentity,
2669    content: Vec<u8>,
2670    recovery_referent: Option<Vec<u8>>,
2671}
2672
2673impl CheckpointInitialPrefill {
2674    const MAGIC: &'static [u8] = b"XLOG-CHECKPOINT-INITIAL-PREFILL\0";
2675
2676    fn encode_section(value: Option<&Self>) -> Result<Vec<u8>, SemanticTransitionError> {
2677        let mut bytes = Self::MAGIC.to_vec();
2678        material_u64(&mut bytes, 1);
2679        if let Some(value) = value {
2680            bytes.push(1);
2681            encode_publication_identity(&mut bytes, value.original);
2682            material_u64(
2683                &mut bytes,
2684                u64::try_from(value.content.len())
2685                    .map_err(|_| publication_input_error("initial prefill exceeds u64"))?,
2686            );
2687            bytes.extend_from_slice(&value.content);
2688        } else {
2689            bytes.push(0);
2690        }
2691        Ok(bytes)
2692    }
2693
2694    fn decode_section(bytes: &[u8]) -> Result<Option<Self>, SemanticTransitionError> {
2695        let mut reader = SemanticMaterialReader::new(bytes);
2696        if reader
2697            .take(Self::MAGIC.len())
2698            .map_err(SemanticTransitionError::Semantic)?
2699            != Self::MAGIC
2700            || reader.u64().map_err(SemanticTransitionError::Semantic)? != 1
2701        {
2702            return Err(publication_input_error(
2703                "checkpoint initial prefill has another domain or version",
2704            ));
2705        }
2706        let result = match reader.u8().map_err(SemanticTransitionError::Semantic)? {
2707            0 => None,
2708            1 => {
2709                let original = decode_publication_identity(&mut reader)?;
2710                let length =
2711                    usize::try_from(reader.u64().map_err(SemanticTransitionError::Semantic)?)
2712                        .map_err(|_| {
2713                            publication_input_error("checkpoint initial prefill exceeds this host")
2714                        })?;
2715                let content = reader
2716                    .take(length)
2717                    .map_err(SemanticTransitionError::Semantic)?
2718                    .to_vec();
2719                if content.is_empty() {
2720                    return Err(publication_input_error(
2721                        "checkpoint initial prefill is empty",
2722                    ));
2723                }
2724                Some(Self {
2725                    original,
2726                    content,
2727                    recovery_referent: None,
2728                })
2729            }
2730            _ => {
2731                return Err(publication_input_error(
2732                    "checkpoint initial prefill presence is invalid",
2733                ))
2734            }
2735        };
2736        reader.finish().map_err(SemanticTransitionError::Semantic)?;
2737        Ok(result)
2738    }
2739
2740    fn verify_content(
2741        &self,
2742        semantic_root: Identity256,
2743        model_generation: u64,
2744        task_identity: Identity256,
2745        task_epoch: u64,
2746        task_content: SemanticTaskContentIdentity,
2747        prefix_extent: u64,
2748    ) -> Result<(), SemanticTransitionError> {
2749        let mut reader = SemanticMaterialReader::new(&self.content);
2750        let read_identity = |reader: &mut SemanticMaterialReader<'_>| {
2751            reader
2752                .take(32)
2753                .map(|value| Identity256::from_bytes(value.try_into().unwrap()))
2754                .map_err(SemanticTransitionError::Semantic)
2755        };
2756        if read_identity(&mut reader)? != semantic_root
2757            || reader.u64().map_err(SemanticTransitionError::Semantic)? != model_generation
2758            || read_identity(&mut reader)? != task_identity
2759            || reader.u64().map_err(SemanticTransitionError::Semantic)? != task_epoch
2760            || [
2761                read_identity(&mut reader)?,
2762                read_identity(&mut reader)?,
2763                read_identity(&mut reader)?,
2764            ] != [
2765                task_content.query,
2766                task_content.theory_program,
2767                task_content.result,
2768            ]
2769        {
2770            return Err(publication_input_error(
2771                "checkpoint initial prefill differs from its native task or parent",
2772            ));
2773        }
2774        let count = reader.u64().map_err(SemanticTransitionError::Semantic)?;
2775        if count == 0 || count != prefix_extent {
2776            return Err(publication_input_error(
2777                "checkpoint initial prefill token extent differs",
2778            ));
2779        }
2780        for _ in 0..count {
2781            reader.u64().map_err(SemanticTransitionError::Semantic)?;
2782        }
2783        if reader.u64().map_err(SemanticTransitionError::Semantic)? != count {
2784            return Err(publication_input_error(
2785                "checkpoint initial prefill mapping extent differs",
2786            ));
2787        }
2788        for position in 0..count {
2789            let length = usize::try_from(reader.u64().map_err(SemanticTransitionError::Semantic)?)
2790                .map_err(|_| {
2791                    publication_input_error("initial prefill source name exceeds this host")
2792                })?;
2793            let source = reader
2794                .take(length)
2795                .map_err(SemanticTransitionError::Semantic)?;
2796            if source.is_empty() || std::str::from_utf8(source).is_err() {
2797                return Err(publication_input_error(
2798                    "checkpoint initial prefill source name is invalid",
2799                ));
2800            }
2801            reader.u64().map_err(SemanticTransitionError::Semantic)?;
2802            if reader.u64().map_err(SemanticTransitionError::Semantic)? != position {
2803                return Err(publication_input_error(
2804                    "checkpoint initial prefill logical positions differ",
2805                ));
2806            }
2807        }
2808        for model in [true, false] {
2809            let count = reader.u64().map_err(SemanticTransitionError::Semantic)?;
2810            if count == 0 {
2811                return Err(publication_input_error(
2812                    "checkpoint initial prefill has an empty seal group",
2813                ));
2814            }
2815            for _ in 0..count {
2816                let role = reader.u64().map_err(SemanticTransitionError::Semantic)?;
2817                if if model {
2818                    !matches!(role, 0 | 18..=25)
2819                } else {
2820                    !matches!(role, 4..=13)
2821                } {
2822                    return Err(publication_input_error(
2823                        "checkpoint initial prefill seal role is invalid",
2824                    ));
2825                }
2826                reader.u64().map_err(SemanticTransitionError::Semantic)?;
2827                reader.take(32).map_err(SemanticTransitionError::Semantic)?;
2828            }
2829        }
2830        reader.finish().map_err(SemanticTransitionError::Semantic)?;
2831        Ok(())
2832    }
2833
2834    fn verify_recorded_content(
2835        &self,
2836        task_identity: Identity256,
2837        task_epoch: u64,
2838        task_content: SemanticTaskContentIdentity,
2839    ) -> Result<(), SemanticTransitionError> {
2840        let mut reader = SemanticMaterialReader::new(&self.content);
2841        let semantic_root = Identity256::from_bytes(
2842            reader
2843                .take(32)
2844                .map_err(SemanticTransitionError::Semantic)?
2845                .try_into()
2846                .unwrap(),
2847        );
2848        let model_generation = reader.u64().map_err(SemanticTransitionError::Semantic)?;
2849        reader
2850            .take(32 + 8 + 3 * 32)
2851            .map_err(SemanticTransitionError::Semantic)?;
2852        let prefix_extent = reader.u64().map_err(SemanticTransitionError::Semantic)?;
2853        self.verify_content(
2854            semantic_root,
2855            model_generation,
2856            task_identity,
2857            task_epoch,
2858            task_content,
2859            prefix_extent,
2860        )
2861    }
2862}
2863
2864/// Opaque handle to the single imported-task prefill stage. This is not a
2865/// model-forward receipt; the actual input and outputs must be joined before
2866/// the parent can be published.
2867#[derive(Clone)]
2868pub struct SemanticInitialPrefillLease {
2869    issuer: Arc<()>,
2870    scope: Arc<()>,
2871}
2872
2873#[derive(Clone, Copy)]
2874enum InitialPrefillContentSlot {
2875    Model,
2876    Captured(usize),
2877}
2878
2879#[derive(Clone, Copy)]
2880enum InitialPrefillCaptureKind {
2881    Model,
2882    Outputs,
2883    Captured,
2884}
2885
2886/// Exact content captured by one imported task's original model prefill.
2887/// This handle never creates a new baseline during verification.
2888#[derive(Clone)]
2889pub struct SemanticInitialPrefillContentWitness {
2890    issuer: Arc<()>,
2891    scope: Arc<()>,
2892    task_identity: Identity256,
2893    task_epoch: u64,
2894    model_generation: u64,
2895    slot: InitialPrefillContentSlot,
2896}
2897
2898impl SemanticInitialPrefillContentWitness {
2899    fn matches(
2900        &self,
2901        issuer: &Arc<()>,
2902        scope: &Arc<()>,
2903        task_identity: Identity256,
2904        task_epoch: u64,
2905        model_generation: u64,
2906        captured_count: usize,
2907    ) -> bool {
2908        Arc::ptr_eq(&self.issuer, issuer)
2909            && Arc::ptr_eq(&self.scope, scope)
2910            && self.task_identity == task_identity
2911            && self.task_epoch == task_epoch
2912            && self.model_generation == model_generation
2913            && match self.slot {
2914                InitialPrefillContentSlot::Model => true,
2915                InitialPrefillContentSlot::Captured(index) => index < captured_count,
2916            }
2917    }
2918}
2919
2920fn validate_initial_prefill_input_layout(
2921    layout: &SemanticTensorLayout,
2922    token_count: u64,
2923) -> Result<(), SemanticTransitionError> {
2924    let row_bytes = token_count
2925        .checked_mul(size_of::<i64>() as u64)
2926        .filter(|_| token_count != 0)
2927        .ok_or_else(|| {
2928            publication_input_error("initial prefill requires nonempty admitted prefix tokens")
2929        })?;
2930    if *layout
2931        != (SemanticTensorLayout {
2932            role: 0,
2933            index: 0,
2934            element_bytes: size_of::<i64>() as u64,
2935            scalar_type: 7,
2936            rank: 2,
2937            logical_axis: 1,
2938            dimensions: [1, token_count, 0, 0],
2939            strides_bytes: [row_bytes, size_of::<i64>() as u64, 0, 0],
2940        })
2941    {
2942        return Err(publication_input_error(
2943            "initial prefill input must be the exact contiguous I64 model token tensor [1,prefix]",
2944        ));
2945    }
2946    Ok(())
2947}
2948
2949fn same_initial_source_rows(expected: &[SemanticTextSlot], actual: &[SemanticTextSlot]) -> bool {
2950    expected.len() == actual.len()
2951        && expected.iter().zip(actual).all(|(expected, actual)| {
2952            SemanticTextSlot {
2953                provenance_record: 0,
2954                ..*expected
2955            } == SemanticTextSlot {
2956                provenance_record: 0,
2957                ..*actual
2958            }
2959        })
2960}
2961
2962/// Place the exact admitted tokens into an ordered computed prefix and original
2963/// 32-row ring. No model cache or publication is claimed by this cold plan.
2964/// The existing parent bind rechecks the same source mapping and cache geometry.
2965#[expect(
2966    clippy::too_many_arguments,
2967    reason = "cold planning checks the admitted source and complete parent text geometry together"
2968)]
2969pub fn initial_source_layout(
2970    sources: &[SemanticObservedSource],
2971    mapping: &[SemanticSourceMapping],
2972    authority: &[u8],
2973    generation: u64,
2974    provenance_capacity_records: u64,
2975    prefix_capacity: u64,
2976    feedback_capacity: u64,
2977    max_position: u64,
2978    pad_token: u64,
2979) -> Result<SemanticInitialSourceLayout, SemanticTransitionError> {
2980    let invalid = publication_input_error;
2981    if pad_token >= TEXT_CARDINALITY as u64 {
2982        return Err(invalid(
2983            "initial source padding token is outside the text vocabulary",
2984        ));
2985    }
2986    let last_position = mapping.iter().map(|entry| entry.logical_position).max();
2987    let source_extent = last_position
2988        .map(|last| {
2989            last.checked_add(1)
2990                .ok_or_else(|| invalid("initial source position overflows"))
2991        })
2992        .transpose()?
2993        .unwrap_or(0);
2994    let prefix_extent = source_extent.saturating_sub(32);
2995    if prefix_extent > prefix_capacity || prefix_extent > mapping.len() as u64 {
2996        return Err(invalid(
2997            "admitted source exceeds its complete prefix capacity",
2998        ));
2999    }
3000    let admitted = sources
3001        .iter()
3002        .map(|source| (source.identity.as_str(), source))
3003        .collect::<BTreeMap<_, _>>();
3004    let mut tokens = BTreeMap::new();
3005    for entry in mapping {
3006        let source = admitted
3007            .get(entry.source.as_str())
3008            .ok_or_else(|| invalid("source mapping names an unadmitted payload"))?;
3009        let offset =
3010            usize::try_from(entry.offset).map_err(|_| invalid("source token offset overflows"))?;
3011        let token = *source
3012            .tokens
3013            .get(offset)
3014            .ok_or_else(|| invalid("source mapping token offset is out of range"))?;
3015        if tokens.insert(entry.logical_position, token).is_some() {
3016            return Err(invalid("source mapping repeats a logical position"));
3017        }
3018    }
3019    let mut source = [SemanticTextSlot {
3020        token: pad_token,
3021        ..SemanticTextSlot::default()
3022    }; 32];
3023    let mut prefix = Vec::with_capacity(prefix_extent as usize);
3024    let mut prefill_tokens = Vec::with_capacity(prefix_extent as usize);
3025    for position in 0..prefix_extent {
3026        let token = *tokens
3027            .get(&position)
3028            .ok_or_else(|| invalid("computed prefix lacks an admitted source token"))?;
3029        prefix.push(SemanticTextSlot {
3030            token,
3031            logical_position: position,
3032            kind: 1,
3033            provenance: 1,
3034            valid: 1,
3035            committed: 1,
3036            ..SemanticTextSlot::default()
3037        });
3038        prefill_tokens.push(token);
3039    }
3040    for (&position, &token) in tokens.range(prefix_extent..) {
3041        let index = usize::try_from(position - prefix_extent)
3042            .map_err(|_| invalid("initial source ring offset overflows"))?;
3043        if index >= source.len() {
3044            return Err(invalid("admitted source exceeds its 32-row active ring"));
3045        }
3046        source[index] = SemanticTextSlot {
3047            token,
3048            logical_position: position,
3049            kind: 1,
3050            provenance: 1,
3051            valid: 1,
3052            ..SemanticTextSlot::default()
3053        };
3054    }
3055    let (_, _, provenance) = initial_source_ledger(
3056        source,
3057        prefix.clone(),
3058        sources,
3059        mapping,
3060        authority,
3061        generation,
3062        provenance_capacity_records,
3063    )?;
3064    #[cfg(feature = "semantic-policy")]
3065    let mut prefill_mapping = mapping
3066        .iter()
3067        .filter(|entry| entry.logical_position < prefix_extent)
3068        .cloned()
3069        .collect::<Vec<_>>();
3070    #[cfg(feature = "semantic-policy")]
3071    prefill_mapping.sort_by_key(|entry| entry.logical_position);
3072    let ring_head = (source_extent - prefix_extent) % 32;
3073    validate_text_parent(
3074        &source,
3075        prefix_extent,
3076        prefix_capacity,
3077        feedback_capacity,
3078        max_position,
3079        ring_head,
3080        mapping.len() as u64,
3081    )?;
3082    Ok(SemanticInitialSourceLayout {
3083        source,
3084        prefix,
3085        prefill_tokens,
3086        ring_head,
3087        #[cfg(feature = "semantic-policy")]
3088        prefill_mapping,
3089        provenance_bytes: provenance.bytes,
3090        provenance_capacity_bytes: provenance.capacity_bytes,
3091        provenance_records: mapping.len() as u64,
3092    })
3093}
3094
3095impl SemanticParentBinding {
3096    /// Construct the private initial SOURCE ledger from admitted observations.
3097    /// The complete authority record is retained in the parent by the same
3098    /// controller. Fresh GENERATED rows must instead enter through restoration.
3099    pub fn bind_initial_sources(
3100        &mut self,
3101        sources: &[SemanticObservedSource],
3102        mapping: &[SemanticSourceMapping],
3103        authority: &[u8],
3104        capacity_records: u64,
3105    ) -> Result<(), SemanticTransitionError> {
3106        if self.recovered_instance.is_some()
3107            || self.provenance_records != 0
3108            || self
3109                .records
3110                .iter()
3111                .any(|record| record.role == SemanticStateRole::TokenProvenanceRecords)
3112            || self.role_counts[SemanticStateRole::TokenProvenanceRecords as usize - 1] != 1
3113        {
3114            return Err(publication_input_error(
3115                "fresh source provenance must be constructed by the controller",
3116            ));
3117        }
3118        let (source, prefix, record) = initial_source_ledger(
3119            self.source,
3120            self.prefix.clone(),
3121            sources,
3122            mapping,
3123            authority,
3124            self.authority_generation,
3125            capacity_records,
3126        )?;
3127        self.source = source;
3128        self.prefix = prefix;
3129        self.provenance_records = mapping.len() as u64;
3130        self.records.push(record);
3131        Ok(())
3132    }
3133}
3134
3135fn initial_source_ledger(
3136    mut ring: [SemanticTextSlot; 32],
3137    mut prefix: Vec<SemanticTextSlot>,
3138    sources: &[SemanticObservedSource],
3139    mapping: &[SemanticSourceMapping],
3140    authority: &[u8],
3141    generation: u64,
3142    capacity: u64,
3143) -> Result<
3144    (
3145        [SemanticTextSlot; 32],
3146        Vec<SemanticTextSlot>,
3147        SemanticStateRecord,
3148    ),
3149    SemanticTransitionError,
3150> {
3151    let invalid = publication_input_error;
3152    let source_count = sources.len();
3153    let sources = sources
3154        .iter()
3155        .map(|source| (source.identity.as_str(), source))
3156        .collect::<BTreeMap<_, _>>();
3157    if sources.len() != source_count
3158        || sources.values().any(|source| {
3159            source.identity.is_empty()
3160                || source.origin.is_empty()
3161                || source.tokens.is_empty()
3162                || source
3163                    .tokens
3164                    .iter()
3165                    .any(|&token| token >= TEXT_CARDINALITY as u64 || token == MASK_TOKEN as u64)
3166        })
3167    {
3168        return Err(invalid(
3169            "observed sources require unique identities and complete valid token payloads",
3170        ));
3171    }
3172    if authority.is_empty()
3173        || generation == 0
3174        || capacity
3175            < (mapping.len() as u64)
3176                .checked_add(32)
3177                .ok_or_else(|| invalid("source ledger capacity overflows"))?
3178    {
3179        return Err(invalid(
3180            "source ledger requires complete authority and append capacity",
3181        ));
3182    }
3183    let mut positions = BTreeMap::new();
3184    for entry in mapping {
3185        let source = sources
3186            .get(entry.source.as_str())
3187            .ok_or_else(|| invalid("source mapping names an unadmitted payload"))?;
3188        let offset =
3189            usize::try_from(entry.offset).map_err(|_| invalid("source token offset overflows"))?;
3190        if offset >= source.tokens.len()
3191            || positions.insert(entry.logical_position, entry).is_some()
3192        {
3193            return Err(invalid(
3194                "source mapping has invalid payload, offset, or duplicate logical position",
3195            ));
3196        }
3197    }
3198    let authority_digest = Identity256::from_bytes(Sha256::digest(authority).into());
3199    let mut bytes = Vec::with_capacity(
3200        mapping
3201            .len()
3202            .checked_mul(size_of::<TokenProvenance>())
3203            .ok_or_else(|| invalid("source ledger extent overflows"))?,
3204    );
3205    let mut seen = BTreeSet::new();
3206    for (physical_slot, slot) in prefix.iter_mut().map(|slot| (u64::MAX, slot)).chain(
3207        ring.iter_mut()
3208            .enumerate()
3209            .map(|(index, slot)| (index as u64, slot)),
3210    ) {
3211        if slot.kind != 1 {
3212            if slot.kind > 2 || slot.provenance != 0 || slot.provenance_record != 0 {
3213                return Err(invalid(
3214                    "MASK or PAD cannot carry initial SOURCE provenance",
3215                ));
3216            }
3217            continue;
3218        }
3219        let entry = positions.get(&slot.logical_position).ok_or_else(|| {
3220            invalid("every initial FILLED position requires its exact source mapping")
3221        })?;
3222        let source = sources[entry.source.as_str()];
3223        let token = source.tokens[entry.offset as usize];
3224        if slot.provenance != 1
3225            || slot.provenance_record != 0
3226            || slot.token != token
3227            || !seen.insert(slot.logical_position)
3228        {
3229            return Err(invalid(
3230                "initial FILLED token differs from its admitted SOURCE payload or position",
3231            ));
3232        }
3233        slot.provenance_record = (bytes.len() / size_of::<TokenProvenance>()) as u64;
3234        let mut record = TokenProvenance {
3235            source_slot: physical_slot,
3236            logical_position: entry.logical_position,
3237            token,
3238            // For observed inputs ordinal is the exact payload token offset;
3239            // no action receipt is invented before a real generated transition.
3240            ordinal: entry.offset,
3241            authority_generation: generation,
3242            origin_logical_digest: Identity256::from_bytes(Sha256::digest(&source.origin).into()),
3243            authority_closure_digest: authority_digest,
3244            ..TokenProvenance::default()
3245        };
3246        // SAFETY: TokenProvenance is a padding-free repr(C) integral record.
3247        // Every field was initialized; the private record digest starts at zero.
3248        let logical = unsafe {
3249            std::slice::from_raw_parts(
3250                (&record as *const TokenProvenance).cast::<u8>(),
3251                size_of::<TokenProvenance>(),
3252            )
3253        };
3254        record.record_digest = Identity256::from_bytes(Sha256::digest(logical).into());
3255        // SAFETY: the same padding-free initialized record is copied, not borrowed.
3256        bytes.extend_from_slice(unsafe {
3257            std::slice::from_raw_parts(
3258                (&record as *const TokenProvenance).cast::<u8>(),
3259                size_of::<TokenProvenance>(),
3260            )
3261        });
3262    }
3263    if seen.len() != mapping.len() {
3264        return Err(invalid(
3265            "source mapping includes a MASK, PAD, or absent logical position",
3266        ));
3267    }
3268    let capacity_bytes = usize::try_from(capacity)
3269        .ok()
3270        .and_then(|count| count.checked_mul(size_of::<TokenProvenance>()))
3271        .ok_or_else(|| invalid("source ledger capacity overflows"))?;
3272    Ok((
3273        ring,
3274        prefix,
3275        SemanticStateRecord {
3276            role: SemanticStateRole::TokenProvenanceRecords,
3277            index: 0,
3278            bytes,
3279            capacity_bytes,
3280        },
3281    ))
3282}
3283
3284/// Original model outputs for one acquired parent. The Session supplies their
3285/// instance, publication word, task and generation binding from its real lease.
3286pub struct SemanticContinuationInput {
3287    pub tensors: Vec<SemanticTensorInput>,
3288    /// Exact fresh controller snapshot used to authorize this invocation.
3289    /// This is not an independently issuable model input or authority claim.
3290    pub authority_decisions: Vec<u8>,
3291    /// Original U64[32,2] mapping and U64[1] count, never host-compacted.
3292    pub text_rows: DlpackManagedTensor,
3293    pub text_row_count: DlpackManagedTensor,
3294    /// Original Bool8[32], indexed by acquired source slot.
3295    pub selected_text: DlpackManagedTensor,
3296    /// Original U64[A,4] physical mapping and U64[1] count; holes remain holes.
3297    pub active_rows: DlpackManagedTensor,
3298    pub active_row_count: DlpackManagedTensor,
3299    /// Original Bool8[1] ordinary numerical admission predicate.
3300    pub numerical_admissibility: DlpackManagedTensor,
3301    /// Original pre-draw FP64[N,2,3] block bounds. Only proposals draw.
3302    pub numerical_blocks: Option<DlpackManagedTensor>,
3303    /// Original sealed model-contract schema digest for this block roster.
3304    pub model_schema_digest: Option<Identity256>,
3305    /// Original sealed model-contract identity for this generation.
3306    pub model_identity: Option<Identity256>,
3307}
3308
3309fn continuation_service_layouts(
3310    first_index: usize,
3311    capacity: u64,
3312    physical_blocks: Option<usize>,
3313) -> Result<Vec<SemanticTensorLayout>, SemanticTransitionError> {
3314    let first_index = u64::try_from(first_index)
3315        .ok()
3316        .filter(|index| {
3317            index
3318                .checked_add(if physical_blocks.is_some() { 6 } else { 5 })
3319                .is_some()
3320        })
3321        .ok_or_else(|| publication_input_error("continuation service roster overflow"))?;
3322    if capacity < 34 {
3323        return Err(publication_input_error(
3324            "continuation active capacity lacks its source and feedback slots",
3325        ));
3326    }
3327    let layout = |offset, scalar_type, element_bytes, rank, dimensions| {
3328        canonical_tensor_layout(SemanticTensorLayout {
3329            role: 0,
3330            index: first_index + offset,
3331            scalar_type,
3332            element_bytes,
3333            rank,
3334            dimensions,
3335            logical_axis: u64::MAX,
3336            strides_bytes: [0; 4],
3337        })
3338    };
3339    let mut layouts = vec![
3340        layout(0, 3, 8, 2, [32, 2, 0, 0])?,
3341        layout(1, 3, 8, 1, [1, 0, 0, 0])?,
3342        layout(2, 8, 1, 1, [32, 0, 0, 0])?,
3343        layout(3, 3, 8, 2, [capacity, 4, 0, 0])?,
3344        layout(4, 3, 8, 1, [1, 0, 0, 0])?,
3345        layout(5, 8, 1, 1, [1, 0, 0, 0])?,
3346    ];
3347    if let Some(blocks) = physical_blocks {
3348        layouts.push(layout(6, 9, 8, 3, [blocks as u64, 2, 3, 0])?);
3349    }
3350    Ok(layouts)
3351}
3352
3353/// Decode the retained versioned schema from the original ModelContract slice.
3354fn retained_model_schema(
3355    record: &[u8],
3356    layout: SemanticModelContractLayout,
3357) -> Result<Option<serde_json::Value>, SemanticTransitionError> {
3358    layout.validate(record.len() as u64)?;
3359    let begin = layout.schema_begin as usize;
3360    let end = begin + layout.schema_bytes as usize;
3361    let Ok(schema) = serde_json::from_slice::<serde_json::Value>(&record[begin..end]) else {
3362        return Ok(None);
3363    };
3364    if schema
3365        .get("counter_encoding")
3366        .and_then(serde_json::Value::as_str)
3367        != Some("u32-hex8")
3368    {
3369        return Ok(None);
3370    }
3371    Ok(Some(schema))
3372}
3373
3374/// Derive unique physical parameter owners from that same authenticated schema.
3375/// Other schema formats cannot claim this block-bound admission contract.
3376fn model_physical_parameter_roster(
3377    record: &[u8],
3378    layout: SemanticModelContractLayout,
3379) -> Result<Option<Vec<String>>, SemanticTransitionError> {
3380    let Some(schema) = retained_model_schema(record, layout)? else {
3381        return Ok(None);
3382    };
3383    let model = schema
3384        .get("model")
3385        .ok_or_else(|| publication_input_error("versioned model schema lacks its model owner"))?;
3386    let physical = model
3387        .get("physical")
3388        .and_then(serde_json::Value::as_object)
3389        .ok_or_else(|| publication_input_error("model schema lacks its physical owner roster"))?;
3390    let mut names = Vec::new();
3391    for (name, entry) in physical {
3392        match entry.get("kind").and_then(serde_json::Value::as_str) {
3393            Some("parameter") => names.push(name.clone()),
3394            Some("buffer") => {}
3395            _ => {
3396                return Err(publication_input_error(
3397                    "model physical roster has an unknown owner kind",
3398                ))
3399            }
3400        }
3401    }
3402    if names.is_empty() {
3403        return Err(publication_input_error(
3404            "model physical roster has no parameter owners",
3405        ));
3406    }
3407    names.sort_unstable();
3408    Ok(Some(names))
3409}
3410
3411/// Identity of one packed active-cache row in its original forward. Kinds are
3412/// FILLED=1, MASK=2 and FEEDBACK=3; physical_row is not the packed coordinate.
3413#[repr(C)]
3414#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
3415pub struct SemanticActiveRow {
3416    pub physical_row: u64,
3417    pub source_slot: u64,
3418    pub logical_position: u64,
3419    pub kind: u64,
3420}
3421
3422/// Acquired bank-local active-cache state. A computed empty result has no rows
3423/// but is distinct from the initial parent which has never consumed a forward.
3424#[derive(Clone, Debug, PartialEq, Eq)]
3425pub struct SemanticActiveRows {
3426    pub computed: bool,
3427    pub rows: Vec<SemanticActiveRow>,
3428}
3429
3430/// One original compact model row; source_slot is the acquired ring identity,
3431/// never the packed model coordinate. The row's array index identifies logits.
3432#[repr(C)]
3433#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
3434pub struct SemanticTextRow {
3435    pub source_slot: u64,
3436    pub logical_position: u64,
3437}
3438// SAFETY: padding-free C representation containing only two initialized u64s.
3439unsafe impl DeviceRepr for SemanticTextRow {}
3440
3441#[repr(C)]
3442#[derive(Clone, Copy, Default)]
3443struct TextBinding {
3444    rows: u64,
3445    count: u64,
3446    selected: u64,
3447}
3448
3449struct TextBindingStorage {
3450    inputs: Vec<PreparedSemanticTensor>,
3451    numerical_block_snapshot: Option<Arc<TrackedCudaSlice<f64>>>,
3452    model_contract: Option<DeviceMemoryView<u8>>,
3453    physical_blocks: u64,
3454    model_schema_digest: Identity256,
3455    model_identity: Identity256,
3456    _witness: SemanticTensorContentWitness,
3457    _model_content_witness: Option<SemanticTensorContentWitness>,
3458    consumer_stream: u64,
3459    parent: TextBindingParent,
3460}
3461
3462#[expect(
3463    clippy::large_enum_variant,
3464    reason = "the published header stays inline on the latency-sensitive export path"
3465)]
3466enum TextBindingParent {
3467    Published {
3468        bank: usize,
3469        header: PublicationHeader,
3470    },
3471    Prepared(Arc<PreparedStepInputs>),
3472}
3473
3474impl TextBindingStorage {
3475    fn published_parent(&self) -> Result<(usize, PublicationHeader), SemanticTransitionError> {
3476        match &self.parent {
3477            TextBindingParent::Published { bank, header } => Ok((*bank, *header)),
3478            TextBindingParent::Prepared(_) => Err(publication_input_error(
3479                "a prepared invocation has no host-observed parent header",
3480            )),
3481        }
3482    }
3483    fn descriptor(&self) -> TextBinding {
3484        TextBinding {
3485            rows: self.inputs[0].data,
3486            count: self.inputs[1].data,
3487            selected: self.inputs[2].data,
3488        }
3489    }
3490
3491    fn record(&self, recorder: &mut LaunchRecorder) {
3492        for input in &self.inputs {
3493            if let Some(source) = &input.source {
3494                recorder.read(source);
3495            }
3496        }
3497        if let Some(snapshot) = &self.numerical_block_snapshot {
3498            recorder.read(snapshot.as_ref());
3499        }
3500        if let Some(contract) = &self.model_contract {
3501            recorder.read(contract);
3502        }
3503    }
3504
3505    fn continuation_inputs(
3506        &self,
3507        kind: SemanticTransitionKind,
3508        authority_bytes: u64,
3509        training_selection: u64,
3510        model_update: ModelUpdateContinuationInputs,
3511    ) -> ContinuationInputs {
3512        ContinuationInputs {
3513            text: self.descriptor(),
3514            active_rows: self.inputs[3].data,
3515            active_row_count: self.inputs[4].data,
3516            numerical_admissibility: self.inputs[5].data,
3517            numerical_blocks: self
3518                .numerical_block_snapshot
3519                .as_ref()
3520                .map_or(0, |snapshot| snapshot.device_ptr_value()),
3521            physical_blocks: self.physical_blocks,
3522            model_schema_digest: self.model_schema_digest,
3523            model_identity: self.model_identity,
3524            model_contract: self
3525                .model_contract
3526                .as_ref()
3527                .map_or(0, |contract| *contract.device_ptr()),
3528            model_contract_bytes: self
3529                .model_contract
3530                .as_ref()
3531                .map_or(0, |contract| contract.len() as u64),
3532            transition_kind: kind.code(),
3533            authority_bytes,
3534            training_selection,
3535            model_update_bindings: model_update.bindings,
3536            model_update_binding_count: model_update.binding_count,
3537            model_update_admissibility: model_update.admissibility,
3538            model_update_refusal: model_update.refusal,
3539            model_update_canary_results: model_update.canary_results,
3540        }
3541    }
3542}
3543
3544fn enqueue_numerical_block_snapshot(
3545    domain: &ResidentExecutionDomain,
3546    poisoned: &mut bool,
3547    original: &PreparedSemanticTensor,
3548    destination: &TrackedCudaSlice<f64>,
3549) -> Result<(), SemanticTransitionError> {
3550    let source = original
3551        .source
3552        .as_ref()
3553        .ok_or_else(|| publication_input_error("original block bounds have no device storage"))?;
3554    let bytes = destination
3555        .len()
3556        .checked_mul(size_of::<f64>())
3557        .ok_or(SemanticTransitionError::GenerationExhausted)?;
3558    if source.len() != bytes {
3559        return Err(publication_input_error(
3560            "original block bounds differ from the frozen native capacity",
3561        ));
3562    }
3563    let mut recorder = domain.new_strict_recorder();
3564    recorder.read(source);
3565    recorder.write(destination);
3566    enqueue_recorded(domain, poisoned, recorder, |enqueue| {
3567        // SAFETY: the original typed witness established the exact contiguous
3568        // FP64 span and the destination is a disjoint native-owned allocation.
3569        unsafe {
3570            sys::cuMemcpyDtoDAsync_v2(
3571                destination.device_ptr_value(),
3572                *source.device_ptr(),
3573                bytes,
3574                enqueue.stream().cu_stream(),
3575            )
3576        }
3577        .result()
3578        .map_err(|error| XlogError::Kernel(format!("block bound snapshot: {error}")))
3579    })
3580}
3581
3582/// Actual device-validated publication identity. This identifies content and
3583/// lineage; it is not a use-authority token or an externally issuable lease.
3584#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3585pub struct SemanticPublishedIdentity {
3586    pub instance: Identity256,
3587    pub word: u64,
3588    pub logical_digest: Identity256,
3589    pub state_digest: Identity256,
3590}
3591
3592/// Read-only identity projected from one fully validated original publication material.
3593#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3594pub struct SemanticCheckpointNativeProjection {
3595    pub publication: SemanticPublishedIdentity,
3596    pub semantic_root: Identity256,
3597    pub model_generation: u64,
3598}
3599
3600/// Read-only original inputs projected through the complete publication codec.
3601/// These content records are not proof of historical execution or use authority.
3602#[derive(Clone, Debug, PartialEq, Eq)]
3603pub struct SemanticPublicationInputProjection {
3604    pub publication: SemanticPublishedIdentity,
3605    pub semantic_root: Identity256,
3606    pub model_generation: u64,
3607    pub model_geometry_digest: Identity256,
3608    pub model_numerical_digest: Identity256,
3609    pub neural_generation: u64,
3610    pub cache_generation: u64,
3611    pub prefix_extent: u64,
3612    pub ring_head: u64,
3613    pub prefix_identity: Identity256,
3614    pub prefix: Vec<SemanticTextSlot>,
3615    pub source: [SemanticTextSlot; 32],
3616    pub token_provenance: Vec<SemanticTokenProvenance>,
3617    pub cache: Vec<SemanticPublicationTensorProjection>,
3618}
3619
3620/// Original cache geometry and logical bytes under the native tensor seal.
3621/// Logical bytes exclude stride gaps and unused capacity, exactly as the seal does.
3622#[derive(Clone, Debug, PartialEq, Eq)]
3623pub struct SemanticPublicationTensorProjection {
3624    pub layout: SemanticTensorLayout,
3625    pub capacity_bytes: u64,
3626    pub logical_begin: u64,
3627    pub logical_end: u64,
3628    pub identity: Identity256,
3629    pub logical_bytes: Vec<u8>,
3630}
3631
3632/// Original token origin projected from the native append-only source ledger.
3633/// A generated token retains its publication, draw and receipt coordinates;
3634/// none of these fields independently grants authority or proves publication.
3635#[derive(Clone, Debug, PartialEq, Eq)]
3636pub struct SemanticTokenProvenance {
3637    pub source_slot: u64,
3638    pub logical_position: u64,
3639    pub token: u64,
3640    pub base_word: u64,
3641    pub proposal: u64,
3642    pub ordinal: u64,
3643    pub action_receipt_digest: Identity256,
3644    pub authority_generation: u64,
3645    pub origin_logical_digest: Identity256,
3646    pub authority_closure_digest: Identity256,
3647    pub record_digest: Identity256,
3648}
3649
3650/// Model metadata projected from one acquired publication, not supplied by the
3651/// model. Content identities grant no authority independently of that reader.
3652pub struct SemanticModelContext {
3653    pub parent: SemanticPublishedIdentity,
3654    pub descriptor_digest: Identity256,
3655    /// Original storage/view geometry and device-sealed numerical state. These
3656    /// do not replace the opaque ModelContract or grant independent authority.
3657    pub numerical_state: (Identity256, Identity256),
3658    pub semantic_root: (u64, u64, u64, Identity256, [u64; 3]),
3659    /// Original prefix identity U8[32] and committed extent U64[1] device views.
3660    pub prefix: (DlpackManagedTensor, DlpackManagedTensor),
3661    /// Original ring head U64[1], not a host scalar or a source rotation.
3662    pub ring_head: DlpackManagedTensor,
3663    /// Original source slots U64[32,8], in physical slot order.
3664    pub source: DlpackManagedTensor,
3665    /// Model generation, neural bank, neural generation, cache and authority.
3666    pub generations: (u64, u64, u64, u64, u64),
3667    pub topology_identity: Identity256,
3668    pub table_identity: Identity256,
3669    /// Prefix capacity, feedback capacity and exclusive position-table bound.
3670    pub capacities: (u64, u64, u64),
3671}
3672
3673/// Direct read-only aliases of the selected resident neural bank. Each backing
3674/// allocation is exported exactly once; storages, views and layouts preserve
3675/// the producer's original alias geometry. The acquired reader remains the use
3676/// owner and therefore prevents reuse of this physical bank through final use.
3677pub struct SemanticResidentModelMemory {
3678    pub parent: SemanticPublishedIdentity,
3679    /// Model generation, neural bank and neural generation.
3680    pub generations: (u64, u64, u64),
3681    /// Original storage/view geometry and sealed numerical contents.
3682    pub numerical_state: (Identity256, Identity256),
3683    pub allocations: Vec<(DeviceAllocationProvenance, DlpackManagedTensor)>,
3684    pub storages: Vec<SemanticModelStorage>,
3685    pub views: Vec<(SemanticModelView, SemanticTensorLayout)>,
3686}
3687
3688/// Admission cost of the next operation, checked against one acquired parent.
3689#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3690pub enum SemanticTransitionKind {
3691    Proposal,
3692    Recompute,
3693    Drain,
3694    Update,
3695}
3696
3697impl SemanticTransitionKind {
3698    fn code(self) -> u64 {
3699        match self {
3700            Self::Proposal => 1,
3701            Self::Recompute => 2,
3702            Self::Drain => 3,
3703            Self::Update => 4,
3704        }
3705    }
3706}
3707
3708fn is_tensor_role(role: u64) -> bool {
3709    matches!(role, 4..=13 | 18..=25 | 51..=54)
3710}
3711
3712fn validate_publication_counts(counts: &[u64; 55]) -> Result<usize, SemanticTransitionError> {
3713    let mut total = 0u64;
3714    for (index, &count) in counts.iter().enumerate() {
3715        let role = index as u64 + 1;
3716        if (!is_tensor_role(role) && count != if role == 16 { 3 } else { 1 })
3717            || (matches!(role, 8..=13) && count != 1)
3718            || (role == 18 && count == 0)
3719        {
3720            return Err(publication_input_error(
3721                "publication role count omits or duplicates a required owner",
3722            ));
3723        }
3724        total = total
3725            .checked_add(count)
3726            .ok_or_else(|| publication_input_error("role count overflow"))?;
3727    }
3728    for (left, right) in [(4, 5), (6, 7), (4, 51), (5, 52), (6, 53), (7, 54)] {
3729        if counts[left - 1] != counts[right - 1] {
3730            return Err(publication_input_error(
3731                "paired cache and active tensor layer counts differ",
3732            ));
3733        }
3734    }
3735    usize::try_from(total).map_err(|_| publication_input_error("role count exceeds host extent"))
3736}
3737
3738fn tensor_layout_bytes(layout: &SemanticTensorLayout) -> Result<usize, SemanticTransitionError> {
3739    if layout.rank > 4
3740        || !matches!(
3741            (layout.scalar_type, layout.element_bytes),
3742            (1, 1) | (2, 4) | (3, 8) | (4, 2) | (5, 2) | (6, 4) | (7, 8) | (8, 1) | (9, 8)
3743        )
3744        || (layout.logical_axis != u64::MAX && layout.logical_axis >= layout.rank)
3745        || layout.dimensions[layout.rank as usize..]
3746            .iter()
3747            .any(|&n| n != 0)
3748        || layout.strides_bytes[layout.rank as usize..]
3749            .iter()
3750            .any(|&n| n != 0)
3751    {
3752        return Err(publication_input_error(
3753            "invalid tensor rank, scalar type, or unused dimensions",
3754        ));
3755    }
3756    if layout.dimensions[..layout.rank as usize].contains(&0) {
3757        return Ok(0);
3758    }
3759    let mut axes: Vec<_> = (0..layout.rank as usize)
3760        .filter(|&i| layout.dimensions[i] > 1)
3761        .collect();
3762    axes.sort_by_key(|&i| layout.strides_bytes[i]);
3763    let mut span = layout.element_bytes;
3764    for axis in axes {
3765        let stride = layout.strides_bytes[axis];
3766        if stride < span || !stride.is_multiple_of(layout.element_bytes) {
3767            return Err(publication_input_error(
3768                "overlapping or unaligned tensor layout",
3769            ));
3770        }
3771        span = stride
3772            .checked_mul(layout.dimensions[axis] - 1)
3773            .and_then(|n| span.checked_add(n))
3774            .ok_or_else(|| publication_input_error("tensor byte extent overflow"))?;
3775    }
3776    usize::try_from(span).map_err(|_| publication_input_error("tensor extent exceeds host size"))
3777}
3778
3779fn empty_model_tensor_layout(layout: &SemanticTensorLayout) -> bool {
3780    matches!(layout.role, 18..=25)
3781        && layout.logical_axis == u64::MAX
3782        && tensor_layout_bytes(layout).is_ok_and(|bytes| bytes == 0)
3783}
3784
3785fn prefix_capacity_layout(
3786    mut layout: SemanticTensorLayout,
3787    capacity: u64,
3788) -> Result<SemanticTensorLayout, SemanticTransitionError> {
3789    if !matches!(layout.role, 4 | 5)
3790        || layout.rank != 4
3791        || layout.logical_axis != 2
3792        || layout.dimensions[0] != 1
3793        || layout.dimensions[2] > capacity
3794    {
3795        return Err(publication_input_error(
3796            "prefix cache layout must be batch-one rank-four with position axis two",
3797        ));
3798    }
3799    layout.dimensions[2] = capacity;
3800    canonical_tensor_layout(layout)
3801}
3802
3803fn canonical_tensor_layout(
3804    mut layout: SemanticTensorLayout,
3805) -> Result<SemanticTensorLayout, SemanticTransitionError> {
3806    if layout.rank > 4 {
3807        return Err(publication_input_error("canonical tensor rank is invalid"));
3808    }
3809    let mut stride = layout.element_bytes;
3810    for axis in (0..layout.rank as usize).rev() {
3811        layout.strides_bytes[axis] = stride;
3812        stride = stride
3813            .checked_mul(layout.dimensions[axis].max(1))
3814            .ok_or_else(|| publication_input_error("canonical tensor stride overflow"))?;
3815    }
3816    tensor_layout_bytes(&layout)?;
3817    Ok(layout)
3818}
3819
3820fn validate_active_capacity(
3821    layout: &SemanticTensorLayout,
3822    capacity: u64,
3823) -> Result<(), SemanticTransitionError> {
3824    tensor_layout_bytes(layout)?;
3825    let axis = if matches!(layout.role, 51 | 52) {
3826        if layout.rank != 4 || layout.dimensions[0] != 1 {
3827            return Err(publication_input_error(
3828                "active attention must be batch-one rank-four",
3829            ));
3830        }
3831        2
3832    } else if matches!(layout.role, 53 | 54) {
3833        0
3834    } else {
3835        return Err(publication_input_error(
3836            "active capacity requires an active tensor role",
3837        ));
3838    };
3839    if layout.logical_axis != axis
3840        || layout.dimensions[axis as usize] != capacity
3841        || capacity == 0
3842        || layout.dimensions[..layout.rank as usize].contains(&0)
3843        || !matches!(layout.scalar_type, 4..=6)
3844    {
3845        return Err(publication_input_error(
3846            "active tensor row axis must have the exact window plus feedback capacity",
3847        ));
3848    }
3849    Ok(())
3850}
3851
3852fn continuation_capacity_layout(
3853    mut model: SemanticTensorLayout,
3854) -> Result<SemanticTensorLayout, SemanticTransitionError> {
3855    tensor_layout_bytes(&model)?;
3856    if !continuation_role(model.role) || !is_tensor_role(model.role) {
3857        return Err(publication_input_error(
3858            "continuation layout has no forward tensor owner",
3859        ));
3860    }
3861    let active = matches!(model.role, 51..=54);
3862    let suffix = matches!(model.role, 4 | 5);
3863    let axis = if active {
3864        if matches!(model.role, 51 | 52) {
3865            2
3866        } else {
3867            0
3868        }
3869    } else if suffix {
3870        2
3871    } else {
3872        u64::MAX
3873    };
3874    if model.logical_axis != axis || (axis != u64::MAX && axis >= model.rank) {
3875        return Err(publication_input_error(
3876            "continuation tensor has the wrong original row axis",
3877        ));
3878    }
3879    if suffix {
3880        model.dimensions[2] = 0;
3881        prefix_capacity_layout(model, 32)
3882    } else {
3883        canonical_tensor_layout(model)
3884    }
3885}
3886
3887fn continuation_allocation_layout(
3888    model: SemanticTensorLayout,
3889) -> Result<SemanticTensorLayout, SemanticTransitionError> {
3890    continuation_capacity_layout(model)?;
3891    if matches!(model.role, 4 | 5) {
3892        canonical_tensor_layout(model)
3893    } else {
3894        continuation_capacity_layout(model)
3895    }
3896}
3897
3898fn continuation_tensor_layout_for_kind(
3899    actual: &SemanticTensorLayout,
3900    begin: u64,
3901    end: u64,
3902    model: &SemanticTensorLayout,
3903    kind: SemanticTransitionKind,
3904) -> Result<SemanticTensorLayout, SemanticTransitionError> {
3905    if kind != SemanticTransitionKind::Update || !matches!(model.role, 4 | 5) {
3906        return continuation_tensor_layout(actual, begin, end, model);
3907    }
3908    let expected = canonical_tensor_layout(*model)?;
3909    let destination = canonical_tensor_layout(*actual)?;
3910    if destination != expected {
3911        return Err(publication_input_error(
3912            "continuation tensor differs from its transition-specific fixed-capacity layout",
3913        ));
3914    }
3915    tensor_layout_bytes(actual)?;
3916    let capacity = if expected.logical_axis == u64::MAX {
3917        0
3918    } else {
3919        expected.dimensions[expected.logical_axis as usize]
3920    };
3921    if (begin, end) != (0, capacity) {
3922        return Err(publication_input_error(
3923            "continuation transport differs from its transition-specific fixed-capacity output",
3924        ));
3925    }
3926    Ok(destination)
3927}
3928
3929fn continuation_tensor_layout(
3930    actual: &SemanticTensorLayout,
3931    begin: u64,
3932    end: u64,
3933    model: &SemanticTensorLayout,
3934) -> Result<SemanticTensorLayout, SemanticTransitionError> {
3935    let expected = continuation_capacity_layout(*model)?;
3936    let destination = canonical_tensor_layout(*actual)?;
3937    if destination != expected {
3938        return Err(publication_input_error(
3939            "continuation tensor differs from its cold fixed-capacity layout",
3940        ));
3941    }
3942    // Validate original strides too: canonicalization must not conceal an
3943    // invalid producer view before the recorded device-to-device snapshot.
3944    tensor_layout_bytes(actual)?;
3945    let capacity = if expected.logical_axis == u64::MAX {
3946        0
3947    } else {
3948        expected.dimensions[expected.logical_axis as usize]
3949    };
3950    if (begin, end) != (0, capacity) {
3951        return Err(publication_input_error(
3952            "continuation transport differs from its original fixed-capacity output",
3953        ));
3954    }
3955    Ok(destination)
3956}
3957
3958/// Cold copy geometry only: no tensor value is inspected or copied through host memory.
3959fn tensor_copy_plan(
3960    source: &SemanticTensorLayout,
3961    destination: &SemanticTensorLayout,
3962) -> Result<Vec<(u64, u64, usize)>, SemanticTransitionError> {
3963    tensor_layout_bytes(source)?;
3964    tensor_layout_bytes(destination)?;
3965    if source.rank != destination.rank
3966        || source.scalar_type != destination.scalar_type
3967        || source.element_bytes != destination.element_bytes
3968        || (0..source.rank as usize)
3969            .any(|axis| source.dimensions[axis] > destination.dimensions[axis])
3970    {
3971        return Err(publication_input_error(
3972            "tensor snapshot layout does not fit its owned destination",
3973        ));
3974    }
3975    if source.dimensions[..source.rank as usize].contains(&0) {
3976        return Ok(Vec::new());
3977    }
3978    let mut first_outer = source.rank as usize;
3979    let mut chunk = source.element_bytes;
3980    while first_outer > 0 {
3981        let axis = first_outer - 1;
3982        if source.strides_bytes[axis] != chunk || destination.strides_bytes[axis] != chunk {
3983            break;
3984        }
3985        chunk = chunk
3986            .checked_mul(source.dimensions[axis])
3987            .ok_or_else(|| publication_input_error("copy chunk overflow"))?;
3988        first_outer = axis;
3989    }
3990    let count = source.dimensions[..first_outer]
3991        .iter()
3992        .try_fold(1u64, |count, &dim| count.checked_mul(dim))
3993        .ok_or_else(|| publication_input_error("copy row count overflow"))?;
3994    let mut result = Vec::new();
3995    result
3996        .try_reserve(
3997            usize::try_from(count)
3998                .map_err(|_| publication_input_error("copy row count exceeds host extent"))?,
3999        )
4000        .map_err(|error| runtime_error("copy plan allocation", error))?;
4001    for mut linear in 0..count {
4002        let (mut source_offset, mut destination_offset) = (0u64, 0u64);
4003        for axis in (0..first_outer).rev() {
4004            let position = linear % source.dimensions[axis];
4005            linear /= source.dimensions[axis];
4006            source_offset += position * source.strides_bytes[axis];
4007            destination_offset += position * destination.strides_bytes[axis];
4008        }
4009        result.push((source_offset, destination_offset, chunk as usize));
4010    }
4011    Ok(result)
4012}
4013
4014#[derive(Clone, Copy)]
4015struct TensorMetadata<'a> {
4016    device_type: i32,
4017    device_id: i32,
4018    dtype: crate::dlpack::DLDataType,
4019    shape: &'a [i64],
4020    strides: Option<&'a [i64]>,
4021    data: u64,
4022    byte_offset: u64,
4023}
4024
4025// SAFETY: the caller retains the genuine managed producer and its immutable
4026// shape/stride arrays for the returned borrow. A scalar has no shape entries;
4027// its DLPack shape and strides may be null and must never form a raw Rust slice.
4028unsafe fn semantic_tensor_metadata(
4029    actual: &crate::dlpack::DLTensor,
4030) -> Result<TensorMetadata<'_>, SemanticTransitionError> {
4031    if !(0..=4).contains(&actual.ndim) || (actual.ndim != 0 && actual.shape.is_null()) {
4032        return Err(publication_input_error(
4033            "semantic tensor requires an original scalar through rank-four shape",
4034        ));
4035    }
4036    let rank = actual.ndim as usize;
4037    Ok(TensorMetadata {
4038        device_type: actual.device.device_type,
4039        device_id: actual.device.device_id,
4040        dtype: actual.dtype,
4041        // SAFETY: a nonempty shape was checked above and is owned by the caller.
4042        shape: if rank == 0 {
4043            &[]
4044        } else {
4045            unsafe { std::slice::from_raw_parts(actual.shape, rank) }
4046        },
4047        strides: if rank == 0 || actual.strides.is_null() {
4048            None
4049        } else {
4050            // SAFETY: DLPack's retained producer owns ndim stride elements.
4051            Some(unsafe { std::slice::from_raw_parts(actual.strides, rank) })
4052        },
4053        data: actual.data as usize as u64,
4054        byte_offset: actual.byte_offset,
4055    })
4056}
4057
4058fn publication_input_error(detail: &str) -> SemanticTransitionError {
4059    SemanticTransitionError::InvalidInput {
4060        detail: detail.into(),
4061    }
4062}
4063
4064fn validate_tensor_metadata(
4065    declared: &SemanticTensorLayout,
4066    actual: &TensorMetadata<'_>,
4067    device_id: i32,
4068) -> Result<(u64, usize), SemanticTransitionError> {
4069    let invalid = || {
4070        publication_input_error("semantic tensor metadata differs from its exact model contract")
4071    };
4072    let (dtype_code, bits) = match declared.scalar_type {
4073        1 => (crate::dlpack::K_DLUINT, 8),
4074        2 => (crate::dlpack::K_DLUINT, 32),
4075        3 => (crate::dlpack::K_DLUINT, 64),
4076        4 => (crate::dlpack::K_DLFLOAT, 16),
4077        5 => (4, 16), // DLPack's distinct bfloat type code, not IEEE float16.
4078        6 => (crate::dlpack::K_DLFLOAT, 32),
4079        7 => (0, 64), // Signed token indices are not unsigned storage aliases.
4080        8 => (6, 8),  // DLPack's distinct Boolean code.
4081        9 => (crate::dlpack::K_DLFLOAT, 64),
4082        _ => return Err(invalid()),
4083    };
4084    let rank = actual.shape.len();
4085    if actual.device_type != crate::dlpack::K_DLCUDA
4086        || actual.device_id != device_id
4087        || rank > 4
4088        || declared.rank != rank as u64
4089        || actual.dtype.code != dtype_code
4090        || actual.dtype.bits != bits
4091        || actual.dtype.lanes != 1
4092        || declared.element_bytes != u64::from(bits / 8)
4093        || (declared.role != 0 && SemanticStateRole::from_code(declared.role).is_none())
4094        || (declared.logical_axis != u64::MAX && declared.logical_axis >= declared.rank)
4095        || declared.dimensions[rank..]
4096            .iter()
4097            .any(|&dimension| dimension != 0)
4098        || declared.strides_bytes[rank..]
4099            .iter()
4100            .any(|&stride| stride != 0)
4101    {
4102        return Err(invalid());
4103    }
4104    let element_bytes = declared.element_bytes;
4105    let mut dimensions = [0u64; 4];
4106    for (index, &dimension) in actual.shape.iter().enumerate() {
4107        dimensions[index] = u64::try_from(dimension).map_err(|_| invalid())?;
4108    }
4109    if dimensions != declared.dimensions {
4110        return Err(invalid());
4111    }
4112    let mut strides = [0u64; 4];
4113    if let Some(actual_strides) = actual.strides {
4114        if actual_strides.len() != rank {
4115            return Err(invalid());
4116        }
4117        for (index, &stride) in actual_strides.iter().enumerate() {
4118            strides[index] = u64::try_from(stride)
4119                .ok()
4120                .and_then(|stride| stride.checked_mul(element_bytes))
4121                .ok_or_else(invalid)?;
4122        }
4123    } else {
4124        let mut stride = element_bytes;
4125        for index in (0..rank).rev() {
4126            strides[index] = stride;
4127            stride = stride.checked_mul(dimensions[index]).ok_or_else(invalid)?;
4128        }
4129    }
4130    if strides != declared.strides_bytes {
4131        return Err(invalid());
4132    }
4133    let empty = dimensions[..rank].contains(&0);
4134    let bytes = if empty {
4135        0
4136    } else {
4137        // Positive non-overlapping strides support real transposed and padded
4138        // views. Broadcast/overlapping cells are not a mutable state contract.
4139        let mut axes = (0..rank)
4140            .filter(|&axis| dimensions[axis] > 1)
4141            .collect::<Vec<_>>();
4142        axes.sort_by_key(|&axis| strides[axis]);
4143        let mut span = element_bytes;
4144        for axis in axes {
4145            if strides[axis] < span {
4146                return Err(invalid());
4147            }
4148            span = strides[axis]
4149                .checked_mul(dimensions[axis] - 1)
4150                .and_then(|bytes| span.checked_add(bytes))
4151                .ok_or_else(invalid)?;
4152        }
4153        span
4154    };
4155    if !actual.byte_offset.is_multiple_of(element_bytes) || (bytes != 0 && actual.data == 0) {
4156        return Err(invalid());
4157    }
4158    let pointer = actual
4159        .data
4160        .checked_add(actual.byte_offset)
4161        .ok_or_else(invalid)?;
4162    if !pointer.is_multiple_of(element_bytes) || pointer.checked_add(bytes).is_none() {
4163        return Err(invalid());
4164    }
4165    let bytes = usize::try_from(bytes).map_err(|_| invalid())?;
4166    usize::try_from(pointer).map_err(|_| invalid())?;
4167    Ok((pointer, bytes))
4168}
4169
4170#[derive(Clone)]
4171struct PreparedSemanticTensor {
4172    layout: SemanticTensorLayout,
4173    logical_begin: u64,
4174    logical_end: u64,
4175    data: u64,
4176    source: Option<DeviceMemoryView<u8>>,
4177    native_allocation: Option<DeviceAllocationProvenance>,
4178    // Empty views still retain their genuine producer; releasing its token can
4179    // retire a larger backing allocation whose producer work is still pending.
4180    _empty_owner: Option<Arc<DlpackManagedTensor>>,
4181}
4182
4183#[cfg(feature = "semantic-policy")]
4184unsafe fn policy_score_cotangent_metadata(
4185    actual: &crate::dlpack::DLTensor,
4186    device_id: i32,
4187) -> Result<(u64, usize), SemanticTransitionError> {
4188    // SAFETY: the caller retains the original shape/stride descriptor arrays.
4189    let (rows, scalar, data, bytes) =
4190        unsafe { crate::dlpack::dlpack_tensor_metadata(device_id, actual) }.map_err(|error| {
4191            publication_input_error(&format!("selected-score cotangent metadata: {error}"))
4192        })?;
4193    if rows != COMPONENT_COUNT as u64
4194        || scalar != xlog_core::ScalarType::F64
4195        || data.checked_add(bytes as u64).is_none()
4196    {
4197        return Err(publication_input_error(
4198            "selected-score cotangents require exact contiguous FP64 storage",
4199        ));
4200    }
4201    Ok((data, bytes))
4202}
4203
4204struct RetainedTensorAdmission<T: Send + 'static> {
4205    inputs: Option<Vec<T>>,
4206    stream: Arc<CudaStream>,
4207    ready: bool,
4208}
4209
4210impl<T: Send + 'static> Drop for RetainedTensorAdmission<T> {
4211    fn drop(&mut self) {
4212        let Some(inputs) = self.inputs.take() else {
4213            return;
4214        };
4215        if self.ready {
4216            drop(inputs);
4217            return;
4218        }
4219        // Preserve the genuine producer tokens through a failed/unknown cold
4220        // handoff. Canonical retirement retries readiness and runs deleters once.
4221        crate::cuda_graph::retire_resources_after_completion(
4222            (Some(inputs), Arc::clone(&self.stream)),
4223            |owners| owners.1.synchronize(),
4224            |owners| {
4225                drop(owners.0.take());
4226                Ok(())
4227            },
4228            |_| Ok(()),
4229            |_, error| eprintln!("semantic tensor producer retirement incomplete: {error}"),
4230        );
4231    }
4232}
4233
4234// Metadata/ownership admission only. The caller must order producer readiness
4235// before reading any device cells; cold import above waits, content guards use
4236// device event edges and retain all owners until explicit reader release.
4237fn prepare_semantic_tensors(
4238    provider: &CudaKernelProvider,
4239    inputs: Vec<SemanticTensorInput>,
4240) -> Result<Vec<PreparedSemanticTensor>, SemanticTransitionError> {
4241    let stream = Arc::clone(provider.device().inner().stream());
4242    let mut pending = RetainedTensorAdmission {
4243        inputs: Some(inputs),
4244        stream: Arc::clone(&stream),
4245        ready: false,
4246    };
4247    let mut geometry = Vec::new();
4248    for input in pending
4249        .inputs
4250        .as_ref()
4251        .expect("retained original producer roster")
4252    {
4253        let pointer = input.tensor.as_ptr();
4254        if pointer.is_null() {
4255            return Err(publication_input_error(
4256                "semantic tensor managed owner is null",
4257            ));
4258        }
4259        // SAFETY: the genuine managed producer owns valid immutable DLPack
4260        // metadata for this import. Rank is bounded before reading its arrays;
4261        // the caller owns the managed record and orders its producer before use.
4262        let actual = unsafe { &(*pointer).dl_tensor };
4263        // SAFETY: the complete original producer roster remains in pending.
4264        let metadata = unsafe { semantic_tensor_metadata(actual) }?;
4265        let (data, bytes) =
4266            validate_tensor_metadata(&input.layout, &metadata, provider.device().ordinal() as i32)?;
4267        geometry.push((data, bytes));
4268    }
4269    // Every fallible metadata check precedes transfer of any original owner.
4270    // Failure retires the complete producer roster on its negotiated stream.
4271    // Success transfers ownership to the views, without a host wait.
4272    pending.ready = true;
4273    let inputs = pending
4274        .inputs
4275        .take()
4276        .expect("retained original producer roster");
4277    let mut imported = Vec::with_capacity(inputs.len());
4278    for (input, (data, bytes)) in inputs.into_iter().zip(geometry) {
4279        let (source, empty_owner) = if bytes == 0 {
4280            // No invented device cells, but keep the actual managed owner until
4281            // the caller's cold completion or content-reader retirement.
4282            (None, Some(Arc::new(input.tensor)))
4283        } else {
4284            // SAFETY: exact original dtype/shape/stride/offset/device bounds and
4285            // producer readiness ordering is the caller's responsibility. This is the
4286            // canonical managed owner, not a borrowed raw-pointer slice.
4287            let column =
4288                unsafe { CudaColumn::dlpack(data, bytes, Arc::clone(&stream), input.tensor) };
4289            (Some(column.device_view()), None)
4290        };
4291        imported.push(PreparedSemanticTensor {
4292            layout: input.layout,
4293            logical_begin: input.logical_begin,
4294            logical_end: input.logical_end,
4295            data,
4296            source,
4297            native_allocation: input.native_allocation,
4298            _empty_owner: empty_owner,
4299        });
4300    }
4301    Ok(imported)
4302}
4303
4304fn complete_tensor_handoff<T: Send + 'static>(
4305    provider: &CudaKernelProvider,
4306    inputs: Vec<T>,
4307) -> Result<Vec<T>, SemanticTransitionError> {
4308    let stream = Arc::clone(provider.device().inner().stream());
4309    let mut pending = RetainedTensorAdmission {
4310        inputs: Some(inputs),
4311        stream,
4312        ready: false,
4313    };
4314    let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&pending.stream)
4315        .map_err(|error| runtime_error("tensor producer stream admission", error))?;
4316    pending
4317        .stream
4318        .synchronize()
4319        .map_err(|error| runtime_error("tensor producer handoff", error))?;
4320    pending.ready = true;
4321    Ok(pending
4322        .inputs
4323        .take()
4324        .expect("retained tensor admission owns its inputs"))
4325}
4326
4327#[repr(C)]
4328#[derive(Clone, Copy, Default)]
4329struct PublicationStorageEntry {
4330    pointer: u64,
4331    bytes: u64,
4332    generation: u64,
4333}
4334
4335#[repr(C)]
4336#[derive(Clone, Copy, Default)]
4337struct PublicationRange {
4338    role: u64,
4339    index: u64,
4340    storage_slot: u64,
4341    generation: u64,
4342    offset_bytes: u64,
4343    length_bytes: u64,
4344    logical_begin: u64,
4345    logical_end: u64,
4346    digest: Identity256,
4347    backing_digest: Identity256,
4348}
4349
4350/// Descriptor integrity includes local handles; logical content identities do
4351/// not. Every physical range resolves through the owner's fixed storage table.
4352#[repr(C)]
4353#[derive(Clone, Copy, Default, PartialEq, Eq)]
4354struct PublicationHeader {
4355    abi: u64,
4356    instance: Identity256,
4357    recovered_instance: Identity256,
4358    sealed_epoch: u64,
4359    base_word: u64,
4360    publication_word: u64,
4361    ring_head: u64,
4362    prefix_extent: u64,
4363    semantic_owner: u64,
4364    semantic_slot: u64,
4365    semantic_generation: u64,
4366    semantic_digest: Identity256,
4367    semantic_extents: [u64; 3],
4368    model_generation: u64,
4369    neural_bank: u64,
4370    neural_generation: u64,
4371    cache_generation: u64,
4372    authority_generation: u64,
4373    terminal: u64,
4374    terminal_position: u64,
4375    fuel: u64,
4376    proposal: u64,
4377    stream_serial: u64,
4378    family_id: u64,
4379    training_cursor: u64,
4380    training_rng: [u64; 4],
4381    range_count: u64,
4382    model_geometry_digest: Identity256,
4383    model_numerical_digest: Identity256,
4384    logical_digest: Identity256,
4385    state_digest: Identity256,
4386    descriptor_digest: Identity256,
4387}
4388
4389impl PublicationHeader {
4390    fn rng_binding(&self) -> Result<SemanticRngBinding, SemanticTransitionError> {
4391        if self.stream_serial > u64::MAX >> 8 {
4392            return Err(SemanticTransitionError::GenerationExhausted);
4393        }
4394        Ok(SemanticRngBinding {
4395            model_generation: u32::try_from(self.model_generation)
4396                .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
4397            family_id: u8::try_from(self.family_id)
4398                .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
4399            stream_serial: self.stream_serial,
4400            proposal: u32::try_from(self.proposal)
4401                .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
4402        })
4403    }
4404}
4405
4406#[repr(C)]
4407#[derive(Clone, Copy, Default)]
4408struct PublicationControl {
4409    abi: u64,
4410    word: u64,
4411    instance: Identity256,
4412    banks: [u64; 2],
4413    directories: [u64; 2],
4414    storage: u64,
4415    storage_count: u64,
4416    contract: u64,
4417    continuation: u64,
4418    reader_counts: [u64; 2],
4419    reader_gate: u64,
4420    refusal: u64,
4421}
4422
4423#[repr(C)]
4424#[derive(Clone, Copy)]
4425struct PublicationBank {
4426    header: PublicationHeader,
4427    source: [SourceSlot; 32],
4428    state: DeviceState,
4429    receipts: [SemanticTransitionReceipt; COMPONENT_COUNT],
4430}
4431
4432#[derive(Clone, Copy)]
4433enum PublicationBankField {
4434    Source,
4435    PrefixExtent,
4436    RingHead,
4437    Terminal,
4438}
4439
4440impl PublicationBankField {
4441    fn layout(self) -> (std::ops::Range<usize>, Vec<i64>, Vec<i64>) {
4442        let (offset, bytes, shape, strides) = match self {
4443            Self::Source => (
4444                std::mem::offset_of!(PublicationBank, source),
4445                size_of::<[SourceSlot; 32]>(),
4446                vec![32, 8],
4447                vec![8, 1],
4448            ),
4449            Self::PrefixExtent => (
4450                std::mem::offset_of!(PublicationBank, header)
4451                    + std::mem::offset_of!(PublicationHeader, prefix_extent),
4452                size_of::<u64>(),
4453                vec![1],
4454                vec![1],
4455            ),
4456            Self::RingHead => (
4457                std::mem::offset_of!(PublicationBank, header)
4458                    + std::mem::offset_of!(PublicationHeader, ring_head),
4459                size_of::<u64>(),
4460                vec![1],
4461                vec![1],
4462            ),
4463            Self::Terminal => (
4464                std::mem::offset_of!(PublicationBank, header)
4465                    + std::mem::offset_of!(PublicationHeader, terminal),
4466                size_of::<u64>(),
4467                vec![1],
4468                vec![1],
4469            ),
4470        };
4471        (offset..offset + bytes, shape, strides)
4472    }
4473}
4474
4475#[repr(C)]
4476#[derive(Clone, Copy, Default)]
4477struct PublicationRoleCount {
4478    role: u64,
4479    count: u64,
4480}
4481
4482#[repr(C)]
4483#[derive(Clone, Copy, Default)]
4484struct PublicationContract {
4485    abi: u64,
4486    range_capacity: u64,
4487    prefix_capacity: u64,
4488    window_capacity: u64,
4489    feedback_capacity: u64,
4490    max_position: u64,
4491    pad_token: u64,
4492    terminal_tokens: u64,
4493    terminal_token_count: u64,
4494    final_intent_payload_bytes: u64,
4495    model_generation: u64,
4496    policy_generation: u64,
4497    authority_generation: u64,
4498    semantic_owner: u64,
4499    task_identity: Identity256,
4500    topology_identity: Identity256,
4501    table_identity: Identity256,
4502    role_counts: u64,
4503    role_count: u64,
4504    model_contract_layout: SemanticModelContractLayout,
4505}
4506
4507#[repr(C)]
4508#[derive(Clone, Copy, Default)]
4509struct PendingContinuation {
4510    abi: u64,
4511    instance: Identity256,
4512    base_word: u64,
4513    model_generation: u64,
4514    authority_generation: u64,
4515    topology_identity: Identity256,
4516    table_identity: Identity256,
4517    prefix_identity: Identity256,
4518    ranges: u64,
4519    range_count: u64,
4520    transition_kind: u64,
4521    text: TextBinding,
4522    numerical_admissibility: u64,
4523    training_selection: u64,
4524    model_update_bindings: u64,
4525    model_update_binding_count: u64,
4526    model_update_admissibility: u64,
4527    model_update_refusal: u64,
4528    model_update_canary_results: u64,
4529    numerical_blocks: u64,
4530    physical_blocks: u64,
4531    model_schema_digest: Identity256,
4532    model_identity: Identity256,
4533}
4534
4535#[repr(C)]
4536#[derive(Clone, Copy)]
4537struct ContinuationInputs {
4538    text: TextBinding,
4539    active_rows: u64,
4540    active_row_count: u64,
4541    numerical_admissibility: u64,
4542    transition_kind: u64,
4543    authority_bytes: u64,
4544    training_selection: u64,
4545    model_update_bindings: u64,
4546    model_update_binding_count: u64,
4547    model_update_admissibility: u64,
4548    model_update_refusal: u64,
4549    model_update_canary_results: u64,
4550    numerical_blocks: u64,
4551    physical_blocks: u64,
4552    model_schema_digest: Identity256,
4553    model_identity: Identity256,
4554    model_contract: u64,
4555    model_contract_bytes: u64,
4556}
4557
4558#[derive(Clone, Copy, Default)]
4559struct ModelUpdateContinuationInputs {
4560    bindings: u64,
4561    binding_count: u64,
4562    admissibility: u64,
4563    refusal: u64,
4564    canary_results: u64,
4565}
4566
4567#[repr(C)]
4568#[derive(Clone, Copy, Default)]
4569struct ModelUpdateBinding {
4570    source: u64,
4571    bytes: u64,
4572    slots: [u64; 2],
4573}
4574
4575#[repr(C)]
4576#[derive(Clone, Copy, Default)]
4577struct ModelUpdateEvidenceSource {
4578    lease: u64,
4579    parent_header: u64,
4580    result: u64,
4581    origin: u64,
4582    states: [u64; 2],
4583}
4584
4585#[repr(C)]
4586#[derive(Clone, Copy, Default)]
4587struct ModelForwardSealInput {
4588    role: u64,
4589    index: u64,
4590    tensor_digest: u64,
4591    backing_digest: u64,
4592}
4593
4594#[repr(C)]
4595#[derive(Clone, Copy, Default)]
4596struct ModelForwardReceipt {
4597    abi: u64,
4598    availability: u64,
4599    role: u64,
4600    generation: u64,
4601    work_sequence: u64,
4602    logits: u64,
4603    scalar_type: u64,
4604    row_count: u64,
4605    capacity: u64,
4606    vocabulary: u64,
4607    strides_bytes: [u64; 3],
4608    model_geometry_digest: Identity256,
4609    model_numerical_digest: Identity256,
4610    logits_digest: Identity256,
4611    identity: Identity256,
4612}
4613
4614#[cfg(feature = "semantic-policy")]
4615impl ModelForwardReceipt {
4616    fn canonical_bytes(&self) -> Vec<u8> {
4617        let mut bytes = Vec::with_capacity(size_of::<Self>());
4618        for word in [
4619            self.abi,
4620            self.availability,
4621            self.role,
4622            self.generation,
4623            self.work_sequence,
4624            self.logits,
4625            self.scalar_type,
4626            self.row_count,
4627            self.capacity,
4628            self.vocabulary,
4629        ]
4630        .into_iter()
4631        .chain(self.strides_bytes)
4632        {
4633            bytes.extend_from_slice(&word.to_le_bytes());
4634        }
4635        for identity in [
4636            self.model_geometry_digest,
4637            self.model_numerical_digest,
4638            self.logits_digest,
4639            self.identity,
4640        ] {
4641            bytes.extend_from_slice(identity.as_bytes());
4642        }
4643        bytes
4644    }
4645}
4646
4647/// Original completed forward receipt, copied cold without retaining CUDA aliases.
4648#[cfg(feature = "semantic-policy")]
4649#[derive(Clone, Debug)]
4650pub struct SemanticUpdateForwardReceipt {
4651    pub availability: u64,
4652    /// None only when the original producer did not obtain a complete receipt.
4653    pub material: Option<SemanticUpdateForwardReceiptMaterial>,
4654}
4655
4656#[cfg(feature = "semantic-policy")]
4657#[derive(Clone, Debug)]
4658pub struct SemanticUpdateForwardReceiptMaterial {
4659    pub role: u64,
4660    pub generation: u64,
4661    pub work_sequence: u64,
4662    pub scalar_type: u64,
4663    pub dimensions: [u64; 3],
4664    pub strides_bytes: [u64; 3],
4665    pub model_geometry_digest: Identity256,
4666    pub model_numerical_digest: Identity256,
4667    pub logits_digest: Identity256,
4668    pub identity: Identity256,
4669    /// Exact private receipt words, including the original pointer value as data,
4670    /// not a live address or execution grant. Its SHA-256 seal is the final 32 bytes.
4671    pub canonical_bytes: Vec<u8>,
4672}
4673
4674/// A frozen check and its device-authored execution/measurement availability.
4675#[cfg(feature = "semantic-policy")]
4676#[derive(Clone, Debug)]
4677pub struct SemanticUpdateCanaryMeasurement {
4678    pub frozen: crate::SemanticTrainingCanaryRecord,
4679    pub protected_positions: Vec<u64>,
4680    pub availability: u64,
4681    pub reason: u64,
4682    pub measurement_bits: Option<u64>,
4683    pub memory_used: u64,
4684    pub work_used: u64,
4685}
4686
4687/// Cold original Update observations. Acceptance is independent of availability.
4688#[cfg(feature = "semantic-policy")]
4689#[derive(Clone, Debug)]
4690pub struct SemanticUpdateMeasurements {
4691    pub predecessor: SemanticPublishedIdentity,
4692    pub successor: Option<SemanticPublishedIdentity>,
4693    pub bank: u8,
4694    pub model_generation: u64,
4695    pub model_geometry_digest: Identity256,
4696    pub model_numerical_digest: Identity256,
4697    pub transition_status: u64,
4698    pub selection: SemanticTrainingViewSelection,
4699    pub canaries: Vec<SemanticUpdateCanaryMeasurement>,
4700    pub forward_receipts: [SemanticUpdateForwardReceipt; 2],
4701    pub canary_refusal: Option<SemanticTrainingCanaryRefusalRecord>,
4702}
4703
4704#[repr(C)]
4705#[derive(Clone, Copy, Default)]
4706struct ModelForwardReceiptInputs {
4707    control: u64,
4708    lease: u64,
4709    candidate_seals: u64,
4710    candidate_seal_count: u64,
4711    role: u64,
4712    work_sequence: u64,
4713    logits: u64,
4714    scalar_type: u64,
4715    row_count: u64,
4716    capacity: u64,
4717    vocabulary: u64,
4718    row_stride_bytes: u64,
4719    position_stride_bytes: u64,
4720    vocabulary_stride_bytes: u64,
4721    logits_digest: u64,
4722    receipt: u64,
4723}
4724
4725#[repr(C)]
4726#[derive(Clone, Copy, Default)]
4727struct PublicationCommand {
4728    control: u64,
4729    lease: u64,
4730    operation: u64,
4731}
4732
4733#[repr(C)]
4734#[derive(Clone, Copy, Default)]
4735struct PublicationDeliveryInput {
4736    lease: u64,
4737    receipt: u64,
4738    receipt_len: u64,
4739    recipient_id: Identity256,
4740    receipt_digest: Identity256,
4741}
4742
4743#[repr(C)]
4744#[derive(Clone, Copy, Default)]
4745struct PublicationLease {
4746    abi: u64,
4747    status: u64,
4748    instance: Identity256,
4749    word: u64,
4750    bank: u64,
4751    epoch: u64,
4752    active: u64,
4753    transition_kind: u64,
4754}
4755
4756#[repr(C)]
4757#[derive(Clone, Copy, Default)]
4758struct CompletionCoverage {
4759    abi: u64,
4760    instance: Identity256,
4761    base_word: u64,
4762    model_generation: u64,
4763    topology_identity: Identity256,
4764    table_identity: Identity256,
4765    prefix_identity: Identity256,
4766    prefix_begin: u64,
4767    prefix_end: u64,
4768    source_digest: Identity256,
4769    attention_digest: Identity256,
4770    linear_digest: Identity256,
4771    value_digest: Identity256,
4772    edit_digest: Identity256,
4773    receipt_digest: Identity256,
4774}
4775
4776#[repr(C)]
4777#[derive(Clone, Copy)]
4778struct RawFeedbackRecord {
4779    valid: u64,
4780    statement_index: u64,
4781    statement_offset_bytes: u64,
4782    statement_length_bytes: u64,
4783    pro: u64,
4784    contra: u64,
4785    query_receipt: [u64; 42],
4786}
4787
4788#[repr(C)]
4789#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4790struct AttemptReceipt {
4791    abi: u64,
4792    transition_kind: u64,
4793    instance: Identity256,
4794    base_word: u64,
4795    next_word: u64,
4796    logical_digest: Identity256,
4797    action_receipts_digest: Identity256,
4798    semantic_receipts_digest: Identity256,
4799    coverage_digest: Identity256,
4800    replay_head_digest: Identity256,
4801    intent_head_digest: Identity256,
4802    acknowledgement_head_digest: Identity256,
4803    previous_attempt_digest: Identity256,
4804    receipt_digest: Identity256,
4805}
4806
4807#[repr(C)]
4808#[derive(Clone, Copy, Default)]
4809struct IntentQueueHeader {
4810    abi: u64,
4811    count: u64,
4812    capacity: u64,
4813    payload_used_bytes: u64,
4814    payload_capacity_bytes: u64,
4815    effect_offset_bytes: u64,
4816    effect_length_bytes: u64,
4817    chain_head: Identity256,
4818}
4819
4820#[repr(C)]
4821#[derive(Clone, Copy, Default)]
4822struct IntentEntry {
4823    stable_identity: Identity256,
4824    checkpoint_lineage: Identity256,
4825    base_logical: Identity256,
4826    effective_delta: Identity256,
4827    result_logical: Identity256,
4828    effect_digest: Identity256,
4829    payload_digest: Identity256,
4830    payload_offset: u64,
4831    payload_len: u64,
4832    audit_instance: Identity256,
4833    audit_epoch: u64,
4834    previous_chain: Identity256,
4835    chain: Identity256,
4836}
4837
4838#[repr(C)]
4839#[derive(Clone, Copy, Default)]
4840struct AcknowledgementQueueHeader {
4841    abi: u64,
4842    count: u64,
4843    capacity: u64,
4844    payload_used_bytes: u64,
4845    payload_capacity_bytes: u64,
4846    chain_head: Identity256,
4847}
4848
4849#[repr(C)]
4850#[derive(Clone, Copy, Default)]
4851struct AcknowledgementEntry {
4852    stable_identity: Identity256,
4853    receipt_digest: Identity256,
4854    receipt_len: u64,
4855    previous_chain: Identity256,
4856    chain: Identity256,
4857}
4858
4859#[repr(C)]
4860#[derive(Clone, Copy, Default)]
4861struct TokenProvenance {
4862    source_slot: u64,
4863    logical_position: u64,
4864    token: u64,
4865    base_word: u64,
4866    proposal: u64,
4867    ordinal: u64,
4868    action_receipt_digest: Identity256,
4869    authority_generation: u64,
4870    origin_logical_digest: Identity256,
4871    authority_closure_digest: Identity256,
4872    record_digest: Identity256,
4873}
4874
4875#[repr(C)]
4876#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4877pub struct SemanticTensorLayout {
4878    pub role: u64,
4879    pub index: u64,
4880    pub element_bytes: u64,
4881    // U8, U32, U64, F16, BF16, F32, I64, Bool8 respectively.
4882    // Equal widths are not equal types.
4883    pub scalar_type: u64,
4884    pub rank: u64,
4885    pub logical_axis: u64,
4886    pub dimensions: [u64; 4],
4887    pub strides_bytes: [u64; 4],
4888}
4889
4890#[repr(C)]
4891#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4892struct TensorLayoutTableHeader {
4893    abi: u64,
4894    layout_count: u64,
4895    active_computed: u64,
4896    active_row_count: u64,
4897}
4898
4899fn tensor_table_capacity(
4900    layout_count: usize,
4901    row_count: u64,
4902) -> Result<usize, SemanticTransitionError> {
4903    layout_count
4904        .checked_mul(size_of::<SemanticTensorLayout>())
4905        .and_then(|n| n.checked_add(size_of::<TensorLayoutTableHeader>()))
4906        .and_then(|n| {
4907            usize::try_from(row_count)
4908                .ok()?
4909                .checked_mul(size_of::<SemanticActiveRow>())?
4910                .checked_add(n)
4911        })
4912        .ok_or_else(|| publication_input_error("tensor layout table extent overflow"))
4913}
4914
4915fn tensor_table_bytes(
4916    layouts: &[SemanticTensorLayout],
4917    computed: bool,
4918    rows: &[SemanticActiveRow],
4919) -> Result<Vec<u8>, SemanticTransitionError> {
4920    if !computed && !rows.is_empty() {
4921        return Err(publication_input_error(
4922            "uncomputed active cache cannot contain rows",
4923        ));
4924    }
4925    let length = tensor_table_capacity(layouts.len(), rows.len() as u64)?;
4926    let mut bytes = Vec::new();
4927    bytes
4928        .try_reserve_exact(length)
4929        .map_err(|error| runtime_error("tensor layout table allocation", error))?;
4930    bytes.extend(publication_abi_bytes(&[TensorLayoutTableHeader {
4931        abi: 1,
4932        layout_count: layouts.len() as u64,
4933        active_computed: u64::from(computed),
4934        active_row_count: rows.len() as u64,
4935    }]));
4936    bytes.extend(publication_abi_bytes(layouts));
4937    bytes.extend(publication_abi_bytes(rows));
4938    Ok(bytes)
4939}
4940
4941fn decode_tensor_table(
4942    bytes: &[u8],
4943) -> Result<
4944    (
4945        TensorLayoutTableHeader,
4946        Vec<SemanticTensorLayout>,
4947        SemanticActiveRows,
4948    ),
4949    SemanticTransitionError,
4950> {
4951    if bytes.len() < size_of::<TensorLayoutTableHeader>() {
4952        return Err(SemanticTransitionError::ObservationMismatch);
4953    }
4954    // SAFETY: checked complete integer-only header; byte storage need not align.
4955    let header = unsafe {
4956        bytes
4957            .as_ptr()
4958            .cast::<TensorLayoutTableHeader>()
4959            .read_unaligned()
4960    };
4961    let count = usize::try_from(header.layout_count)
4962        .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
4963    if header.abi != 1
4964        || header.active_computed > 1
4965        || (header.active_computed == 0 && header.active_row_count != 0)
4966        || tensor_table_capacity(count, header.active_row_count)? != bytes.len()
4967    {
4968        return Err(SemanticTransitionError::ObservationMismatch);
4969    }
4970    let layouts_end =
4971        size_of::<TensorLayoutTableHeader>() + count * size_of::<SemanticTensorLayout>();
4972    let layouts = bytes[size_of::<TensorLayoutTableHeader>()..layouts_end]
4973        .as_chunks::<{ size_of::<SemanticTensorLayout>() }>()
4974        .0
4975        .iter()
4976        // SAFETY: each chunk is a complete integer-only C record.
4977        .map(|chunk| unsafe {
4978            chunk
4979                .as_ptr()
4980                .cast::<SemanticTensorLayout>()
4981                .read_unaligned()
4982        })
4983        .collect();
4984    let rows = bytes[layouts_end..]
4985        .as_chunks::<{ size_of::<SemanticActiveRow>() }>()
4986        .0
4987        .iter()
4988        // SAFETY: each chunk is a complete integer-only C record.
4989        .map(|chunk| unsafe { chunk.as_ptr().cast::<SemanticActiveRow>().read_unaligned() })
4990        .collect();
4991    Ok((
4992        header,
4993        layouts,
4994        SemanticActiveRows {
4995            computed: header.active_computed == 1,
4996            rows,
4997        },
4998    ))
4999}
5000
5001// SAFETY: these C-layout records contain only integers, fixed byte arrays and
5002// the already checked scalar state/receipt ABI. Every bit pattern is valid.
5003unsafe impl DeviceRepr for PublicationStorageEntry {}
5004unsafe impl DeviceRepr for PublicationRange {}
5005unsafe impl DeviceRepr for PublicationHeader {}
5006unsafe impl DeviceRepr for PublicationControl {}
5007unsafe impl DeviceRepr for PublicationBank {}
5008unsafe impl DeviceRepr for PublicationRoleCount {}
5009unsafe impl DeviceRepr for PublicationContract {}
5010unsafe impl DeviceRepr for PendingContinuation {}
5011unsafe impl DeviceRepr for ModelUpdateBinding {}
5012unsafe impl DeviceRepr for ModelUpdateEvidenceSource {}
5013unsafe impl DeviceRepr for ModelForwardSealInput {}
5014unsafe impl DeviceRepr for ModelForwardReceipt {}
5015unsafe impl DeviceRepr for PublicationCommand {}
5016unsafe impl DeviceRepr for PublicationDeliveryInput {}
5017unsafe impl DeviceRepr for AcknowledgementQueueHeader {}
5018unsafe impl DeviceRepr for AcknowledgementEntry {}
5019unsafe impl DeviceRepr for PublicationLease {}
5020unsafe impl DeviceRepr for SemanticTensorLayout {}
5021// SAFETY: padding-free C records containing initialized u64 values only.
5022unsafe impl DeviceRepr for TensorLayoutTableHeader {}
5023unsafe impl DeviceRepr for SemanticActiveRow {}
5024unsafe impl DeviceRepr for CompletionCoverage {}
5025unsafe impl DeviceRepr for RawFeedbackRecord {}
5026unsafe impl DeviceRepr for AttemptReceipt {}
5027unsafe impl DeviceRepr for IntentQueueHeader {}
5028unsafe impl DeviceRepr for IntentEntry {}
5029unsafe impl DeviceRepr for TokenProvenance {}
5030
5031const _: () = assert!(size_of::<SourceSlot>() == 64);
5032const _: () = assert!(size_of::<PublicationStorageEntry>() == 24);
5033const _: () = assert!(size_of::<PublicationRange>() == 128);
5034const _: () = assert!(size_of::<PublicationHeader>() == 488);
5035const _: () = assert!(size_of::<PublicationControl>() == 144);
5036const _: () = assert!(size_of::<PublicationBank>() == 50360);
5037const _: () = assert!(size_of::<PublicationRoleCount>() == 16);
5038const _: () = assert!(size_of::<SemanticModelContractLayout>() == 48);
5039const _: () = assert!(size_of::<PublicationContract>() == 272);
5040const _: () = assert!(size_of::<SemanticTextRow>() == 16);
5041const _: () = assert!(size_of::<TextBinding>() == 24);
5042const _: () = assert!(size_of::<ModelUpdateBinding>() == 32);
5043const _: () = assert!(size_of::<ModelUpdateEvidenceSource>() == 48);
5044const _: () = assert!(size_of::<ModelForwardSealInput>() == 32);
5045const _: () = assert!(size_of::<ModelForwardReceipt>() == 232);
5046const _: () = assert!(size_of::<ModelForwardReceiptInputs>() == 128);
5047const _: () = assert!(size_of::<PublicationCommand>() == 24);
5048const _: () = assert!(size_of::<PublicationDeliveryInput>() == 88);
5049const _: () = assert!(size_of::<PublicationLease>() == 88);
5050const _: () = assert!(size_of::<SemanticTensorLayout>() == 112);
5051const _: () = assert!(size_of::<TensorLayoutTableHeader>() == 32);
5052const _: () = assert!(size_of::<SemanticActiveRow>() == 32);
5053const _: () = assert!(size_of::<CompletionCoverage>() == 360);
5054const _: () = assert!(size_of::<RawFeedbackRecord>() == 384);
5055const _: () = assert!(size_of::<AttemptReceipt>() == 352);
5056const _: () = assert!(size_of::<IntentQueueHeader>() == 88);
5057const _: () = assert!(size_of::<AcknowledgementQueueHeader>() == 72);
5058const _: () = assert!(size_of::<AcknowledgementEntry>() == 136);
5059const _: () = assert!(size_of::<IntentEntry>() == 344);
5060const _: () = assert!(size_of::<TokenProvenance>() == 184);
5061
5062#[derive(Clone)]
5063enum PublicationPayload {
5064    Metadata(Vec<u8>),
5065    Tensor(PreparedSemanticTensor),
5066    Uncomputed,
5067}
5068
5069struct PublicationAllocationPlan {
5070    role: u64,
5071    index: u64,
5072    capacity: usize,
5073    length: usize,
5074    logical_begin: u64,
5075    logical_end: u64,
5076    payload: PublicationPayload,
5077}
5078
5079/// One reachable range of a cold publication material. Allocation capacity is
5080/// retained for future appends; bytes outside the sealed extent are not exported.
5081#[derive(Clone)]
5082struct PublicationMaterialRange {
5083    range: PublicationRange,
5084    capacity: usize,
5085    bytes: Vec<u8>,
5086}
5087
5088/// Original non-tensor feedback material from a completed acquired step.
5089/// `identity` is its native range seal, not SHA-256 of `bytes` alone. Raw slots
5090/// (role 15), statement bytes (16) and provenance records (17) stay separate;
5091/// encoded feature tensors are not a replacement for any of these records.
5092pub struct SemanticFeedbackRecordMaterial {
5093    pub role: SemanticStateRole,
5094    pub index: u64,
5095    pub generation: u64,
5096    pub capacity_bytes: u64,
5097    pub logical_begin: u64,
5098    pub logical_end: u64,
5099    pub identity: Identity256,
5100    pub bytes: Vec<u8>,
5101}
5102
5103/// Canonical native witnesses retained by one actually completed step.
5104/// The identity names the retained native owner and is deliberately independent
5105/// of the canonical bytes hash recorded by downstream closure storage.
5106#[cfg(feature = "semantic-policy")]
5107#[derive(Clone)]
5108pub struct SemanticCompletedStepWitnessMaterial {
5109    pub identity: Identity256,
5110    pub bytes: Vec<u8>,
5111}
5112
5113#[cfg(feature = "semantic-policy")]
5114pub struct SemanticCompletedModelCarrierMaterial {
5115    pub numerical_realization: SemanticCompletedStepWitnessMaterial,
5116    pub logits: SemanticCompletedStepWitnessMaterial,
5117    pub random_state: SemanticCompletedStepWitnessMaterial,
5118}
5119
5120/// One exact categorical decision and the native closure materials needed to
5121/// replay its probability law and selected-score VJP without parsing a private
5122/// device ABI.
5123#[cfg(feature = "semantic-policy")]
5124#[derive(Clone)]
5125pub struct SemanticCompletedActionComponentMaterial {
5126    pub ordinal: u32,
5127    pub null: bool,
5128    pub choice: u32,
5129    pub legal_count: u32,
5130    pub active_count: u32,
5131    pub probability_numerator: [u64; 3],
5132    pub probability_denominator: [u64; 3],
5133    pub importance_denominator: [u64; 3],
5134    pub cumulative_mass_below: [u64; 3],
5135    pub cdf_start: u64,
5136    pub cdf_end: u64,
5137    pub mass: u64,
5138    pub selected_rank: u32,
5139    pub draw: u64,
5140    pub key: [u32; 2],
5141    pub counter: [u32; 4],
5142    pub final_mask: SemanticCompletedStepWitnessMaterial,
5143    pub pwl_cell: SemanticCompletedStepWitnessMaterial,
5144    pub active_set: SemanticCompletedStepWitnessMaterial,
5145    pub vjp: SemanticCompletedStepWitnessMaterial,
5146    pub component_receipt: SemanticCompletedStepWitnessMaterial,
5147    pub hard_decode_receipt: Option<SemanticCompletedStepWitnessMaterial>,
5148}
5149
5150/// Exact decoded choices and native admission receipts for one learned lane.
5151#[cfg(feature = "semantic-policy")]
5152#[derive(Clone)]
5153pub struct SemanticCompletedActionLaneMaterial {
5154    /// Exact non-NULL learned text actions as (original source slot, token).
5155    pub text_actions: Vec<(u32, u32)>,
5156    pub edit_actions: [[u32; 18]; 2],
5157    pub admitted: bool,
5158    pub refusal_reason: Option<&'static str>,
5159    pub admission: SemanticCompletedStepWitnessMaterial,
5160    pub hard_decode_receipts: [SemanticCompletedStepWitnessMaterial; 2],
5161}
5162
5163/// One actual native structural insertion attempt, including a duplicate
5164/// attachment. The lane verdict is independent of winner selection.
5165#[cfg(feature = "semantic-policy")]
5166#[derive(Clone)]
5167pub struct SemanticCompletedTheoryDeltaMaterial {
5168    pub kind: &'static str,
5169    pub delta: SemanticCompletedStepWitnessMaterial,
5170    pub theory_generation: Identity256,
5171    pub verdict: &'static str,
5172    pub evidence: SemanticCompletedStepWitnessMaterial,
5173    pub lane: u32,
5174    pub slot: u32,
5175}
5176
5177/// Terminal native result for one learned lane of a completed task ground.
5178/// A refusal never invents query results for a request that was not executed.
5179#[cfg(feature = "semantic-policy")]
5180#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5181pub enum SemanticCompletedLaneOutcomeMaterial {
5182    Executed([crate::SemanticTruth; 3]),
5183    Refused(SemanticTaskRefusal),
5184}
5185
5186/// Typed semantic ground retained by the same completed Proposal owner as the
5187/// action projection. Learned attempted requests remain in `lanes`; this value
5188/// records their terminal execution results without creating a replay path.
5189#[cfg(feature = "semantic-policy")]
5190#[derive(Clone)]
5191pub struct SemanticCompletedTaskGroundMaterial {
5192    pub witness: SemanticCompletedStepWitnessMaterial,
5193    /// Original six admitted coefficients and their finite signed return bound.
5194    pub scoring_law: SemanticCompletedStepWitnessMaterial,
5195    pub scoring: SemanticTaskScoring,
5196    pub return_bound: i64,
5197    pub structural_cost: SemanticStructuralCostDescriptor,
5198    pub task_identity: Identity256,
5199    pub content: SemanticTaskContentIdentity,
5200    pub goal: SemanticTaskGoalWitness,
5201    pub priority_levels: Vec<SemanticTaskPriorityLevel>,
5202    pub base: SemanticPublishedIdentity,
5203    pub expected_truth: [crate::SemanticTruth; 3],
5204    pub facts: [SemanticTaskFacts; 3],
5205    pub base_truth: [crate::SemanticTruth; 3],
5206    pub lane_outcomes: [SemanticCompletedLaneOutcomeMaterial; 2],
5207}
5208
5209/// A minimal learned lane that is genuinely decisive for the bound semantic
5210/// goal. Presence is the edit-supervision membership decision; selection does
5211/// not depend on the policy winner, return, or an admission-only flag.
5212#[cfg(feature = "semantic-policy")]
5213#[derive(Clone)]
5214pub struct SemanticCompletedEditSolutionMaterial {
5215    pub witness: SemanticCompletedStepWitnessMaterial,
5216    pub lane: u64,
5217    pub component_begin: u64,
5218    pub component_end: u64,
5219    pub structural_delta: SemanticTransitionWork,
5220    pub resulting_state_receipt: SemanticCompletedStepWitnessMaterial,
5221}
5222
5223/// Cold typed projection of one completed Proposal action. All byte-backed
5224/// children retain the same owner identity and are observations, not authority.
5225#[cfg(feature = "semantic-policy")]
5226pub struct SemanticCompletedActionProjectionMaterial {
5227    pub owner: SemanticCompletedStepWitnessMaterial,
5228    /// Original cold parent prefill only; later and restored parents have no
5229    /// stage-owned input/output witness to export.
5230    pub initial_prefill: Option<SemanticCompletedStepWitnessMaterial>,
5231    /// This action's own late pre-action checkpoint reference, sealed against
5232    /// retained custody. Never present alongside an initial-prefill child.
5233    pub pre_action_checkpoint: Option<SemanticCompletedStepWitnessMaterial>,
5234    /// Exact cold-exported predecessor root when its native digest still matches
5235    /// this Proposal's acquired parent. Later changed roots are not invented.
5236    pub world_root: Option<SemanticCompletedStepWitnessMaterial>,
5237    pub schema_generation: SemanticCompletedStepWitnessMaterial,
5238    pub action_law: SemanticCompletedStepWitnessMaterial,
5239    pub edit_codebook: SemanticCompletedStepWitnessMaterial,
5240    pub roster: SemanticCompletedStepWitnessMaterial,
5241    /// Original pre-draw physical bounds and their native model/profile binding.
5242    /// Non-actor actions and models without a physical roster have no certificate.
5243    pub estimator_bound: Option<SemanticCompletedStepWitnessMaterial>,
5244    /// Native digest of the semantic root acquired by this Proposal.
5245    pub predecessor_semantic_root_digest: Identity256,
5246    pub predecessor: SemanticPublishedIdentity,
5247    pub successor: SemanticPublishedIdentity,
5248    pub proposal: u64,
5249    pub stream_serial: u64,
5250    pub family_id: u64,
5251    pub action_law_generation: u64,
5252    pub model_generation: u64,
5253    pub winner: u64,
5254    pub actor_eligible: bool,
5255    pub total_return_bits: u64,
5256    pub batch_root: Identity256,
5257    pub batch_receipt: SemanticCompletedStepWitnessMaterial,
5258    pub result: SemanticCompletedStepWitnessMaterial,
5259    pub action_rng_base: SemanticCompletedStepWitnessMaterial,
5260    pub action_rng_successor: SemanticCompletedStepWitnessMaterial,
5261    pub base_logical_state: SemanticCompletedStepWitnessMaterial,
5262    pub successor_logical_state: SemanticCompletedStepWitnessMaterial,
5263    pub slot_zero_admission: SemanticCompletedStepWitnessMaterial,
5264    pub lanes: [SemanticCompletedActionLaneMaterial; 2],
5265    pub theory_deltas: Vec<SemanticCompletedTheoryDeltaMaterial>,
5266    pub components: Vec<SemanticCompletedActionComponentMaterial>,
5267    pub task_ground: SemanticCompletedTaskGroundMaterial,
5268    pub edit_solution: Option<SemanticCompletedEditSolutionMaterial>,
5269    pub attempt_receipt: SemanticCompletedStepWitnessMaterial,
5270}
5271
5272/// Cold capacity of every native material one original Proposal can export.
5273/// Counts deliberately precede digest deduplication and outcome selection.
5274#[cfg(feature = "semantic-policy")]
5275#[derive(Default)]
5276pub struct SemanticCompletedMaterialCapacity {
5277    pub material_count: usize,
5278    pub largest_material_bytes: usize,
5279    pub total_material_bytes: usize,
5280    /// Numerical realization, structural logits, and random state, in that order.
5281    pub carrier_bytes: [usize; 3],
5282    pub attempt_receipt_bytes: usize,
5283    pub publication_evidence_bytes: usize,
5284}
5285
5286#[cfg(feature = "semantic-policy")]
5287fn completed_material_extent(parts: &[usize]) -> Result<usize, SemanticTransitionError> {
5288    parts.iter().try_fold(0usize, |total, &bytes| {
5289        total.checked_add(bytes).ok_or_else(|| {
5290            publication_input_error("completed material capacity exceeds host extent")
5291        })
5292    })
5293}
5294
5295#[cfg(feature = "semantic-policy")]
5296fn repeated_material_extent(count: usize, bytes: usize) -> Result<usize, SemanticTransitionError> {
5297    count
5298        .checked_mul(bytes)
5299        .ok_or_else(|| publication_input_error("completed material capacity exceeds host extent"))
5300}
5301
5302#[cfg(feature = "semantic-policy")]
5303impl SemanticCompletedMaterialCapacity {
5304    fn add(&mut self, bytes: usize) -> Result<(), SemanticTransitionError> {
5305        self.material_count = completed_material_extent(&[self.material_count, 1])?;
5306        self.total_material_bytes = completed_material_extent(&[self.total_material_bytes, bytes])?;
5307        self.largest_material_bytes = self.largest_material_bytes.max(bytes);
5308        Ok(())
5309    }
5310
5311    fn child(&mut self, kind: &[u8], payload: usize) -> Result<usize, SemanticTransitionError> {
5312        let bytes = completed_material_extent(&[
5313            b"XLOG-COMPLETED-ACTION-CHILD\0".len(),
5314            32 + 4 * size_of::<u64>(),
5315            kind.len(),
5316            payload,
5317        ])?;
5318        self.add(bytes)?;
5319        Ok(bytes)
5320    }
5321}
5322
5323impl PublicationMaterialRange {
5324    fn into_feedback_record(
5325        self,
5326    ) -> Result<SemanticFeedbackRecordMaterial, SemanticTransitionError> {
5327        if !matches!(self.range.role, 15..=17)
5328            || self.range.generation != 1
5329            || self.range.length_bytes != self.bytes.len() as u64
5330            || self.bytes.is_empty()
5331            || self.bytes.len() > self.capacity
5332            || self.range.logical_begin != 0
5333            || (self.range.role != 15 && self.range.logical_end != 0)
5334            || (self.range.role == 15
5335                && (!self
5336                    .bytes
5337                    .len()
5338                    .is_multiple_of(size_of::<RawFeedbackRecord>())
5339                    || self.range.logical_end
5340                        > (self.bytes.len() / size_of::<RawFeedbackRecord>()) as u64))
5341            || self.original_record_digest() != self.range.digest
5342        {
5343            return Err(SemanticTransitionError::ObservationMismatch);
5344        }
5345        Ok(SemanticFeedbackRecordMaterial {
5346            role: SemanticStateRole::from_code(self.range.role).expect("checked feedback role"),
5347            index: self.range.index,
5348            generation: self.range.generation,
5349            capacity_bytes: self.capacity as u64,
5350            logical_begin: self.range.logical_begin,
5351            logical_end: self.range.logical_end,
5352            identity: self.range.digest,
5353            bytes: self.bytes,
5354        })
5355    }
5356
5357    // Exact opaque-record branch of publication_content_view. Runtime words
5358    // must remain present here, including those normalized out of Hlogical.
5359    fn original_record_digest(&self) -> Identity256 {
5360        debug_assert!(!is_tensor_role(self.range.role));
5361        self.record_digest(&self.bytes)
5362    }
5363
5364    fn digest_prefix(&self) -> [u64; 16] {
5365        let mut prefix = [0u64; 16];
5366        prefix[..5].copy_from_slice(&[
5367            0x786c6f6772616e31,
5368            self.range.role,
5369            self.range.index,
5370            self.range.logical_begin,
5371            self.range.logical_end,
5372        ]);
5373        prefix
5374    }
5375
5376    fn record_digest(&self, bytes: &[u8]) -> Identity256 {
5377        let mut hash = Sha256::new();
5378        for word in self.digest_prefix() {
5379            hash.update(word.to_le_bytes());
5380        }
5381        hash.update(bytes);
5382        Identity256::from_bytes(hash.finalize().into())
5383    }
5384
5385    /// Cold form of publication_content_view for the original cache roster.
5386    /// This traverses the same logical coordinates as CUDA, not storage padding.
5387    fn cache_projection(
5388        &self,
5389        layout: SemanticTensorLayout,
5390    ) -> Result<SemanticPublicationTensorProjection, SemanticTransitionError> {
5391        tensor_layout_bytes(&layout)?;
5392        if !matches!(layout.role, 4..=13)
5393            || (layout.role, layout.index) != (self.range.role, self.range.index)
5394            || layout.strides_bytes[..layout.rank as usize]
5395                .iter()
5396                .any(|stride| !stride.is_multiple_of(layout.element_bytes))
5397        {
5398            return Err(publication_input_error(
5399                "cache material has another tensor layout",
5400            ));
5401        }
5402        let mut dimensions = layout.dimensions;
5403        if layout.logical_axis != u64::MAX {
5404            let axis = layout.logical_axis as usize;
5405            dimensions[axis] = self.range.logical_end - self.range.logical_begin;
5406            if dimensions[axis] > layout.dimensions[axis] {
5407                return Err(publication_input_error(
5408                    "cache interval exceeds its original layout",
5409                ));
5410            }
5411        }
5412        let cells =
5413            dimensions[..layout.rank as usize]
5414                .iter()
5415                .try_fold(1u64, |cells, &dimension| {
5416                    cells
5417                        .checked_mul(dimension)
5418                        .ok_or(SemanticTransitionError::GenerationExhausted)
5419                })?;
5420        let length = cells
5421            .checked_mul(layout.element_bytes)
5422            .and_then(|bytes| usize::try_from(bytes).ok())
5423            .filter(|&bytes| bytes <= self.bytes.len())
5424            .ok_or(SemanticTransitionError::ObservationMismatch)?;
5425        let mut logical_bytes = Vec::with_capacity(length);
5426        for cell in 0..cells {
5427            let mut coordinate = cell;
5428            let mut offset = 0u64;
5429            for axis in (0..layout.rank as usize).rev() {
5430                let at = coordinate % dimensions[axis];
5431                coordinate /= dimensions[axis];
5432                offset = at
5433                    .checked_mul(layout.strides_bytes[axis])
5434                    .and_then(|bytes| offset.checked_add(bytes))
5435                    .ok_or(SemanticTransitionError::GenerationExhausted)?;
5436            }
5437            let start = usize::try_from(offset)
5438                .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
5439            let end = offset
5440                .checked_add(layout.element_bytes)
5441                .and_then(|bytes| usize::try_from(bytes).ok())
5442                .ok_or(SemanticTransitionError::ObservationMismatch)?;
5443            logical_bytes.extend_from_slice(
5444                self.bytes
5445                    .get(start..end)
5446                    .ok_or(SemanticTransitionError::ObservationMismatch)?,
5447            );
5448        }
5449        let mut prefix = self.digest_prefix();
5450        prefix[5..9].copy_from_slice(&[
5451            layout.element_bytes,
5452            layout.scalar_type,
5453            layout.rank,
5454            layout.logical_axis,
5455        ]);
5456        prefix[9..13].copy_from_slice(&dimensions);
5457        let mut hash = Sha256::new();
5458        for word in prefix {
5459            hash.update(word.to_le_bytes());
5460        }
5461        hash.update(&logical_bytes);
5462        if Identity256::from_bytes(hash.finalize().into()) != self.range.digest {
5463            return Err(publication_input_error(
5464                "cache bytes differ from their original native seal",
5465            ));
5466        }
5467        Ok(SemanticPublicationTensorProjection {
5468            layout,
5469            capacity_bytes: self.capacity as u64,
5470            logical_begin: self.range.logical_begin,
5471            logical_end: self.range.logical_end,
5472            identity: self.range.digest,
5473            logical_bytes,
5474        })
5475    }
5476
5477    fn attempt(&self) -> Result<AttemptReceipt, SemanticTransitionError> {
5478        if self.range.role != 33 || self.bytes.len() != size_of::<AttemptReceipt>() {
5479            return Err(publication_input_error(
5480                "replay evidence requires the whole native attempt receipt",
5481            ));
5482        }
5483        // SAFETY: the checked, padding-free ABI contains only integer/digest fields.
5484        Ok(unsafe { std::ptr::read_unaligned(self.bytes.as_ptr().cast::<AttemptReceipt>()) })
5485    }
5486
5487    // Exact PublicationLogicalBytes normalization for the publication-only
5488    // records and completion coverage. This is a cold comparison, never a
5489    // substitute for the actual device publication seals.
5490    fn logical_record_digest(&self) -> Result<Identity256, SemanticTransitionError> {
5491        let mut bytes = self.bytes.clone();
5492        match self.range.role {
5493            14 | 33 => {
5494                let (extent, first, last, tail) = if self.range.role == 14 {
5495                    (size_of::<CompletionCoverage>(), 1, 5, 41)
5496                } else {
5497                    (size_of::<AttemptReceipt>(), 1, 6, 39)
5498                };
5499                if bytes.len() != extent {
5500                    return Err(publication_input_error(
5501                        "replay record has another native ABI extent",
5502                    ));
5503                }
5504                bytes[first * 8..(last + 1) * 8].fill(0);
5505                bytes[tail * 8..].fill(0);
5506            }
5507            30 => {
5508                if bytes.len() < size_of::<IntentQueueHeader>() {
5509                    return Err(publication_input_error(
5510                        "replay intent queue omits its native header",
5511                    ));
5512                }
5513                // SAFETY: the checked prefix is an all-integer, padding-free ABI.
5514                let header =
5515                    unsafe { std::ptr::read_unaligned(bytes.as_ptr().cast::<IntentQueueHeader>()) };
5516                if header.abi != 1
5517                    || header.count > header.capacity
5518                    || header
5519                        .count
5520                        .checked_mul(size_of::<IntentEntry>() as u64)
5521                        .and_then(|n| n.checked_add(size_of::<IntentQueueHeader>() as u64))
5522                        != Some(bytes.len() as u64)
5523                {
5524                    return Err(publication_input_error(
5525                        "replay intent queue differs from its exact native extent",
5526                    ));
5527                }
5528                for entry in bytes[size_of::<IntentQueueHeader>()..]
5529                    .as_chunks_mut::<{ size_of::<IntentEntry>() }>()
5530                    .0
5531                {
5532                    entry[30 * 8..35 * 8].fill(0);
5533                }
5534            }
5535            27 | 28 | 31 | 32 => {}
5536            _ => {
5537                return Err(publication_input_error(
5538                    "record is not a native replay comparison record",
5539                ))
5540            }
5541        }
5542        Ok(self.record_digest(&bytes))
5543    }
5544
5545    fn encode_into(&self, bytes: &mut Vec<u8>) -> Result<(), SemanticTransitionError> {
5546        material_bytes(bytes, &publication_abi_bytes(&[self.range]))
5547            .map_err(SemanticTransitionError::Semantic)?;
5548        material_u64(bytes, self.capacity as u64);
5549        material_bytes(bytes, &self.bytes).map_err(SemanticTransitionError::Semantic)
5550    }
5551
5552    fn decode_from(
5553        reader: &mut SemanticMaterialReader<'_>,
5554    ) -> Result<Self, SemanticTransitionError> {
5555        // SAFETY: the range ABI contains only integer/digest fields.
5556        let range = unsafe { publication_material_record::<PublicationRange>(reader)? };
5557        let capacity = usize::try_from(reader.u64().map_err(SemanticTransitionError::Semantic)?)
5558            .map_err(|_| {
5559                publication_input_error("publication material capacity exceeds host extent")
5560            })?;
5561        let bytes = reader
5562            .bytes()
5563            .map_err(SemanticTransitionError::Semantic)?
5564            .to_vec();
5565        Ok(Self {
5566            range,
5567            capacity,
5568            bytes,
5569        })
5570    }
5571}
5572
5573// publication_fold hashes digest bytes followed by two little-endian ABI words
5574// and the content digest. Identity256 preserves the CUDA SHA output byte order.
5575fn publication_fold_digest(
5576    digest: Identity256,
5577    role: u64,
5578    index: u64,
5579    content: Identity256,
5580) -> Identity256 {
5581    let mut hash = Sha256::new();
5582    hash.update(digest.as_bytes());
5583    hash.update(role.to_le_bytes());
5584    hash.update(index.to_le_bytes());
5585    hash.update(content.as_bytes());
5586    Identity256::from_bytes(hash.finalize().into())
5587}
5588
5589fn publication_action_receipts_digest(
5590    codebook: &PublicationMaterialRange,
5591    receipts: &[SemanticTransitionReceipt],
5592) -> Result<Identity256, SemanticTransitionError> {
5593    // publication_logical_codebook_digest and PublicationActionReceiptBytes:
5594    // owner/slot/generation and the runtime admission binding are audit data.
5595    if codebook.range.role != 48 {
5596        return Err(publication_input_error(
5597            "replay action codebook has another native extent",
5598        ));
5599    }
5600    publication_action_receipts_digest_bytes(&codebook.bytes, receipts)
5601}
5602
5603fn publication_action_receipts_digest_bytes(
5604    bytes: &[u8],
5605    receipts: &[SemanticTransitionReceipt],
5606) -> Result<Identity256, SemanticTransitionError> {
5607    if bytes.len() < 25 * 8 || !bytes.len().is_multiple_of(8) {
5608        return Err(publication_input_error(
5609            "replay action codebook has another native extent",
5610        ));
5611    }
5612    let word =
5613        |index: usize| u64::from_le_bytes(bytes[index * 8..(index + 1) * 8].try_into().unwrap());
5614    let (offset, length) = (word(8), word(9));
5615    if offset % 8 != 0
5616        || offset > bytes.len() as u64
5617        || length > bytes.len() as u64 - offset
5618        || (offset + length).div_ceil(8) != (bytes.len() / 8) as u64
5619    {
5620        return Err(publication_input_error(
5621            "replay action codebook omits its exact statement payload",
5622        ));
5623    }
5624    let mut hash = Sha256::new();
5625    hash.update(b"xlog.semantic.logical-codebooks.v1\0");
5626    hash.update(CATALOGUE_DIGEST);
5627    hash.update(((bytes.len() / 8) as u64).to_le_bytes());
5628    for (index, bytes) in bytes.as_chunks::<8>().0.iter().enumerate() {
5629        hash.update(if matches!(index, 14..=16 | 21..=24) {
5630            &[0; 8]
5631        } else {
5632            bytes
5633        });
5634    }
5635    let binding = Identity256::from_bytes(hash.finalize().into());
5636    let mut hash = Sha256::new();
5637    for receipt in receipts {
5638        let mut normalized = *receipt;
5639        if normalized.catalogue_generation == CATALOGUE_GENERATION {
5640            normalized.admission_binding = binding;
5641        }
5642        hash.update(publication_abi_bytes(&[normalized]));
5643    }
5644    Ok(Identity256::from_bytes(hash.finalize().into()))
5645}
5646
5647fn publication_semantic_receipts_digest(receipts: &[[u64; 42]; 7]) -> Identity256 {
5648    let mut hash = Sha256::new();
5649    for receipt in receipts {
5650        for (index, &word) in receipt.iter().enumerate() {
5651            hash.update(
5652                if matches!(index, 3..=12 | 34..=41) {
5653                    0
5654                } else {
5655                    word
5656                }
5657                .to_le_bytes(),
5658            );
5659        }
5660    }
5661    Identity256::from_bytes(hash.finalize().into())
5662}
5663
5664fn publication_action_batch_root(batch: &SemanticActionBatchReceipt) -> Identity256 {
5665    Identity256::from_bytes(Sha256::digest(publication_abi_bytes(&[*batch])).into())
5666}
5667
5668const REPLAY_EVIDENCE_ROLES: [u64; 6] = [27, 28, 30, 31, 32, 33];
5669const REPLAY_EVIDENCE_MAGIC: &[u8] = b"XLOG-REPLAY-EVIDENCE\0";
5670const REPLAY_PROVENANCE_MAGIC: &[u8] = b"XLOG-REPLAY-PROVENANCE\0";
5671
5672fn encode_publication_identity(bytes: &mut Vec<u8>, identity: SemanticPublishedIdentity) {
5673    bytes.extend_from_slice(identity.instance.as_bytes());
5674    material_u64(bytes, identity.word);
5675    bytes.extend_from_slice(identity.logical_digest.as_bytes());
5676    bytes.extend_from_slice(identity.state_digest.as_bytes());
5677}
5678
5679#[cfg(feature = "semantic-policy")]
5680fn completed_action_child_material(
5681    owner: Identity256,
5682    kind: &[u8],
5683    ordinal: u64,
5684    payload: &[u8],
5685) -> SemanticCompletedStepWitnessMaterial {
5686    let mut owner_binding = Vec::new();
5687    owner_binding.extend_from_slice(b"xlog.completed-action-child.v1\0");
5688    owner_binding.extend_from_slice(owner.as_bytes());
5689    material_u64(&mut owner_binding, kind.len() as u64);
5690    owner_binding.extend_from_slice(kind);
5691    material_u64(&mut owner_binding, ordinal);
5692    let identity = Identity256::from_bytes(Sha256::digest(&owner_binding).into());
5693
5694    let mut bytes = Vec::new();
5695    bytes.extend_from_slice(b"XLOG-COMPLETED-ACTION-CHILD\0");
5696    material_u64(&mut bytes, 1);
5697    bytes.extend_from_slice(owner.as_bytes());
5698    material_u64(&mut bytes, kind.len() as u64);
5699    bytes.extend_from_slice(kind);
5700    material_u64(&mut bytes, ordinal);
5701    material_u64(&mut bytes, payload.len() as u64);
5702    bytes.extend_from_slice(payload);
5703    SemanticCompletedStepWitnessMaterial { identity, bytes }
5704}
5705
5706#[cfg(feature = "semantic-policy")]
5707fn encode_completed_component_receipt(bytes: &mut Vec<u8>, receipt: SemanticTransitionReceipt) {
5708    material_u64(bytes, receipt.proposal);
5709    material_u64(bytes, receipt.catalogue_generation);
5710    bytes.extend_from_slice(receipt.catalogue_digest.as_bytes());
5711    bytes.extend_from_slice(receipt.admission_binding.as_bytes());
5712    for value in [
5713        receipt.ordinal,
5714        receipt.lane,
5715        receipt.slot,
5716        receipt.field,
5717        receipt.kind,
5718        receipt.choice,
5719        receipt.legal_count,
5720        receipt.active_count,
5721        receipt.selected_rank,
5722    ] {
5723        material_u64(bytes, value as u64);
5724    }
5725    for value in receipt.key {
5726        material_u64(bytes, value as u64);
5727    }
5728    for value in receipt.counter {
5729        material_u64(bytes, value as u64);
5730    }
5731    for value in receipt.random_words {
5732        material_u64(bytes, value as u64);
5733    }
5734    for value in [
5735        receipt.draw,
5736        receipt.cdf_start,
5737        receipt.cdf_end,
5738        receipt.mass,
5739    ] {
5740        material_u64(bytes, value);
5741    }
5742    for limbs in [
5743        receipt.p,
5744        receipt.q,
5745        receipt.factor_denominator,
5746        receipt.cumulative_mass_below,
5747    ] {
5748        for value in limbs {
5749            material_u64(bytes, value);
5750        }
5751    }
5752    material_u64(bytes, receipt.active_fields as u64);
5753    material_u64(bytes, receipt.null_fields as u64);
5754}
5755
5756#[cfg(feature = "semantic-policy")]
5757fn completed_receipt_material(
5758    owner: Identity256,
5759    kind: &[u8],
5760    ordinal: u64,
5761    receipt: &[u64; 42],
5762) -> SemanticCompletedStepWitnessMaterial {
5763    let mut payload = Vec::new();
5764    for value in receipt {
5765        material_u64(&mut payload, *value);
5766    }
5767    completed_action_child_material(owner, kind, ordinal, &payload)
5768}
5769
5770#[expect(
5771    clippy::too_many_arguments,
5772    reason = "the native rule receipt binds task, lane, slot, current edit, and prior edit independently"
5773)]
5774fn validated_rule_receipt(
5775    codebooks: &ActionCodebooks,
5776    program: &crate::SemanticProgramAdmission,
5777    task_identity: Identity256,
5778    lane: usize,
5779    slot: usize,
5780    choices: &[u32; 18],
5781    previous_choices: Option<&[u32; 18]>,
5782    receipt: &[u64; 42],
5783) -> Result<
5784    (
5785        SemanticDecodedRuleInsertion,
5786        Option<crate::SemanticProgramRule>,
5787    ),
5788    SemanticTransitionError,
5789> {
5790    let mismatch = || SemanticTransitionError::ObservationMismatch;
5791    if lane >= 2 || slot >= 2 {
5792        return Err(mismatch());
5793    }
5794    let decoded = codebooks.decoded_rule_insertion(program, choices)?;
5795    let previous = match previous_choices {
5796        Some(prior) if prior[0] == 1 && prior[1] == 2 => {
5797            Some(codebooks.decoded_rule_insertion(program, prior)?.rule)
5798        }
5799        Some(prior) if prior.iter().all(|&choice| choice == 0) => None,
5800        None => None,
5801        _ => return Err(mismatch()),
5802    };
5803    let previous_fields = previous.map(semantic_program_rule_words).unwrap_or([0; 10]);
5804    if receipt[0] != 0
5805        || receipt[1] != 3
5806        || receipt[2] != lane as u64 + 1
5807        || receipt[3] != slot as u64
5808        || receipt[4..8] != identity_words(*task_identity.as_bytes())
5809        || receipt[8..12] != identity_words(*codebooks.binding.digest.as_bytes())
5810        || receipt[12..22] != semantic_program_rule_words(decoded.rule)
5811        || receipt[22] != program.initial_facts.len() as u64
5812        || receipt[23] != program.initial_rules.len() as u64
5813        || receipt[24] != u64::from(previous.is_some())
5814        || receipt[25..35] != previous_fields
5815        || receipt[35..].iter().any(|&word| word != 0)
5816    {
5817        return Err(mismatch());
5818    }
5819    Ok((decoded, previous))
5820}
5821
5822#[cfg(feature = "semantic-policy")]
5823#[expect(
5824    clippy::too_many_arguments,
5825    reason = "one delta binds independent native owner, source, decode, and admission receipts"
5826)]
5827fn completed_theory_delta_for_slot(
5828    codebooks: &ActionCodebooks,
5829    admission: &SemanticAdmission,
5830    program: Option<&crate::SemanticProgramAdmission>,
5831    task_identity: Identity256,
5832    owner: Identity256,
5833    predecessor_semantic_root_digest: Identity256,
5834    lane: usize,
5835    slot: usize,
5836    choices: &[u32; 18],
5837    previous_choices: Option<&[u32; 18]>,
5838    hard_decode: &[u64; 42],
5839    lane_admission: &[u64; 42],
5840    component_receipts: &[SemanticTransitionReceipt],
5841    lane_refusal: u64,
5842) -> Result<Option<SemanticCompletedTheoryDeltaMaterial>, SemanticTransitionError> {
5843    if lane >= 2
5844        || slot >= 2
5845        || component_receipts.len() != 18
5846        || hard_decode[0] != 0
5847        || hard_decode[1] > 3
5848        || lane_refusal > 4
5849    {
5850        return Err(SemanticTransitionError::ObservationMismatch);
5851    }
5852    if hard_decode[1] == 0 {
5853        if choices[0] == 1 && choices[1] == 2 {
5854            return Err(SemanticTransitionError::ObservationMismatch);
5855        }
5856        return Ok(None);
5857    }
5858    if hard_decode[1] == 3 {
5859        let program = program.ok_or(SemanticTransitionError::ObservationMismatch)?;
5860        let (decoded, previous) = validated_rule_receipt(
5861            codebooks,
5862            program,
5863            task_identity,
5864            lane,
5865            slot,
5866            choices,
5867            previous_choices,
5868            hard_decode,
5869        )?;
5870        let previous_fields = previous.map(semantic_program_rule_words).unwrap_or([0; 10]);
5871        let program_binding = ActionCodebooks::program_binding(program);
5872        let theory_generation = if previous.is_some() {
5873            let mut hash = Sha256::new();
5874            hash.update(b"xlog.semantic.program-theory.v1\0");
5875            hash.update(program_binding.as_bytes());
5876            for word in previous_fields {
5877                hash.update(word.to_le_bytes());
5878            }
5879            Identity256::from_bytes(hash.finalize().into())
5880        } else {
5881            program_binding
5882        };
5883        let ordinal = (lane * 2 + slot) as u64;
5884        let delta =
5885            completed_action_child_material(owner, b"theory-rule-delta", ordinal, &decoded.bytes);
5886        let mut payload = Vec::new();
5887        payload.extend_from_slice(theory_generation.as_bytes());
5888        payload.extend_from_slice(task_identity.as_bytes());
5889        material_u64(&mut payload, lane as u64 + 1);
5890        material_u64(&mut payload, slot as u64);
5891        material_u64(&mut payload, lane_refusal);
5892        for receipt in [hard_decode, lane_admission] {
5893            for &word in receipt {
5894                material_u64(&mut payload, word);
5895            }
5896        }
5897        for receipt in component_receipts {
5898            encode_completed_component_receipt(&mut payload, *receipt);
5899        }
5900        let evidence = completed_action_child_material(
5901            owner,
5902            b"theory-rule-delta-evidence",
5903            ordinal,
5904            &payload,
5905        );
5906        return Ok(Some(SemanticCompletedTheoryDeltaMaterial {
5907            kind: "rule",
5908            delta,
5909            theory_generation,
5910            verdict: if lane_refusal == 0 {
5911                "accepted"
5912            } else {
5913                "rejected"
5914            },
5915            evidence,
5916            lane: lane as u32 + 1,
5917            slot: slot as u32,
5918        }));
5919    }
5920    if program.is_some() {
5921        return Err(SemanticTransitionError::ObservationMismatch);
5922    }
5923    let decoded = codebooks
5924        .decoded_support_insertion(admission, choices)?
5925        .ok_or(SemanticTransitionError::ObservationMismatch)?;
5926    if hard_decode[20..24] != identity_words(*decoded.statement.as_bytes())
5927        || hard_decode[24..28] != identity_words(*decoded.support.as_bytes())
5928    {
5929        return Err(SemanticTransitionError::ObservationMismatch);
5930    }
5931    let ordinal = (lane * 2 + slot) as u64;
5932    let delta = completed_action_child_material(owner, b"theory-delta", ordinal, &decoded.bytes);
5933    let mut payload = Vec::new();
5934    payload.extend_from_slice(predecessor_semantic_root_digest.as_bytes());
5935    material_u64(&mut payload, lane as u64 + 1);
5936    material_u64(&mut payload, slot as u64);
5937    material_u64(&mut payload, lane_refusal);
5938    material_u32(&mut payload, decoded.source_event);
5939    for reference in decoded.reconstruction {
5940        material_u32(&mut payload, reference);
5941    }
5942    for receipt in [hard_decode, lane_admission] {
5943        for &word in receipt {
5944            material_u64(&mut payload, word);
5945        }
5946    }
5947    for receipt in component_receipts {
5948        encode_completed_component_receipt(&mut payload, *receipt);
5949    }
5950    let evidence =
5951        completed_action_child_material(owner, b"theory-delta-evidence", ordinal, &payload);
5952    Ok(Some(SemanticCompletedTheoryDeltaMaterial {
5953        kind: "fact",
5954        delta,
5955        theory_generation: predecessor_semantic_root_digest,
5956        verdict: if lane_refusal == 0 {
5957            "accepted"
5958        } else {
5959            "rejected"
5960        },
5961        evidence,
5962        lane: lane as u32 + 1,
5963        slot: slot as u32,
5964    }))
5965}
5966
5967fn validate_program_query_receipts(
5968    program: &crate::SemanticProgramAdmission,
5969    task_identity: Identity256,
5970    codebooks: &ActionCodebooks,
5971    state: &DeviceState,
5972    edits: &[[[u32; 18]; 2]; 2],
5973) -> Result<(), SemanticTransitionError> {
5974    let mismatch = || SemanticTransitionError::ObservationMismatch;
5975    let expected_queries = 3 + state
5976        .task_evaluation
5977        .lane_refusal
5978        .iter()
5979        .filter(|&&refusal| refusal != 3 && refusal != 4)
5980        .count() as u64
5981        * 3;
5982    if state.binding_digest != codebooks.binding.digest
5983        || state.task_evaluation.query_count != expected_queries
5984        || state.task_evaluation.lane_refusal.contains(&1)
5985    {
5986        return Err(mismatch());
5987    }
5988    let mut inserted: [Vec<crate::SemanticProgramRule>; 2] = std::array::from_fn(|_| Vec::new());
5989    for (lane, actions) in edits.iter().enumerate() {
5990        for choices in actions {
5991            match (choices[0], choices[1]) {
5992                (0, 0) if choices[2..].iter().all(|&value| value == 0) => {}
5993                (1, 2) => {
5994                    inserted[lane].push(codebooks.decoded_rule_insertion(program, choices)?.rule)
5995                }
5996                _ => return Err(mismatch()),
5997            }
5998        }
5999    }
6000    let task_words = identity_words(*task_identity.as_bytes());
6001    let binding_words = identity_words(*codebooks.binding.digest.as_bytes());
6002    for slot in 0..3 {
6003        let rules: &[crate::SemanticProgramRule] =
6004            if slot == 0 { &[] } else { &inserted[slot - 1] };
6005        let receipts = &state.task_evaluation.query_receipts[slot];
6006        let facts = &state.task_evaluation.facts[slot];
6007        if slot != 0 && matches!(state.task_evaluation.lane_refusal[slot - 1], 3 | 4) {
6008            let work = state.work[slot - 1];
6009            if rules.is_empty()
6010                || receipts
6011                    .iter()
6012                    .any(|receipt| receipt.iter().any(|&word| word != 0))
6013                || facts.truth != [0; 3]
6014                || facts.correct != [0; 3]
6015                || facts.g != 0
6016                || facts.p != 0
6017                || facts.eligible != 0
6018                || work.edit_commands != rules.len() as u64
6019                || work.added_supports != 0
6020                || work.defined_truth_changes != 0
6021            {
6022                return Err(mismatch());
6023            }
6024            continue;
6025        }
6026        let metrics = &receipts[0][37..40];
6027        if metrics[1] > crate::semantic_program::RESIDENT_PROGRAM_FACT_CAPACITY as u64
6028            || metrics[2] > metrics[1]
6029            || facts.truth.iter().any(|&truth| truth > 1)
6030        {
6031            return Err(mismatch());
6032        }
6033        for (query, receipt) in receipts.iter().enumerate() {
6034            let mut expected = [0u64; 42];
6035            expected[1] = 0x5850524f47515545;
6036            expected[2] = facts.truth[query];
6037            expected[3] = slot as u64;
6038            expected[4] = query as u64;
6039            expected[5..9].copy_from_slice(&task_words);
6040            expected[9..13].copy_from_slice(&binding_words);
6041            expected[13] = rules.len() as u64;
6042            for (edit, rule) in rules.iter().enumerate() {
6043                expected[14 + edit * 10..24 + edit * 10]
6044                    .copy_from_slice(&semantic_program_rule_words(*rule));
6045            }
6046            let query_fact = program.queries[query];
6047            expected[34..37].copy_from_slice(&[
6048                u64::from(query_fact.predicate),
6049                u64::from(query_fact.first),
6050                u64::from(query_fact.second),
6051            ]);
6052            expected[37..40].copy_from_slice(metrics);
6053            expected[40] = program.initial_rules.len() as u64;
6054            expected[41] = program.initial_facts.len() as u64;
6055            if receipt != &expected {
6056                return Err(mismatch());
6057            }
6058        }
6059        if slot != 0 {
6060            let baseline = &state.task_evaluation.facts[0];
6061            let derived = metrics[2]
6062                .checked_sub(state.task_evaluation.query_receipts[0][0][39])
6063                .ok_or_else(mismatch)?;
6064            let truth_changes = facts
6065                .truth
6066                .iter()
6067                .zip(baseline.truth)
6068                .filter(|(current, original)| **current != *original)
6069                .count() as u64;
6070            let work = state.work[slot - 1];
6071            if work.edit_commands != rules.len() as u64
6072                || work.added_supports != derived
6073                || work.defined_truth_changes != truth_changes
6074            {
6075                return Err(mismatch());
6076            }
6077        }
6078    }
6079    Ok(())
6080}
6081
6082#[cfg(feature = "semantic-policy")]
6083fn completed_task_truths(
6084    facts: SemanticTaskFacts,
6085) -> Result<[crate::SemanticTruth; 3], SemanticTransitionError> {
6086    Ok([
6087        crate::SemanticTruth::from_bits(facts.truth[0])
6088            .map_err(SemanticTransitionError::Semantic)?,
6089        crate::SemanticTruth::from_bits(facts.truth[1])
6090            .map_err(SemanticTransitionError::Semantic)?,
6091        crate::SemanticTruth::from_bits(facts.truth[2])
6092            .map_err(SemanticTransitionError::Semantic)?,
6093    ])
6094}
6095
6096#[cfg(feature = "semantic-policy")]
6097fn encode_completed_task_facts(bytes: &mut Vec<u8>, facts: SemanticTaskFacts) {
6098    for value in facts.truth {
6099        material_u64(bytes, value);
6100    }
6101    for value in facts.correct {
6102        material_u64(bytes, value);
6103    }
6104    for value in [facts.g, facts.p, facts.c, facts.v as u64, facts.eligible] {
6105        material_u64(bytes, value);
6106    }
6107}
6108
6109#[cfg(feature = "semantic-policy")]
6110fn bind_completed_material(bytes: &mut Vec<u8>, material: &SemanticCompletedStepWitnessMaterial) {
6111    bytes.extend_from_slice(material.identity.as_bytes());
6112    bytes.extend_from_slice(&Sha256::digest(&material.bytes));
6113}
6114
6115#[cfg(feature = "semantic-policy")]
6116fn completed_logical_state_material(
6117    owner: Identity256,
6118    ordinal: u64,
6119    identity: SemanticPublishedIdentity,
6120) -> SemanticCompletedStepWitnessMaterial {
6121    let mut payload = Vec::new();
6122    encode_publication_identity(&mut payload, identity);
6123    let mut material = completed_action_child_material(owner, b"logical-state", ordinal, &payload);
6124    material.identity = identity.logical_digest;
6125    material
6126}
6127
6128#[cfg(feature = "semantic-policy")]
6129fn completed_rng_material(
6130    owner: Identity256,
6131    ordinal: u64,
6132    model_generation: u64,
6133    stream_serial: u64,
6134    family_id: u64,
6135    proposal: u64,
6136) -> SemanticCompletedStepWitnessMaterial {
6137    let mut payload = Vec::new();
6138    for value in [model_generation, stream_serial, family_id, proposal] {
6139        material_u64(&mut payload, value);
6140    }
6141    completed_action_child_material(owner, b"action-rng", ordinal, &payload)
6142}
6143
6144fn decode_publication_identity(
6145    reader: &mut SemanticMaterialReader<'_>,
6146) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
6147    let instance = Identity256::from_bytes(
6148        reader
6149            .take(32)
6150            .map_err(SemanticTransitionError::Semantic)?
6151            .try_into()
6152            .unwrap(),
6153    );
6154    let word = reader.u64().map_err(SemanticTransitionError::Semantic)?;
6155    let logical_digest = Identity256::from_bytes(
6156        reader
6157            .take(32)
6158            .map_err(SemanticTransitionError::Semantic)?
6159            .try_into()
6160            .unwrap(),
6161    );
6162    let state_digest = Identity256::from_bytes(
6163        reader
6164            .take(32)
6165            .map_err(SemanticTransitionError::Semantic)?
6166            .try_into()
6167            .unwrap(),
6168    );
6169    Ok(SemanticPublishedIdentity {
6170        instance,
6171        word,
6172        logical_digest,
6173        state_digest,
6174    })
6175}
6176
6177// The reconstruction provenance root contains original authority bytes and the
6178// original continuation decision, never a new grant or the successor snapshot.
6179struct PublicationReplayProvenance {
6180    predecessor: SemanticPublishedIdentity,
6181    authority: PublicationMaterialRange,
6182    decision: PublicationMaterialRange,
6183}
6184
6185impl PublicationReplayProvenance {
6186    fn encode(&self) -> Result<Vec<u8>, SemanticTransitionError> {
6187        let mut bytes = REPLAY_PROVENANCE_MAGIC.to_vec();
6188        material_u32(&mut bytes, 1);
6189        bytes.extend_from_slice(&publication_material_runtime());
6190        encode_publication_identity(&mut bytes, self.predecessor);
6191        self.authority.encode_into(&mut bytes)?;
6192        self.decision.encode_into(&mut bytes)?;
6193        Ok(bytes)
6194    }
6195
6196    fn decode(bytes: &[u8]) -> Result<Self, SemanticTransitionError> {
6197        let mut reader = SemanticMaterialReader::new(bytes);
6198        if reader
6199            .take(REPLAY_PROVENANCE_MAGIC.len())
6200            .map_err(SemanticTransitionError::Semantic)?
6201            != REPLAY_PROVENANCE_MAGIC
6202            || reader.u32().map_err(SemanticTransitionError::Semantic)? != 1
6203            || reader.take(32).map_err(SemanticTransitionError::Semantic)?
6204                != publication_material_runtime()
6205        {
6206            return Err(publication_input_error(
6207                "replay provenance requires its exact pinned native runtime",
6208            ));
6209        }
6210        let predecessor = decode_publication_identity(&mut reader)?;
6211        let authority = PublicationMaterialRange::decode_from(&mut reader)?;
6212        let decision = PublicationMaterialRange::decode_from(&mut reader)?;
6213        reader.finish().map_err(SemanticTransitionError::Semantic)?;
6214        Ok(Self {
6215            predecessor,
6216            authority,
6217            decision,
6218        })
6219    }
6220
6221    fn validate(&self, predecessor: &PublicationMaterial) -> Result<(), SemanticTransitionError> {
6222        let header = predecessor.bank.header;
6223        let original = SemanticPublishedIdentity {
6224            instance: header.instance,
6225            word: header.publication_word,
6226            logical_digest: header.logical_digest,
6227            state_digest: header.state_digest,
6228        };
6229        if self.predecessor != original {
6230            return Err(publication_input_error(
6231                "replay provenance names another original native predecessor",
6232            ));
6233        }
6234        for (item, role) in [(&self.authority, 38), (&self.decision, 39)] {
6235            let saved = predecessor
6236                .ranges
6237                .iter()
6238                .find(|item| item.range.role == role && item.range.index == 0)
6239                .ok_or(SemanticTransitionError::ObservationMismatch)?;
6240            if (item.range.role, item.range.index) != (role, 0)
6241                || item.range.generation != 1
6242                || item.range.length_bytes != item.bytes.len() as u64
6243                || item.capacity != saved.capacity
6244                || item.capacity == 0
6245                || item.bytes.is_empty()
6246                || item.bytes.len() > item.capacity
6247                || item.range.logical_begin > item.range.logical_end
6248                || item.original_record_digest() != item.range.digest
6249            {
6250                return Err(publication_input_error(
6251                    "replay provenance changes an originally sealed authority record",
6252                ));
6253            }
6254            if role == 38
6255                && (item.bytes != saved.bytes
6256                    || publication_abi_bytes(&[item.range])
6257                        != publication_abi_bytes(&[saved.range]))
6258            {
6259                return Err(publication_input_error("replay provenance differs from the predecessor's whole original authority envelope"));
6260            }
6261        }
6262        Ok(())
6263    }
6264}
6265
6266struct PublicationReplayEvidence {
6267    successor: SemanticPublishedIdentity,
6268    ranges: Vec<PublicationMaterialRange>,
6269}
6270
6271impl PublicationReplayEvidence {
6272    fn range(&self, role: u64) -> Result<&PublicationMaterialRange, SemanticTransitionError> {
6273        self.ranges
6274            .iter()
6275            .find(|item| item.range.role == role && item.range.index == 0)
6276            .ok_or_else(|| publication_input_error("replay evidence omits a publication record"))
6277    }
6278
6279    fn state_digest(&self) -> Result<Identity256, SemanticTransitionError> {
6280        let mut digest = self.successor.logical_digest;
6281        for item in &self.ranges {
6282            digest = publication_fold_digest(
6283                digest,
6284                item.range.role,
6285                item.range.index,
6286                item.logical_record_digest()?,
6287            );
6288        }
6289        Ok(digest)
6290    }
6291
6292    fn encode(&self) -> Result<Vec<u8>, SemanticTransitionError> {
6293        let mut bytes = REPLAY_EVIDENCE_MAGIC.to_vec();
6294        material_u32(&mut bytes, 1);
6295        bytes.extend_from_slice(&publication_material_runtime());
6296        encode_publication_identity(&mut bytes, self.successor);
6297        material_u32(
6298            &mut bytes,
6299            u32::try_from(self.ranges.len())
6300                .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
6301        );
6302        for item in &self.ranges {
6303            item.encode_into(&mut bytes)?;
6304        }
6305        Ok(bytes)
6306    }
6307
6308    fn decode(bytes: &[u8]) -> Result<Self, SemanticTransitionError> {
6309        let mut reader = SemanticMaterialReader::new(bytes);
6310        if reader
6311            .take(REPLAY_EVIDENCE_MAGIC.len())
6312            .map_err(SemanticTransitionError::Semantic)?
6313            != REPLAY_EVIDENCE_MAGIC
6314            || reader.u32().map_err(SemanticTransitionError::Semantic)? != 1
6315            || reader.take(32).map_err(SemanticTransitionError::Semantic)?
6316                != publication_material_runtime()
6317        {
6318            return Err(publication_input_error(
6319                "replay evidence requires its exact pinned native runtime",
6320            ));
6321        }
6322        let successor = decode_publication_identity(&mut reader)?;
6323        if reader.u32().map_err(SemanticTransitionError::Semantic)?
6324            != REPLAY_EVIDENCE_ROLES.len() as u32
6325        {
6326            return Err(publication_input_error(
6327                "replay evidence requires all six native publication records",
6328            ));
6329        }
6330        let mut ranges = Vec::with_capacity(REPLAY_EVIDENCE_ROLES.len());
6331        for _ in REPLAY_EVIDENCE_ROLES {
6332            ranges.push(PublicationMaterialRange::decode_from(&mut reader)?);
6333        }
6334        reader.finish().map_err(SemanticTransitionError::Semantic)?;
6335        Ok(Self { successor, ranges })
6336    }
6337
6338    fn validate(
6339        &self,
6340        predecessor: &PublicationMaterial,
6341    ) -> Result<SemanticTransitionKind, SemanticTransitionError> {
6342        let base = predecessor.bank.header;
6343        let successor_word = (base.publication_word >> 1)
6344            .checked_add(1)
6345            .filter(|&epoch| epoch <= u64::MAX >> 1)
6346            .map(|epoch| (epoch << 1) | ((base.publication_word & 1) ^ 1))
6347            .ok_or(SemanticTransitionError::GenerationExhausted)?;
6348        if self.successor.instance != base.instance
6349            || self.successor.word != successor_word
6350            || self.ranges.len() != REPLAY_EVIDENCE_ROLES.len()
6351        {
6352            return Err(publication_input_error(
6353                "replay evidence is not the original predecessor's immediate successor",
6354            ));
6355        }
6356        for (item, role) in self.ranges.iter().zip(REPLAY_EVIDENCE_ROLES) {
6357            let previous = predecessor
6358                .ranges
6359                .iter()
6360                .find(|item| item.range.role == role && item.range.index == 0)
6361                .ok_or(SemanticTransitionError::ObservationMismatch)?;
6362            if (item.range.role, item.range.index) != (role, 0)
6363                || item.range.generation != 1
6364                || item.range.length_bytes != item.bytes.len() as u64
6365                || item.capacity != previous.capacity
6366                || item.capacity == 0
6367                || item.bytes.len() > item.capacity
6368                || item.range.logical_begin > item.range.logical_end
6369                || item.original_record_digest() != item.range.digest
6370            {
6371                return Err(publication_input_error(
6372                    "replay evidence changes or omits an originally sealed publication record",
6373                ));
6374            }
6375        }
6376        let attempt_range = self.range(33)?;
6377        let attempt = attempt_range.attempt()?;
6378        let previous_attempt = predecessor
6379            .ranges
6380            .iter()
6381            .find(|item| item.range.role == 33 && item.range.index == 0)
6382            .ok_or(SemanticTransitionError::ObservationMismatch)?;
6383        if attempt.abi != 2
6384            || attempt.instance != self.successor.instance
6385            || attempt.base_word != base.publication_word
6386            || attempt.next_word != self.successor.word
6387            || attempt.logical_digest != self.successor.logical_digest
6388            || attempt.receipt_digest != attempt_range.logical_record_digest()?
6389            || attempt.previous_attempt_digest != previous_attempt.logical_record_digest()?
6390            || attempt.replay_head_digest != self.range(27)?.logical_record_digest()?
6391            || attempt.intent_head_digest != self.range(30)?.logical_record_digest()?
6392            || attempt.acknowledgement_head_digest != self.range(32)?.logical_record_digest()?
6393            || self.successor.state_digest != self.state_digest()?
6394        {
6395            return Err(publication_input_error(
6396                "replay evidence differs from its whole native attempt and state links",
6397            ));
6398        }
6399        let no_draw =
6400            attempt.action_receipts_digest == Identity256::from_bytes(Sha256::digest([]).into());
6401        match (attempt.transition_kind, base.terminal, no_draw) {
6402            (1, 0, false) => Ok(SemanticTransitionKind::Proposal),
6403            (2, 0, true) => Ok(SemanticTransitionKind::Recompute),
6404            (3, 1, true) => Ok(SemanticTransitionKind::Drain),
6405            (4, 0, true) => Ok(SemanticTransitionKind::Update),
6406            _ => Err(publication_input_error(
6407                "replay attempt cannot follow this predecessor's native terminal state",
6408            )),
6409        }
6410    }
6411
6412    fn validate_observed(
6413        &self,
6414        predecessor: &PublicationMaterial,
6415        bank: &PublicationBank,
6416        coverage: &PublicationMaterialRange,
6417        codebook: &PublicationMaterialRange,
6418    ) -> Result<(), SemanticTransitionError> {
6419        let kind = self.validate(predecessor)?;
6420        let base = predecessor.bank.header;
6421        let header = bank.header;
6422        let draws = if kind == SemanticTransitionKind::Proposal {
6423            COMPONENT_COUNT
6424        } else {
6425            0
6426        };
6427        let proposal = base
6428            .proposal
6429            .checked_add(u64::from(draws != 0))
6430            .ok_or(SemanticTransitionError::GenerationExhausted)?;
6431        if header.abi != 1
6432            || header.instance != self.successor.instance
6433            || header.publication_word != self.successor.word
6434            || header.base_word != base.publication_word
6435            || header.sealed_epoch != self.successor.word >> 1
6436            || header.logical_digest != self.successor.logical_digest
6437            || header.state_digest != self.successor.state_digest
6438            || header.proposal != proposal
6439            || bank.state.proposal != base.proposal
6440            || bank.state.next_proposal != proposal
6441            || bank.state.blocks != draws as u64
6442            || bank.state.status != 0
6443            || (kind == SemanticTransitionKind::Drain && header.terminal != 2)
6444            || (kind == SemanticTransitionKind::Recompute && header.terminal != 0)
6445            || (kind == SemanticTransitionKind::Proposal && header.terminal > 1)
6446        {
6447            return Err(publication_input_error(
6448                "replay evidence does not describe the actual acquired native transition",
6449            ));
6450        }
6451        let attempt = self.range(33)?.attempt()?;
6452        if coverage.range.role != 14
6453            || coverage.bytes.len() != size_of::<CompletionCoverage>()
6454            || coverage.original_record_digest() != coverage.range.digest
6455            || codebook.original_record_digest() != codebook.range.digest
6456        {
6457            return Err(publication_input_error(
6458                "replay evidence sources differ from their actual native seals",
6459            ));
6460        }
6461        // SAFETY: the exact coverage extent was checked and all ABI fields are integers.
6462        let completion = unsafe {
6463            std::ptr::read_unaligned(coverage.bytes.as_ptr().cast::<CompletionCoverage>())
6464        };
6465        let coverage_digest = coverage.logical_record_digest()?;
6466        let component_receipts_digest =
6467            publication_action_receipts_digest(codebook, &bank.receipts[..draws])?;
6468        let semantic_receipts_digest =
6469            publication_semantic_receipts_digest(&bank.state.semantic_receipts);
6470        let action_batch_valid = if kind == SemanticTransitionKind::Proposal {
6471            let batch = &bank.state.action_batch;
6472            let root = publication_action_batch_root(batch);
6473            batch.abi == 1
6474                && batch.proposal == bank.state.proposal
6475                && batch.stream_serial == bank.state.stream_serial
6476                && batch.family_id == u64::from(bank.state.family_id)
6477                && batch.action_law_generation == bank.state.catalogue_generation
6478                && batch.model_generation == u64::from(bank.state.model_generation)
6479                && batch.actor_eligible == bank.state.actor_eligible
6480                && batch.actor_eligible <= 1
6481                && batch.component_count == COMPONENT_COUNT as u64
6482                && batch.candidate_count == 3
6483                && batch.winner == bank.state.task_evaluation.winner
6484                && batch.total_return_bits == bank.state.task_evaluation.return_value as u64
6485                && batch.base_word == base.publication_word
6486                && batch.next_word == header.publication_word
6487                && batch.rng_base == bank.state.proposal * COMPONENT_COUNT as u64
6488                && batch.rng_span == COMPONENT_COUNT as u64
6489                && batch.rng_successor == bank.state.next_proposal * COMPONENT_COUNT as u64
6490                && batch.catalogue_digest == bank.state.catalogue_digest
6491                && batch.component_receipts_digest == component_receipts_digest
6492                && batch.semantic_receipts_digest == semantic_receipts_digest
6493                && batch.base_logical_digest == base.logical_digest
6494                && batch.execution_work == bank.state.execution_work
6495                && [0usize, 3, 6]
6496                    .into_iter()
6497                    .enumerate()
6498                    .all(|(candidate, receipt)| {
6499                        identity_words(*batch.candidate_roots[candidate].as_bytes())
6500                            == bank.state.semantic_receipts[receipt][16..20]
6501                    })
6502                && root == bank.state.action_batch_root
6503                && root == attempt.action_receipts_digest
6504        } else {
6505            bank.state.action_batch == SemanticActionBatchReceipt::default()
6506                && bank.state.action_batch_root == Identity256::default()
6507                && attempt.action_receipts_digest == component_receipts_digest
6508        };
6509        if completion.abi != 1
6510            || completion.instance != header.instance
6511            || completion.base_word != base.publication_word
6512            || completion.receipt_digest != coverage_digest
6513            || attempt.coverage_digest != coverage_digest
6514            || !action_batch_valid
6515            || attempt.semantic_receipts_digest != semantic_receipts_digest
6516        {
6517            return Err(publication_input_error(
6518                "whole native attempt differs from actual action, semantic or completion receipts",
6519            ));
6520        }
6521        Ok(())
6522    }
6523}
6524
6525/// Owned cold replay inputs: complete predecessor material and the successor's
6526/// external native publication evidence. Hash consistency does not establish
6527/// historical execution, current rights, or permission to use a model.
6528pub struct SemanticReplayMaterial {
6529    predecessor: PublicationMaterial,
6530    evidence: PublicationReplayEvidence,
6531    kind: SemanticTransitionKind,
6532}
6533
6534struct ReplayInitialPrefill {
6535    original: SemanticPublishedIdentity,
6536    content: Vec<u8>,
6537    recovery_referent: Option<Vec<u8>>,
6538}
6539
6540impl SemanticReplayMaterial {
6541    fn completed_child_payload<'a>(
6542        &self,
6543        bytes: &'a [u8],
6544        kind: &[u8],
6545        expected_identity: Identity256,
6546        expected_owner: Identity256,
6547    ) -> Result<&'a [u8], SemanticTransitionError> {
6548        let mut reader = SemanticMaterialReader::new(bytes);
6549        let magic = b"XLOG-COMPLETED-ACTION-CHILD\0";
6550        if reader
6551            .take(magic.len())
6552            .map_err(SemanticTransitionError::Semantic)?
6553            != magic
6554            || reader.u64().map_err(SemanticTransitionError::Semantic)? != 1
6555        {
6556            return Err(publication_input_error(
6557                "completed action child has another envelope",
6558            ));
6559        }
6560        let owner = reader.take(32).map_err(SemanticTransitionError::Semantic)?;
6561        if owner != expected_owner.as_bytes() {
6562            return Err(publication_input_error(
6563                "completed action child belongs to another action",
6564            ));
6565        }
6566        if reader.u64().map_err(SemanticTransitionError::Semantic)? != kind.len() as u64
6567            || reader
6568                .take(kind.len())
6569                .map_err(SemanticTransitionError::Semantic)?
6570                != kind
6571            || reader.u64().map_err(SemanticTransitionError::Semantic)? != 0
6572        {
6573            return Err(publication_input_error(
6574                "completed action child has another kind or ordinal",
6575            ));
6576        }
6577        let mut binding = b"xlog.completed-action-child.v1\0".to_vec();
6578        binding.extend_from_slice(owner);
6579        material_u64(&mut binding, kind.len() as u64);
6580        binding.extend_from_slice(kind);
6581        material_u64(&mut binding, 0);
6582        if Identity256::from_bytes(Sha256::digest(binding).into()) != expected_identity {
6583            return Err(publication_input_error(
6584                "completed action child identity differs from its owner",
6585            ));
6586        }
6587        let length = usize::try_from(reader.u64().map_err(SemanticTransitionError::Semantic)?)
6588            .map_err(|_| publication_input_error("completed action child exceeds this host"))?;
6589        let payload = reader
6590            .take(length)
6591            .map_err(SemanticTransitionError::Semantic)?;
6592        reader.finish().map_err(SemanticTransitionError::Semantic)?;
6593        Ok(payload)
6594    }
6595
6596    fn read_initial_prefill_child(
6597        &self,
6598        bytes: &[u8],
6599        expected_identity: Identity256,
6600        expected_owner: Identity256,
6601    ) -> Result<ReplayInitialPrefill, SemanticTransitionError> {
6602        let payload = self.completed_child_payload(
6603            bytes,
6604            b"initial-prefill",
6605            expected_identity,
6606            expected_owner,
6607        )?;
6608        let mut payload = SemanticMaterialReader::new(payload);
6609        let magic = b"XLOG-INITIAL-PREFILL\0";
6610        if payload
6611            .take(magic.len())
6612            .map_err(SemanticTransitionError::Semantic)?
6613            != magic
6614            || payload.u64().map_err(SemanticTransitionError::Semantic)? != 2
6615        {
6616            return Err(publication_input_error(
6617                "initial prefill child has another body version",
6618            ));
6619        }
6620        let original = decode_publication_identity(&mut payload)?;
6621        let actual = decode_publication_identity(&mut payload)?;
6622        let header = self.predecessor.bank.header;
6623        if actual != self.predecessor_identity() {
6624            return Err(publication_input_error(
6625                "initial prefill child names another actual predecessor",
6626            ));
6627        }
6628        let recovery_referent = match payload.u8().map_err(SemanticTransitionError::Semantic)? {
6629            1 if original == actual => None,
6630            2 if original != actual
6631                && original.word == 0
6632                && actual.word == 0
6633                && original.instance != actual.instance
6634                && header.recovered_instance == original.instance
6635                && original.logical_digest == actual.logical_digest
6636                && original.state_digest == actual.state_digest =>
6637            {
6638                let length =
6639                    usize::try_from(payload.u64().map_err(SemanticTransitionError::Semantic)?)
6640                        .map_err(|_| {
6641                            publication_input_error("initial prefill referent exceeds this host")
6642                        })?;
6643                let referent = payload
6644                    .take(length)
6645                    .map_err(SemanticTransitionError::Semantic)?
6646                    .to_vec();
6647                if referent.is_empty() {
6648                    return Err(publication_input_error(
6649                        "recovered initial prefill has no source referent",
6650                    ));
6651                }
6652                Some(referent)
6653            }
6654            _ => {
6655                return Err(publication_input_error(
6656                    "initial prefill recovery chain is invalid",
6657                ))
6658            }
6659        };
6660        let content = payload.take_rest().to_vec();
6661        if content.is_empty() {
6662            return Err(publication_input_error(
6663                "initial prefill child has no original content",
6664            ));
6665        }
6666        let mut tail = SemanticMaterialReader::new(&content);
6667        tail.take(32 + 8 + 32)
6668            .map_err(SemanticTransitionError::Semantic)?;
6669        let task_epoch = tail.u64().map_err(SemanticTransitionError::Semantic)?;
6670        let mut read_identity = || -> Result<Identity256, SemanticTransitionError> {
6671            Ok(Identity256::from_bytes(
6672                tail.take(32)
6673                    .map_err(SemanticTransitionError::Semantic)?
6674                    .try_into()
6675                    .unwrap(),
6676            ))
6677        };
6678        let task_content = SemanticTaskContentIdentity {
6679            query: read_identity()?,
6680            theory_program: read_identity()?,
6681            result: read_identity()?,
6682        };
6683        CheckpointInitialPrefill {
6684            original,
6685            content: content.clone(),
6686            recovery_referent: None,
6687        }
6688        .verify_content(
6689            header.semantic_digest,
6690            header.model_generation,
6691            self.predecessor.contract.task_identity,
6692            task_epoch,
6693            task_content,
6694            header.prefix_extent,
6695        )?;
6696        Ok(ReplayInitialPrefill {
6697            original,
6698            content,
6699            recovery_referent,
6700        })
6701    }
6702
6703    /// Return a recovery source reference only after checking the native child
6704    /// owner, its exact physical predecessor, and the restored-instance chain.
6705    pub fn initial_prefill_recovery_referent(
6706        &self,
6707        child: &[u8],
6708        child_identity: Identity256,
6709        action_identity: Identity256,
6710    ) -> Result<Option<Vec<u8>>, SemanticTransitionError> {
6711        Ok(self
6712            .read_initial_prefill_child(child, child_identity, action_identity)?
6713            .recovery_referent)
6714    }
6715
6716    /// Read the late action's compact record through the same child envelope.
6717    /// The binding layer verifies every referent field and resolves its complete
6718    /// checkpoint through the existing bounded source resolver.
6719    pub fn pre_action_checkpoint_referent(
6720        &self,
6721        child: &[u8],
6722        child_identity: Identity256,
6723        action_identity: Identity256,
6724    ) -> Result<Vec<u8>, SemanticTransitionError> {
6725        let payload = self.completed_child_payload(
6726            child,
6727            b"pre-action-checkpoint",
6728            child_identity,
6729            action_identity,
6730        )?;
6731        if payload.len() != SemanticTransitionSession::CHECKPOINT_REFERENT_BYTES
6732            || payload.last() != Some(&3)
6733        {
6734            return Err(publication_input_error(
6735                "late checkpoint child has another pre-action phase or extent",
6736            ));
6737        }
6738        Ok(payload.to_vec())
6739    }
6740
6741    /// Full resolved late source must equal this original replay's own acquired
6742    /// publication, including all model allocations, random state and arena.
6743    pub fn verify_pre_action_checkpoint_source(
6744        &self,
6745        native: &[u8],
6746        task_identity: Identity256,
6747        task_epoch: u64,
6748    ) -> Result<(), SemanticTransitionError> {
6749        if self.predecessor.contract.task_identity != task_identity
6750            || self.predecessor.bank.header.authority_generation != task_epoch
6751            || native != self.predecessor.encode()?
6752        {
6753            return Err(publication_input_error(
6754                "late checkpoint differs from this action's complete predecessor custody",
6755            ));
6756        }
6757        Ok(())
6758    }
6759
6760    /// The compact reference is useful only if the full original checkpoint
6761    /// carries precisely the source publication and prefill bytes in this child.
6762    /// Keep the child bytes with their seal and the original checkpoint sections
6763    /// together; the task binding belongs to that original checkpoint.
6764    pub fn verify_initial_prefill_checkpoint_source(
6765        &self,
6766        (child, child_identity): (&[u8], Identity256),
6767        action_identity: Identity256,
6768        (original_native, original_prefill_section): (&[u8], &[u8]),
6769        task_identity: Identity256,
6770        task_epoch: u64,
6771        task_content: SemanticTaskContentIdentity,
6772    ) -> Result<(), SemanticTransitionError> {
6773        let replay = self.read_initial_prefill_child(child, child_identity, action_identity)?;
6774        if replay.recovery_referent.is_none()
6775            || !SemanticTransitionSession::verify_checkpoint_initial_prefill_source(
6776                original_prefill_section,
6777                original_native,
6778                task_identity,
6779                task_epoch,
6780                task_content,
6781                true,
6782            )?
6783        {
6784            return Err(publication_input_error(
6785                "initial prefill recovery has no original checkpoint source",
6786            ));
6787        }
6788        let original = CheckpointInitialPrefill::decode_section(original_prefill_section)?
6789            .ok_or_else(|| publication_input_error("original checkpoint has no initial prefill"))?;
6790        if replay.original != original.original || replay.content != original.content {
6791            return Err(publication_input_error(
6792                "recovered prefill differs from original checkpoint content",
6793            ));
6794        }
6795        Ok(())
6796    }
6797
6798    /// Check the original coordinates and seals before any runtime relocation.
6799    pub fn decode(
6800        predecessor_bytes: &[u8],
6801        evidence_bytes: &[u8],
6802        expected_predecessor_logical: Identity256,
6803        expected_successor_logical: Identity256,
6804    ) -> Result<Self, SemanticTransitionError> {
6805        let predecessor = PublicationMaterial::decode(predecessor_bytes)?;
6806        let evidence = PublicationReplayEvidence::decode(evidence_bytes)?;
6807        if predecessor.bank.header.logical_digest != expected_predecessor_logical
6808            || evidence.successor.logical_digest != expected_successor_logical
6809        {
6810            return Err(publication_input_error(
6811                "replay native materials differ from the execution's logical identities",
6812            ));
6813        }
6814        let kind = evidence.validate(&predecessor)?;
6815        Ok(Self {
6816            predecessor,
6817            evidence,
6818            kind,
6819        })
6820    }
6821
6822    pub fn predecessor_identity(&self) -> SemanticPublishedIdentity {
6823        let header = self.predecessor.bank.header;
6824        SemanticPublishedIdentity {
6825            instance: header.instance,
6826            word: header.publication_word,
6827            logical_digest: header.logical_digest,
6828            state_digest: header.state_digest,
6829        }
6830    }
6831
6832    pub fn successor_identity(&self) -> SemanticPublishedIdentity {
6833        self.evidence.successor
6834    }
6835
6836    pub fn transition_kind(&self) -> SemanticTransitionKind {
6837        self.kind
6838    }
6839
6840    pub fn training_view_origin(
6841        &self,
6842    ) -> Result<SemanticTrainingViewOrigin, SemanticTransitionError> {
6843        let header = self.predecessor.bank.header;
6844        Ok(SemanticTrainingViewOrigin {
6845            transition: self.kind,
6846            predecessor: self.predecessor_identity(),
6847            successor: self.successor_identity(),
6848            invocation: header.rng_binding()?,
6849            model_geometry_digest: header.model_geometry_digest,
6850            model_numerical_digest: header.model_numerical_digest,
6851        })
6852    }
6853
6854    /// Original model-owned contribution, after complete material validation.
6855    /// Its consumer must validate the supported model format before restoring
6856    /// numerical state; these bytes are not current settings or an execution grant.
6857    pub fn model_numerical_mode(&self) -> Result<&[u8], SemanticTransitionError> {
6858        self.predecessor.model_numerical_mode()
6859    }
6860
6861    /// Return the archived continuation decision after checking its native
6862    /// provenance root against the original complete predecessor. The caller
6863    /// must separately bind this root through the canonical reconstruction
6864    /// closure and check current rights; these bytes are not current authority.
6865    pub fn verify_provenance(&self, bytes: &[u8]) -> Result<Vec<u8>, SemanticTransitionError> {
6866        let provenance = PublicationReplayProvenance::decode(bytes)?;
6867        provenance.validate(&self.predecessor)?;
6868        Ok(provenance.decision.bytes)
6869    }
6870}
6871
6872/// Complete native logical-state material inside an execution's material
6873/// closure. This is not an episode, a use grant, or proof of past publication.
6874struct PublicationMaterial {
6875    bank: PublicationBank,
6876    contract: PublicationContract,
6877    role_counts: [u64; 55],
6878    terminals: Vec<u64>,
6879    layouts: BTreeMap<(u64, u64), SemanticTensorLayout>,
6880    model_memory: ModelMemoryGeometry,
6881    model_allocations: Vec<Vec<u8>>,
6882    ranges: Vec<PublicationMaterialRange>,
6883    graph: SemanticRootMaterial,
6884    learning_phases: Vec<SemanticLearningPhaseRecord>,
6885}
6886
6887/// Read-only delivery material from a sealed publication. Reading an
6888/// intent neither proves that the checkpoint was durably committed nor grants
6889/// authority to perform its external effect.
6890pub struct SemanticOutputIntent {
6891    pub stable_identity: Identity256,
6892    pub effect: Vec<u8>,
6893    pub payload: Vec<u8>,
6894}
6895
6896fn acknowledgement_receipts(
6897    bytes: &[u8],
6898    capacity_bytes: usize,
6899) -> Result<Vec<(Identity256, Vec<u8>)>, SemanticTransitionError> {
6900    if bytes.len() < size_of::<AcknowledgementQueueHeader>() {
6901        return Err(publication_input_error(
6902            "acknowledgement queue has no native header",
6903        ));
6904    }
6905    // SAFETY: the checked, padding-free header contains only integral fields.
6906    let header = unsafe {
6907        bytes
6908            .as_ptr()
6909            .cast::<AcknowledgementQueueHeader>()
6910            .read_unaligned()
6911    };
6912    let declared_capacity = usize::try_from(header.capacity)
6913        .ok()
6914        .and_then(|count| count.checked_mul(size_of::<AcknowledgementEntry>()))
6915        .and_then(|entries| {
6916            usize::try_from(header.payload_capacity_bytes)
6917                .ok()?
6918                .checked_add(entries)
6919        })
6920        .and_then(|body| body.checked_add(size_of::<AcknowledgementQueueHeader>()));
6921    if header.abi != 1
6922        || header.count > header.capacity
6923        || declared_capacity != Some(capacity_bytes)
6924        || header.payload_used_bytes
6925            != (bytes.len() - size_of::<AcknowledgementQueueHeader>()) as u64
6926    {
6927        return Err(publication_input_error(
6928            "acknowledgement queue extent is inconsistent",
6929        ));
6930    }
6931    let mut cursor = size_of::<AcknowledgementQueueHeader>();
6932    let mut receipt_bytes = 0usize;
6933    let mut chain = Identity256::default();
6934    let mut seen = BTreeSet::new();
6935    let mut result = Vec::with_capacity(header.count as usize);
6936    for ordinal in 0..header.count {
6937        let entry_end = cursor
6938            .checked_add(size_of::<AcknowledgementEntry>())
6939            .filter(|&end| end <= bytes.len())
6940            .ok_or_else(|| publication_input_error("acknowledgement entry is incomplete"))?;
6941        // SAFETY: the exact entry extent was checked above.
6942        let entry = unsafe {
6943            bytes[cursor..]
6944                .as_ptr()
6945                .cast::<AcknowledgementEntry>()
6946                .read_unaligned()
6947        };
6948        let length = usize::try_from(entry.receipt_len)
6949            .map_err(|_| publication_input_error("acknowledgement receipt overflows this host"))?;
6950        let end = entry_end
6951            .checked_add(length)
6952            .filter(|&end| end <= bytes.len())
6953            .ok_or_else(|| publication_input_error("acknowledgement receipt is incomplete"))?;
6954        let receipt = &bytes[entry_end..end];
6955        receipt_bytes = receipt_bytes
6956            .checked_add(length)
6957            .ok_or_else(|| publication_input_error("acknowledgement receipt extent overflows"))?;
6958        let previous = chain;
6959        chain = publication_fold_digest(chain, 32, ordinal, entry.stable_identity);
6960        chain = publication_fold_digest(chain, 32, ordinal, entry.receipt_digest);
6961        if entry.stable_identity == Identity256::default()
6962            || !seen.insert(*entry.stable_identity.as_bytes())
6963            || entry.previous_chain != previous
6964            || entry.chain != chain
6965            || entry.receipt_digest != Identity256::from_bytes(Sha256::digest(receipt).into())
6966        {
6967            return Err(publication_input_error(
6968                "acknowledgement differs from its native chain",
6969            ));
6970        }
6971        result.push((entry.stable_identity, receipt.to_vec()));
6972        cursor = end;
6973    }
6974    if cursor != bytes.len()
6975        || chain != header.chain_head
6976        || receipt_bytes > header.payload_capacity_bytes as usize
6977    {
6978        return Err(publication_input_error(
6979            "acknowledgement chain does not cover its receipts",
6980        ));
6981    }
6982    Ok(result)
6983}
6984
6985pub fn output_intents_from_publication_material(
6986    native_material: &[u8],
6987) -> Result<Vec<SemanticOutputIntent>, SemanticTransitionError> {
6988    let material = PublicationMaterial::decode(native_material)?;
6989    let entries = material
6990        .ranges
6991        .iter()
6992        .find(|item| (item.range.role, item.range.index) == (30, 0))
6993        .ok_or_else(|| publication_input_error("checkpoint omits its native intent queue"))?;
6994    let payload = material
6995        .ranges
6996        .iter()
6997        .find(|item| (item.range.role, item.range.index) == (31, 0))
6998        .ok_or_else(|| publication_input_error("checkpoint omits its native intent payload"))?;
6999    output_intents_from_ranges(entries, payload)
7000}
7001
7002/// Resolve the current undelivered set from both sealed native queues. The
7003/// trusted receiver key authenticates every persisted acknowledgement before
7004/// any intent is omitted from a restored delivery retry.
7005pub fn pending_output_intents_from_publication_material(
7006    native_material: &[u8],
7007    recipient_id: Identity256,
7008    verification_key: &[u8; 32],
7009    expected_effect: &[u8],
7010) -> Result<Vec<SemanticOutputIntent>, SemanticTransitionError> {
7011    if recipient_id == Identity256::default() || verification_key.iter().all(|&byte| byte == 0) {
7012        return Err(publication_input_error(
7013            "pending intent projection requires the trusted receiver identity and key",
7014        ));
7015    }
7016    let material = PublicationMaterial::decode(native_material)?;
7017    let entries = material
7018        .ranges
7019        .iter()
7020        .find(|item| (item.range.role, item.range.index) == (30, 0))
7021        .ok_or_else(|| publication_input_error("checkpoint omits its native intent queue"))?;
7022    let payload = material
7023        .ranges
7024        .iter()
7025        .find(|item| (item.range.role, item.range.index) == (31, 0))
7026        .ok_or_else(|| publication_input_error("checkpoint omits its native intent payload"))?;
7027    let acknowledgements = material
7028        .ranges
7029        .iter()
7030        .find(|item| (item.range.role, item.range.index) == (32, 0))
7031        .ok_or_else(|| {
7032            publication_input_error("checkpoint omits its native acknowledgement queue")
7033        })?;
7034    let intents = output_intents_from_ranges(entries, payload)?;
7035    if expected_effect.is_empty()
7036        || intents
7037            .iter()
7038            .any(|intent| intent.effect.as_slice() != expected_effect)
7039    {
7040        return Err(publication_input_error(
7041            "checkpoint intent differs from the bound receiver effect",
7042        ));
7043    }
7044    let receipts = acknowledgement_receipts(&acknowledgements.bytes, acknowledgements.capacity)?;
7045    let mut acknowledged = BTreeSet::new();
7046    for (identity, receipt) in receipts {
7047        let intent = intents
7048            .iter()
7049            .find(|intent| intent.stable_identity == identity)
7050            .ok_or_else(|| {
7051                publication_input_error("checkpoint acknowledges an absent native intent")
7052            })?;
7053        verify_delivery_receipt(&receipt, intent, recipient_id, verification_key)?;
7054        acknowledged.insert(*identity.as_bytes());
7055    }
7056    Ok(intents
7057        .into_iter()
7058        .filter(|intent| !acknowledged.contains(intent.stable_identity.as_bytes()))
7059        .collect())
7060}
7061
7062fn output_intents_from_ranges(
7063    entries: &PublicationMaterialRange,
7064    payload: &PublicationMaterialRange,
7065) -> Result<Vec<SemanticOutputIntent>, SemanticTransitionError> {
7066    if entries.bytes.len() < size_of::<IntentQueueHeader>() {
7067        return Err(publication_input_error(
7068            "checkpoint intent queue has no header",
7069        ));
7070    }
7071    // SAFETY: the checked byte extent contains an all-bit-valid scalar ABI record.
7072    let header =
7073        unsafe { std::ptr::read_unaligned(entries.bytes.as_ptr().cast::<IntentQueueHeader>()) };
7074    let entry_extent = usize::try_from(header.count)
7075        .ok()
7076        .and_then(|count| count.checked_mul(size_of::<IntentEntry>()))
7077        .and_then(|bytes| bytes.checked_add(size_of::<IntentQueueHeader>()));
7078    let capacity_extent = usize::try_from(header.capacity)
7079        .ok()
7080        .and_then(|count| count.checked_mul(size_of::<IntentEntry>()))
7081        .and_then(|bytes| bytes.checked_add(size_of::<IntentQueueHeader>()));
7082    if header.abi != 1
7083        || header.count > header.capacity
7084        || entry_extent != Some(entries.bytes.len())
7085        || capacity_extent.is_none_or(|extent| extent != entries.capacity)
7086        || header.payload_used_bytes != payload.bytes.len() as u64
7087        || header.payload_capacity_bytes != payload.capacity as u64
7088        || header.effect_offset_bytes != 0
7089        || header.effect_length_bytes == 0
7090        || header.effect_length_bytes > header.payload_used_bytes
7091    {
7092        return Err(publication_input_error(
7093            "checkpoint intent queue has inconsistent extents",
7094        ));
7095    }
7096    let effect_end = usize::try_from(header.effect_length_bytes)
7097        .map_err(|_| publication_input_error("checkpoint intent effect overflows this host"))?;
7098    let effect = &payload.bytes[..effect_end];
7099    let effect_digest = Identity256::from_bytes(Sha256::digest(effect).into());
7100    let mut cursor = effect_end;
7101    let mut chain = Identity256::default();
7102    let mut result = Vec::with_capacity(header.count as usize);
7103    for ordinal in 0..header.count {
7104        let offset = size_of::<IntentQueueHeader>() + ordinal as usize * size_of::<IntentEntry>();
7105        // SAFETY: the exact entry extent was checked above; the ABI is scalar-only.
7106        let entry = unsafe {
7107            std::ptr::read_unaligned(entries.bytes[offset..].as_ptr().cast::<IntentEntry>())
7108        };
7109        let length = usize::try_from(entry.payload_len).map_err(|_| {
7110            publication_input_error("checkpoint intent payload overflows this host")
7111        })?;
7112        let end = cursor
7113            .checked_add(length)
7114            .filter(|&end| end <= payload.bytes.len())
7115            .ok_or_else(|| publication_input_error("checkpoint intent payload is incomplete"))?;
7116        let content = &payload.bytes[cursor..end];
7117        let mut identity = Sha256::new();
7118        identity.update(0x786c6f67696e7431u64.to_le_bytes());
7119        for part in [
7120            entry.checkpoint_lineage,
7121            entry.base_logical,
7122            entry.effective_delta,
7123            entry.result_logical,
7124            entry.effect_digest,
7125            entry.payload_digest,
7126        ] {
7127            identity.update(part.as_bytes());
7128        }
7129        let stable_identity = Identity256::from_bytes(identity.finalize().into());
7130        let previous_chain = chain;
7131        chain = publication_fold_digest(chain, 30, ordinal, stable_identity);
7132        if entry.payload_offset != cursor as u64
7133            || entry.payload_len < 8
7134            || entry.effect_digest != effect_digest
7135            || entry.payload_digest != Identity256::from_bytes(Sha256::digest(content).into())
7136            || entry.previous_chain != previous_chain
7137            || entry.chain != chain
7138            || entry.stable_identity != stable_identity
7139            || stable_identity == Identity256::default()
7140        {
7141            return Err(publication_input_error(
7142                "checkpoint intent entry differs from its native chain",
7143            ));
7144        }
7145        result.push(SemanticOutputIntent {
7146            stable_identity,
7147            effect: effect.to_vec(),
7148            payload: content.to_vec(),
7149        });
7150        cursor = end;
7151    }
7152    if cursor != payload.bytes.len() || header.chain_head != chain {
7153        return Err(publication_input_error(
7154            "checkpoint intent chain does not cover its payload",
7155        ));
7156    }
7157    Ok(result)
7158}
7159
7160fn verify_delivery_receipt(
7161    receipt: &[u8],
7162    intent: &SemanticOutputIntent,
7163    recipient_id: Identity256,
7164    verification_key: &[u8; 32],
7165) -> Result<Identity256, SemanticTransitionError> {
7166    const RECEIPT_DOMAIN: &[u8] = b"xlog.delivery.receipt.v1\0";
7167    const RECORD_DOMAIN: &[u8] = b"xlog.delivery.record.v1\0";
7168    let body_len = RECEIPT_DOMAIN
7169        .len()
7170        .checked_add(32 + 32 + 8 + 8 + 32)
7171        .and_then(|size| size.checked_add(intent.effect.len()))
7172        .and_then(|size| size.checked_add(intent.payload.len()))
7173        .ok_or_else(|| publication_input_error("delivery receipt extent overflows"))?;
7174    if recipient_id == Identity256::default()
7175        || body_len.checked_add(32) != Some(receipt.len())
7176        || !receipt.starts_with(RECEIPT_DOMAIN)
7177    {
7178        return Err(publication_input_error(
7179            "delivery receipt has another canonical extent or recipient",
7180        ));
7181    }
7182    let mut cursor = RECEIPT_DOMAIN.len();
7183    let identity_end = cursor + 32;
7184    if receipt[cursor..identity_end] != intent.stable_identity.as_bytes()[..] {
7185        return Err(publication_input_error(
7186            "delivery receipt has another native intent identity",
7187        ));
7188    }
7189    cursor = identity_end;
7190    let recipient_end = cursor + 32;
7191    if receipt[cursor..recipient_end] != recipient_id.as_bytes()[..] {
7192        return Err(publication_input_error(
7193            "delivery receipt has another trusted recipient",
7194        ));
7195    }
7196    cursor = recipient_end;
7197    let effect_length = u64::from_le_bytes(
7198        receipt[cursor..cursor + 8]
7199            .try_into()
7200            .expect("fixed extent"),
7201    );
7202    cursor += 8;
7203    if effect_length != intent.effect.len() as u64
7204        || receipt[cursor..cursor + intent.effect.len()] != intent.effect[..]
7205    {
7206        return Err(publication_input_error(
7207            "delivery receipt has another native effect",
7208        ));
7209    }
7210    cursor += intent.effect.len();
7211    let payload_length = u64::from_le_bytes(
7212        receipt[cursor..cursor + 8]
7213            .try_into()
7214            .expect("fixed extent"),
7215    );
7216    cursor += 8;
7217    if payload_length != intent.payload.len() as u64
7218        || receipt[cursor..cursor + intent.payload.len()] != intent.payload[..]
7219    {
7220        return Err(publication_input_error(
7221            "delivery receipt has another native payload",
7222        ));
7223    }
7224    cursor += intent.payload.len();
7225    let mut record = Sha256::new();
7226    record.update(RECORD_DOMAIN);
7227    record.update(&receipt[RECEIPT_DOMAIN.len()..cursor]);
7228    let expected_record: [u8; 32] = record.finalize().into();
7229    if receipt[cursor..cursor + 32] != expected_record {
7230        return Err(publication_input_error(
7231            "delivery receipt differs from its durable record digest",
7232        ));
7233    }
7234    let mut ipad = [0x36u8; 64];
7235    let mut opad = [0x5cu8; 64];
7236    for (index, &byte) in verification_key.iter().enumerate() {
7237        ipad[index] ^= byte;
7238        opad[index] ^= byte;
7239    }
7240    let mut inner = Sha256::new();
7241    inner.update(ipad);
7242    inner.update(&receipt[..body_len]);
7243    let mut outer = Sha256::new();
7244    outer.update(opad);
7245    outer.update(inner.finalize());
7246    let expected_mac: [u8; 32] = outer.finalize().into();
7247    let mut mismatch = 0u8;
7248    for (actual, expected) in receipt[body_len..].iter().zip(expected_mac) {
7249        mismatch |= *actual ^ expected;
7250    }
7251    if mismatch != 0 {
7252        return Err(publication_input_error(
7253            "delivery receipt MAC does not match the trusted receiver",
7254        ));
7255    }
7256    Ok(Identity256::from_bytes(Sha256::digest(receipt).into()))
7257}
7258
7259#[cfg(test)]
7260mod delivery_receipt_tests {
7261    use super::*;
7262
7263    #[test]
7264    fn exact_durable_receipt_binds_the_native_intent_and_receiver() {
7265        let intent = SemanticOutputIntent {
7266            stable_identity: Identity256::from_bytes([3; 32]),
7267            effect: b"deliver".to_vec(),
7268            payload: b"result".to_vec(),
7269        };
7270        let recipient = Identity256::from_bytes([5; 32]);
7271        let key = [7; 32];
7272        let mut receipt = b"xlog.delivery.receipt.v1\0".to_vec();
7273        receipt.extend_from_slice(intent.stable_identity.as_bytes());
7274        receipt.extend_from_slice(recipient.as_bytes());
7275        receipt.extend_from_slice(&(intent.effect.len() as u64).to_le_bytes());
7276        receipt.extend_from_slice(&intent.effect);
7277        receipt.extend_from_slice(&(intent.payload.len() as u64).to_le_bytes());
7278        receipt.extend_from_slice(&intent.payload);
7279        let mut record = Sha256::new();
7280        record.update(b"xlog.delivery.record.v1\0");
7281        record.update(&receipt[b"xlog.delivery.receipt.v1\0".len()..]);
7282        receipt.extend_from_slice(&record.finalize());
7283        let mut ipad = [0x36u8; 64];
7284        let mut opad = [0x5cu8; 64];
7285        for (index, byte) in key.iter().enumerate() {
7286            ipad[index] ^= byte;
7287            opad[index] ^= byte;
7288        }
7289        let mut inner = Sha256::new();
7290        inner.update(ipad);
7291        inner.update(&receipt);
7292        let mut outer = Sha256::new();
7293        outer.update(opad);
7294        outer.update(inner.finalize());
7295        receipt.extend_from_slice(&outer.finalize());
7296        assert_eq!(
7297            receipt.len(),
7298            169 + intent.effect.len() + intent.payload.len()
7299        );
7300        assert_eq!(
7301            verify_delivery_receipt(&receipt, &intent, recipient, &key).unwrap(),
7302            Identity256::from_bytes(Sha256::digest(&receipt).into())
7303        );
7304        assert!(verify_delivery_receipt(&receipt, &intent, recipient, &[8; 32]).is_err());
7305        assert!(
7306            verify_delivery_receipt(&receipt, &intent, Identity256::from_bytes([6; 32]), &key)
7307                .is_err()
7308        );
7309        receipt[100] ^= 1;
7310        assert!(verify_delivery_receipt(&receipt, &intent, recipient, &key).is_err());
7311    }
7312
7313    #[test]
7314    fn acknowledgement_reserve_covers_every_full_receipt() {
7315        let required = 169 * 3 + 256 + 2 * 7;
7316        assert!(initial_acknowledgement_record(3, required - 1, 256, 7).is_err());
7317        let record = initial_acknowledgement_record(3, required, 256, 7).unwrap();
7318        assert_eq!(
7319            acknowledgement_receipts(&record.bytes, record.capacity_bytes)
7320                .unwrap()
7321                .len(),
7322            0
7323        );
7324        assert!(initial_acknowledgement_record(0, required, 256, 7).is_err());
7325    }
7326}
7327
7328fn relocate_publication_codebooks(
7329    saved: &[u8],
7330    actual: &[u64],
7331) -> Result<Vec<u8>, SemanticTransitionError> {
7332    if actual.len() < 25
7333        || saved.len()
7334            != actual
7335                .len()
7336                .checked_mul(8)
7337                .ok_or(SemanticTransitionError::GenerationExhausted)?
7338    {
7339        return Err(publication_input_error(
7340            "restored codebook has another actual extent",
7341        ));
7342    }
7343    for (index, (saved, &actual)) in saved.as_chunks::<8>().0.iter().zip(actual).enumerate() {
7344        if !matches!(index, 14..=16 | 21..=24) && u64::from_le_bytes(*saved) != actual {
7345            return Err(publication_input_error(
7346                "restored codebook changes its admitted logical content or original base",
7347            ));
7348        }
7349    }
7350    Ok(publication_abi_bytes(actual))
7351}
7352
7353fn publication_material_runtime() -> [u8; 32] {
7354    static IDENTITY: std::sync::OnceLock<[u8; 32]> = std::sync::OnceLock::new();
7355    *IDENTITY.get_or_init(|| {
7356        let mut hash = Sha256::new();
7357        hash.update(b"xlog.publication.material-runtime.v1\0");
7358        hash.update(include_bytes!("semantic_transition.rs"));
7359        hash.update(include_bytes!("semantic_transition/learning_phase.rs"));
7360        hash.update(include_bytes!("semantic_transition/prepared_replay.rs"));
7361        #[cfg(feature = "semantic-policy")]
7362        hash.update(include_bytes!("semantic_transition/model_evaluation.rs"));
7363        hash.update(include_bytes!("../kernels/semantic_transition.cu"));
7364        let policy_identity: [u8; 32] =
7365            include!(concat!(env!("OUT_DIR"), "/semantic_policy_identity.rs"));
7366        hash.update(policy_identity);
7367        #[cfg(feature = "semantic-policy")]
7368        hash.update(include_bytes!("../kernels/semantic_policy_binding.cuh"));
7369        hash.update(include_bytes!("../kernels/semantic_policy_domains.cuh"));
7370        hash.update(include_bytes!("semantic_hypergraph.rs"));
7371        hash.update(include_bytes!("../kernels/semantic_hypergraph.cu"));
7372        hash.finalize().into()
7373    })
7374}
7375
7376const RUNTIME_CONTRACT_MAGIC: &[u8] = b"XLOG-PUBLICATION-RUNTIME\0";
7377
7378/// Portable projection of the actual cold publication envelope. Mutable
7379/// extents, active rows, bank/instance identities and executable addresses do
7380/// not belong here. The original model contribution is retained in full.
7381fn runtime_contract_bytes(
7382    contract: PublicationContract,
7383    counts: &[u64; 55],
7384    terminals: &[u64],
7385    layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
7386    capacities: &[(u64, u64, usize)],
7387    model_mode: &[u8],
7388    model_memory: &ModelMemoryGeometry,
7389) -> Result<Vec<u8>, SemanticTransitionError> {
7390    if model_mode.is_empty() || model_mode.len() > 16 * 1024 * 1024 {
7391        return Err(publication_input_error(
7392            "runtime contract requires the complete bounded model numerical mode",
7393        ));
7394    }
7395    let mut bytes = RUNTIME_CONTRACT_MAGIC.to_vec();
7396    material_u32(&mut bytes, 1);
7397    bytes.extend_from_slice(&publication_material_runtime());
7398    material_bytes(&mut bytes, model_mode).map_err(SemanticTransitionError::Semantic)?;
7399    for field in [
7400        contract.abi,
7401        contract.range_capacity,
7402        contract.prefix_capacity,
7403        contract.window_capacity,
7404        contract.feedback_capacity,
7405        contract.max_position,
7406        contract.pad_token,
7407        contract.terminal_token_count,
7408        contract.final_intent_payload_bytes,
7409        contract.model_generation,
7410        contract.policy_generation,
7411        contract.authority_generation,
7412        contract.role_count,
7413    ] {
7414        material_u64(&mut bytes, field);
7415    }
7416    let model = contract.model_contract_layout;
7417    for field in [
7418        model.schema_begin,
7419        model.schema_bytes,
7420        model.schema_digest_offset,
7421        model.generation_offset,
7422        model.numerical_digest_offset,
7423        model.identity_offset,
7424    ] {
7425        material_u64(&mut bytes, field);
7426    }
7427    for identity in [
7428        contract.task_identity,
7429        contract.topology_identity,
7430        contract.table_identity,
7431    ] {
7432        bytes.extend_from_slice(identity.as_bytes());
7433    }
7434    for &count in counts {
7435        material_u64(&mut bytes, count);
7436    }
7437    for &token in terminals {
7438        material_u64(&mut bytes, token);
7439    }
7440    material_u64(&mut bytes, layouts.len() as u64);
7441    for layout in layouts.values() {
7442        for field in [
7443            layout.role,
7444            layout.index,
7445            layout.element_bytes,
7446            layout.scalar_type,
7447            layout.rank,
7448            layout.logical_axis,
7449        ]
7450        .into_iter()
7451        .chain(layout.dimensions)
7452        .chain(layout.strides_bytes)
7453        {
7454            material_u64(&mut bytes, field);
7455        }
7456    }
7457    material_u64(&mut bytes, capacities.len() as u64);
7458    for &(role, index, capacity) in capacities {
7459        for field in [role, index, capacity as u64] {
7460            material_u64(&mut bytes, field);
7461        }
7462    }
7463    model_memory.encode_into(&mut bytes)?;
7464    Ok(bytes)
7465}
7466
7467#[expect(
7468    clippy::too_many_arguments,
7469    reason = "the authenticated model mode is defined by independent publication owners"
7470)]
7471fn verified_runtime_model_mode<'a>(
7472    bytes: &'a [u8],
7473    contract: PublicationContract,
7474    counts: &[u64; 55],
7475    terminals: &[u64],
7476    layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
7477    capacities: &[(u64, u64, usize)],
7478    table: &PublicationMaterialRange,
7479    model_memory: &ModelMemoryGeometry,
7480) -> Result<&'a [u8], SemanticTransitionError> {
7481    // The host layout map is not evidence of published device bytes: public
7482    // record aliases retain the actual mutable allocation. Authenticate that
7483    // parent's entire original table, including its active-row state, first.
7484    if (table.range.role, table.range.index, table.range.generation) != (55, 0, 1)
7485        || table.range.length_bytes != table.bytes.len() as u64
7486        || table.bytes.len() > table.capacity
7487        || table.original_record_digest() != table.range.digest
7488    {
7489        return Err(SemanticTransitionError::ObservationMismatch);
7490    }
7491    let (_, actual_layouts, _) = decode_tensor_table(&table.bytes)?;
7492    if actual_layouts != layouts.values().copied().collect::<Vec<_>>() {
7493        return Err(publication_input_error(
7494            "publication material layout differs from its sealed table",
7495        ));
7496    }
7497    let mut reader = SemanticMaterialReader::new(bytes);
7498    if reader
7499        .take(RUNTIME_CONTRACT_MAGIC.len())
7500        .map_err(SemanticTransitionError::Semantic)?
7501        != RUNTIME_CONTRACT_MAGIC
7502        || reader.u32().map_err(SemanticTransitionError::Semantic)? != 1
7503        || reader.take(32).map_err(SemanticTransitionError::Semantic)?
7504            != publication_material_runtime()
7505    {
7506        return Err(publication_input_error(
7507            "unsupported native runtime contract format or identity",
7508        ));
7509    }
7510    let mode = reader.bytes().map_err(SemanticTransitionError::Semantic)?;
7511    // Comparing the complete explicit encoding validates the suffix, including
7512    // its exact length and all cold fields. Never overwrite the saved record.
7513    if runtime_contract_bytes(
7514        contract,
7515        counts,
7516        terminals,
7517        layouts,
7518        capacities,
7519        mode,
7520        model_memory,
7521    )? != bytes
7522    {
7523        return Err(publication_input_error(
7524            "runtime contract differs from actual cold publication state",
7525        ));
7526    }
7527    Ok(mode)
7528}
7529
7530fn initial_runtime_contract_record(
7531    contract: PublicationContract,
7532    counts: &[u64; 55],
7533    terminals: &[u64],
7534    layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
7535    mut capacities: Vec<(u64, u64, usize)>,
7536    model_mode: &[u8],
7537    model_memory: &ModelMemoryGeometry,
7538) -> Result<SemanticStateRecord, SemanticTransitionError> {
7539    if capacities.iter().any(|&(role, _, _)| role == 43) || counts[42] != 1 {
7540        return Err(publication_input_error(
7541            "runtime contract is generated exactly once by the native owner",
7542        ));
7543    }
7544    capacities.push((43, 0, 0));
7545    capacities.sort_by_key(|&(role, index, _)| (role, index));
7546    if capacities.len() != validate_publication_counts(counts)?
7547        || contract.range_capacity != capacities.len() as u64
7548    {
7549        return Err(publication_input_error(
7550            "runtime capacity roster differs from the actual publication directory",
7551        ));
7552    }
7553    // Only the value of a fixed-width capacity cell changes between passes.
7554    let capacity = runtime_contract_bytes(
7555        contract,
7556        counts,
7557        terminals,
7558        layouts,
7559        &capacities,
7560        model_mode,
7561        model_memory,
7562    )?
7563    .len();
7564    capacities.iter_mut().find(|entry| entry.0 == 43).unwrap().2 = capacity;
7565    let bytes = runtime_contract_bytes(
7566        contract,
7567        counts,
7568        terminals,
7569        layouts,
7570        &capacities,
7571        model_mode,
7572        model_memory,
7573    )?;
7574    debug_assert_eq!(bytes.len(), capacity);
7575    Ok(SemanticStateRecord {
7576        role: SemanticStateRole::RuntimeContract,
7577        index: 0,
7578        capacity_bytes: capacity,
7579        bytes,
7580    })
7581}
7582
7583// SAFETY: callers below name only fixed publication ABI records containing
7584// integer/IEEE scalar fields with all bit patterns valid. The exact ABI size is
7585// checked before reading; no pointer-bearing control records enter this codec.
7586unsafe fn publication_material_record<T: Copy>(
7587    reader: &mut SemanticMaterialReader<'_>,
7588) -> Result<T, SemanticTransitionError> {
7589    let bytes = reader.bytes().map_err(SemanticTransitionError::Semantic)?;
7590    if bytes.len() != size_of::<T>() {
7591        return Err(publication_input_error(
7592            "publication material record has another ABI extent",
7593        ));
7594    }
7595    Ok(unsafe { std::ptr::read_unaligned(bytes.as_ptr().cast::<T>()) })
7596}
7597
7598impl PublicationMaterial {
7599    fn model_numerical_mode(&self) -> Result<&[u8], SemanticTransitionError> {
7600        let record = self
7601            .ranges
7602            .iter()
7603            .find(|item| item.range.role == 43 && item.range.index == 0)
7604            .ok_or(SemanticTransitionError::ObservationMismatch)?;
7605        let table = self
7606            .ranges
7607            .iter()
7608            .find(|item| item.range.role == 55 && item.range.index == 0)
7609            .ok_or(SemanticTransitionError::ObservationMismatch)?;
7610        let capacities = self
7611            .ranges
7612            .iter()
7613            .map(|item| (item.range.role, item.range.index, item.capacity))
7614            .collect::<Vec<_>>();
7615        verified_runtime_model_mode(
7616            &record.bytes,
7617            self.contract,
7618            &self.role_counts,
7619            &self.terminals,
7620            &self.layouts,
7621            &capacities,
7622            table,
7623            &self.model_memory,
7624        )
7625    }
7626
7627    fn encode(&self) -> Result<Vec<u8>, SemanticTransitionError> {
7628        self.validate()?;
7629        let mut bytes = b"XLOG-PUBLICATION-MATERIAL\0".to_vec();
7630        material_u32(&mut bytes, 3);
7631        bytes.extend_from_slice(&publication_material_runtime());
7632        material_bytes(
7633            &mut bytes,
7634            &self
7635                .graph
7636                .encode()
7637                .map_err(SemanticTransitionError::Semantic)?,
7638        )
7639        .map_err(SemanticTransitionError::Semantic)?;
7640        for record in [
7641            publication_abi_bytes(&[self.bank]),
7642            publication_abi_bytes(&[self.contract]),
7643            publication_abi_bytes(&self.role_counts),
7644            publication_abi_bytes(&self.terminals),
7645        ] {
7646            material_bytes(&mut bytes, &record).map_err(SemanticTransitionError::Semantic)?;
7647        }
7648        material_u32(
7649            &mut bytes,
7650            u32::try_from(self.layouts.len())
7651                .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
7652        );
7653        for layout in self.layouts.values() {
7654            material_bytes(&mut bytes, &publication_abi_bytes(&[*layout]))
7655                .map_err(SemanticTransitionError::Semantic)?;
7656        }
7657        self.model_memory.encode_into(&mut bytes)?;
7658        for allocation in &self.model_allocations {
7659            material_bytes(&mut bytes, allocation).map_err(SemanticTransitionError::Semantic)?;
7660        }
7661        material_u32(
7662            &mut bytes,
7663            u32::try_from(self.ranges.len())
7664                .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
7665        );
7666        for range in &self.ranges {
7667            if matches!(range.range.role, 18..=25) {
7668                // Model bytes occur once per full backing allocation, including
7669                // padding and cells outside any individual typed view.
7670                material_bytes(&mut bytes, &publication_abi_bytes(&[range.range]))
7671                    .map_err(SemanticTransitionError::Semantic)?;
7672                material_u64(&mut bytes, range.capacity as u64);
7673            } else {
7674                range.encode_into(&mut bytes)?;
7675            }
7676        }
7677        learning_phase::encode_history(&self.learning_phases, &mut bytes)?;
7678        Ok(bytes)
7679    }
7680
7681    fn decode(bytes: &[u8]) -> Result<Self, SemanticTransitionError> {
7682        let mut reader = SemanticMaterialReader::new(bytes);
7683        if reader.take(26).map_err(SemanticTransitionError::Semantic)?
7684            != b"XLOG-PUBLICATION-MATERIAL\0"
7685            || reader.u32().map_err(SemanticTransitionError::Semantic)? != 3
7686            || reader.take(32).map_err(SemanticTransitionError::Semantic)?
7687                != publication_material_runtime()
7688        {
7689            return Err(publication_input_error(
7690                "publication material requires its exact pinned native runtime",
7691            ));
7692        }
7693        let graph_bytes = reader.bytes().map_err(SemanticTransitionError::Semantic)?;
7694        let limit = u32::try_from(graph_bytes.len()).unwrap_or(u32::MAX);
7695        let graph = SemanticRootMaterial::decode(
7696            graph_bytes,
7697            SemanticAdmissionLimits {
7698                max_records: limit,
7699                max_terms: limit,
7700                max_references: limit,
7701                max_utf8_bytes: graph_bytes.len(),
7702            },
7703        )
7704        .map_err(SemanticTransitionError::Semantic)?;
7705        // SAFETY: these fixed ABI records contain only all-bit-valid scalars.
7706        let bank = unsafe { publication_material_record::<PublicationBank>(&mut reader)? };
7707        let contract = unsafe { publication_material_record::<PublicationContract>(&mut reader)? };
7708        let role_counts = unsafe { publication_material_record::<[u64; 55]>(&mut reader)? };
7709        let terminal_bytes = reader.bytes().map_err(SemanticTransitionError::Semantic)?;
7710        if terminal_bytes.len() % 8 != 0 {
7711            return Err(publication_input_error(
7712                "publication terminal material is not integral",
7713            ));
7714        }
7715        let terminals = terminal_bytes
7716            .as_chunks::<8>()
7717            .0
7718            .iter()
7719            .map(|item| u64::from_le_bytes(*item))
7720            .collect();
7721        let count = reader
7722            .count(4 + size_of::<SemanticTensorLayout>())
7723            .map_err(SemanticTransitionError::Semantic)?;
7724        let mut layouts = BTreeMap::new();
7725        let mut previous = None;
7726        for _ in 0..count {
7727            // SAFETY: the tensor-layout ABI contains only integer fields.
7728            let layout =
7729                unsafe { publication_material_record::<SemanticTensorLayout>(&mut reader)? };
7730            let key = (layout.role, layout.index);
7731            if previous.is_some_and(|previous| previous >= key) {
7732                return Err(publication_input_error(
7733                    "publication material tensor layouts are not in canonical order",
7734                ));
7735            }
7736            previous = Some(key);
7737            layouts.insert(key, layout);
7738        }
7739        let model_memory = ModelMemoryGeometry::decode_from(&mut reader)?;
7740        model_memory.validate(&layouts)?;
7741        let mut model_allocations = Vec::new();
7742        for &extent in &model_memory.allocation_bytes {
7743            let allocation = reader.bytes().map_err(SemanticTransitionError::Semantic)?;
7744            if allocation.len() as u64 != extent {
7745                return Err(publication_input_error(
7746                    "publication material truncates a complete model backing allocation",
7747                ));
7748            }
7749            model_allocations.push(allocation.to_vec());
7750        }
7751        let count = reader
7752            .count(12 + size_of::<PublicationRange>())
7753            .map_err(SemanticTransitionError::Semantic)?;
7754        let mut ranges = Vec::with_capacity(count);
7755        for _ in 0..count {
7756            // SAFETY: the range ABI contains only integer/digest fields.
7757            let range = unsafe { publication_material_record::<PublicationRange>(&mut reader)? };
7758            let capacity =
7759                usize::try_from(reader.u64().map_err(SemanticTransitionError::Semantic)?).map_err(
7760                    |_| publication_input_error("publication material range capacity overflows"),
7761                )?;
7762            let payload = if matches!(range.role, 18..=25) {
7763                let (allocation, offset) = model_memory.location(range.role, range.index)?;
7764                let end = usize::try_from(range.length_bytes)
7765                    .ok()
7766                    .and_then(|bytes| offset.checked_add(bytes))
7767                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
7768                model_allocations[allocation]
7769                    .get(offset..end)
7770                    .ok_or(SemanticTransitionError::ObservationMismatch)?
7771            } else {
7772                reader.bytes().map_err(SemanticTransitionError::Semantic)?
7773            };
7774            ranges.push(PublicationMaterialRange {
7775                range,
7776                capacity,
7777                bytes: payload.to_vec(),
7778            });
7779        }
7780        let learning_phases = learning_phase::decode_history(&mut reader)?;
7781        reader.finish().map_err(SemanticTransitionError::Semantic)?;
7782        let material = Self {
7783            bank,
7784            contract,
7785            role_counts,
7786            terminals,
7787            layouts,
7788            model_memory,
7789            model_allocations,
7790            ranges,
7791            graph,
7792            learning_phases,
7793        };
7794        material.validate()?;
7795        for range in &material.ranges {
7796            if !is_tensor_role(range.range.role)
7797                && range.original_record_digest() != range.range.digest
7798            {
7799                return Err(publication_input_error(
7800                    "publication material changes an originally sealed native record",
7801                ));
7802            }
7803        }
7804        if material.original_descriptor_digest() != material.bank.header.descriptor_digest {
7805            return Err(publication_input_error(
7806                "publication material differs from its original descriptor seal",
7807            ));
7808        }
7809        Ok(material)
7810    }
7811
7812    // A retained successor carries the native attempt which published it.
7813    // This proves the selected publication has the recompute form without
7814    // inventing an application-side completion flag or retaining an old GPU
7815    // reader. Historical provenance still belongs to the trusted importer.
7816    fn require_current_model_caches(&self) -> Result<(), SemanticTransitionError> {
7817        let coverage = self
7818            .ranges
7819            .iter()
7820            .find(|r| (r.range.role, r.range.index) == (14, 0))
7821            .filter(|r| r.bytes.len() == size_of::<CompletionCoverage>())
7822            .ok_or(SemanticTransitionError::ObservationMismatch)?;
7823        // SAFETY: the exact-size, decoded native ABI contains integer records
7824        // only and permits unaligned retained checkpoint bytes.
7825        let coverage = unsafe {
7826            std::ptr::read_unaligned(coverage.bytes.as_ptr().cast::<CompletionCoverage>())
7827        };
7828        if coverage.abi != 1 || coverage.model_generation != self.bank.header.model_generation {
7829            return Err(publication_input_error(
7830                "effective model changed; original caches require a full recompute before use",
7831            ));
7832        }
7833        Ok(())
7834    }
7835
7836    fn require_successful_recompute(&self) -> Result<(), SemanticTransitionError> {
7837        self.require_current_model_caches()?;
7838        let header = self.bank.header;
7839        let next_word = (header.base_word >> 1)
7840            .checked_add(1)
7841            .filter(|epoch| *epoch <= u64::MAX >> 1)
7842            .map(|epoch| (epoch << 1) | ((header.base_word & 1) ^ 1))
7843            .ok_or(SemanticTransitionError::GenerationExhausted)?;
7844        let successor = SemanticPublishedIdentity {
7845            instance: header.instance,
7846            word: header.publication_word,
7847            logical_digest: header.logical_digest,
7848            state_digest: header.state_digest,
7849        };
7850        let ranges = REPLAY_EVIDENCE_ROLES
7851            .iter()
7852            .map(|&role| {
7853                self.ranges
7854                    .iter()
7855                    .find(|item| item.range.role == role && item.range.index == 0)
7856                    .cloned()
7857                    .ok_or(SemanticTransitionError::ObservationMismatch)
7858            })
7859            .collect::<Result<Vec<_>, _>>()?;
7860        let evidence = PublicationReplayEvidence { successor, ranges };
7861        let attempt = evidence.range(33)?.attempt()?;
7862        let coverage = self
7863            .ranges
7864            .iter()
7865            .find(|item| item.range.role == 14 && item.range.index == 0)
7866            .ok_or(SemanticTransitionError::ObservationMismatch)?;
7867        if header.abi != 1
7868            || header.publication_word != next_word
7869            || header.terminal != 0
7870            || attempt.abi != 2
7871            || attempt.transition_kind != 2
7872            || attempt.instance != header.instance
7873            || attempt.base_word != header.base_word
7874            || attempt.next_word != header.publication_word
7875            || attempt.logical_digest != header.logical_digest
7876            || attempt.action_receipts_digest != Identity256::from_bytes(Sha256::digest([]).into())
7877            || attempt.coverage_digest != coverage.logical_record_digest()?
7878            || attempt.replay_head_digest != evidence.range(27)?.logical_record_digest()?
7879            || attempt.intent_head_digest != evidence.range(30)?.logical_record_digest()?
7880            || attempt.acknowledgement_head_digest != evidence.range(32)?.logical_record_digest()?
7881            || attempt.previous_attempt_digest == Identity256::default()
7882            || attempt.receipt_digest != evidence.range(33)?.logical_record_digest()?
7883            || evidence.state_digest()? != header.state_digest
7884        {
7885            return Err(publication_input_error(
7886                "selected publication has no sealed successful recompute completion",
7887            ));
7888        }
7889        Ok(())
7890    }
7891
7892    // Match publication_descriptor_digest before any owner/slot relocation.
7893    // This unkeyed consistency seal is not proof of historical execution. The
7894    // native restore still hashes actual payloads, and the trusted importer
7895    // separately verifies the complete execution evidence and current rights.
7896    fn original_descriptor_digest(&self) -> Identity256 {
7897        let mut bank = self.bank;
7898        bank.header.abi = 1;
7899        bank.header.descriptor_digest = Identity256::default();
7900        let mut digest =
7901            Identity256::from_bytes(Sha256::digest(publication_abi_bytes(&[bank])).into());
7902        for material in &self.ranges {
7903            let range = material.range;
7904            let content =
7905                Identity256::from_bytes(Sha256::digest(publication_abi_bytes(&[range])).into());
7906            digest = publication_fold_digest(digest, range.role, range.index, content);
7907        }
7908        digest
7909    }
7910
7911    fn validate(&self) -> Result<(), SemanticTransitionError> {
7912        self.model_memory.validate(&self.layouts)?;
7913        let model = self
7914            .ranges
7915            .iter()
7916            .find(|item| (item.range.role, item.range.index) == (44, 0))
7917            .ok_or_else(|| {
7918                publication_input_error("publication material lacks its complete model contract")
7919            })?;
7920        self.contract
7921            .model_contract_layout
7922            .validate(model.bytes.len() as u64)?;
7923        if self.bank.header.model_geometry_digest != self.model_memory.digest(&self.layouts)? {
7924            return Err(publication_input_error(
7925                "publication model geometry differs from its original sealed map",
7926            ));
7927        }
7928        if self.model_allocations.len() != self.model_memory.allocation_bytes.len()
7929            || self
7930                .model_allocations
7931                .iter()
7932                .zip(&self.model_memory.allocation_bytes)
7933                .any(|(bytes, &extent)| bytes.len() as u64 != extent)
7934        {
7935            return Err(publication_input_error(
7936                "publication material lacks complete model backing bytes",
7937            ));
7938        }
7939        learning_phase::validate_history(self)?;
7940        let mut model_slots = BTreeMap::new();
7941        let mut slot_allocations = BTreeMap::new();
7942        let backing_digests = self
7943            .model_allocations
7944            .iter()
7945            .map(|bytes| Identity256::from_bytes(Sha256::digest(bytes).into()))
7946            .collect::<Vec<_>>();
7947        for item in self
7948            .ranges
7949            .iter()
7950            .filter(|item| matches!(item.range.role, 18..=25))
7951        {
7952            let (allocation, offset) = self
7953                .model_memory
7954                .location(item.range.role, item.range.index)?;
7955            let bytes = &self.model_allocations[allocation];
7956            let end = offset
7957                .checked_add(item.bytes.len())
7958                .ok_or(SemanticTransitionError::ObservationMismatch)?;
7959            if item.range.offset_bytes != offset as u64
7960                || item.capacity != bytes.len() - offset
7961                || bytes.get(offset..end) != Some(item.bytes.as_slice())
7962                || item.range.backing_digest != backing_digests[allocation]
7963                || model_slots
7964                    .insert(allocation, item.range.storage_slot)
7965                    .is_some_and(|slot| slot != item.range.storage_slot)
7966                || slot_allocations
7967                    .insert(item.range.storage_slot, allocation)
7968                    .is_some_and(|prior| prior != allocation)
7969            {
7970                return Err(publication_input_error(
7971                    "publication material changes model backing or view relationships",
7972                ));
7973            }
7974        }
7975        if self.ranges.iter().any(|item| {
7976            !matches!(item.range.role, 18..=25)
7977                && (slot_allocations.contains_key(&item.range.storage_slot)
7978                    || item.range.backing_digest != Identity256::default())
7979        }) {
7980            return Err(publication_input_error(
7981                "model backing aliases native control or cache storage",
7982            ));
7983        }
7984        let header = self.bank.header;
7985        let contract = self.contract;
7986        if !cfg!(target_endian = "little")
7987            || header.abi != 1
7988            || contract.abi != 1
7989            || header.sealed_epoch != header.publication_word >> 1
7990            || contract.terminal_tokens != 0
7991            || contract.role_counts != 0
7992            || contract.semantic_owner != 0
7993            || contract.window_capacity != 32
7994            || contract.role_count != 55
7995            || contract.terminal_token_count != self.terminals.len() as u64
7996            || contract.model_generation == 0
7997            || header.model_generation < contract.model_generation
7998            || u32::try_from(header.model_generation).is_err()
7999            || header.authority_generation != contract.authority_generation
8000            || header.semantic_digest.as_bytes() != &self.graph.digest
8001            || header.semantic_extents != self.graph.extents.map(u64::from)
8002            || validate_publication_counts(&self.role_counts)? != self.ranges.len()
8003            || header.range_count != self.ranges.len() as u64
8004            || contract.range_capacity != header.range_count
8005        {
8006            return Err(publication_input_error(
8007                "publication material header or graph differs from its complete owned state",
8008            ));
8009        }
8010        let mut ranges = self.ranges.iter();
8011        for (ordinal, &count) in self.role_counts.iter().enumerate() {
8012            let role = ordinal as u64 + 1;
8013            for index in 0..count {
8014                let item = ranges
8015                    .next()
8016                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
8017                if (item.range.role, item.range.index) != (role, index)
8018                    || item.range.generation != 1
8019                    || item.range.length_bytes != item.bytes.len() as u64
8020                    || (item.capacity == 0
8021                        && !self
8022                            .layouts
8023                            .get(&(role, index))
8024                            .is_some_and(empty_model_tensor_layout))
8025                    || item.bytes.len() > item.capacity
8026                    || item.range.logical_begin > item.range.logical_end
8027                {
8028                    return Err(publication_input_error(
8029                        "publication material omits, reorders or changes a reachable range",
8030                    ));
8031                }
8032                if is_tensor_role(role) {
8033                    let layout = self.layouts.get(&(role, index)).ok_or_else(|| {
8034                        publication_input_error("publication material omits a tensor layout")
8035                    })?;
8036                    if tensor_layout_bytes(layout)? > item.capacity
8037                        || (empty_model_tensor_layout(layout)
8038                            && (item.range.logical_begin != 0 || item.range.logical_end != 0))
8039                    {
8040                        return Err(publication_input_error(
8041                            "publication material tensor exceeds its actual capacity",
8042                        ));
8043                    }
8044                } else if self.layouts.contains_key(&(role, index)) {
8045                    return Err(publication_input_error(
8046                        "publication material gives a tensor layout to a native record",
8047                    ));
8048                }
8049            }
8050        }
8051        if self.layouts.len()
8052            != self
8053                .ranges
8054                .iter()
8055                .filter(|item| is_tensor_role(item.range.role))
8056                .count()
8057        {
8058            return Err(publication_input_error(
8059                "publication material has an undeclared tensor layout",
8060            ));
8061        }
8062        let acknowledgements = self
8063            .ranges
8064            .iter()
8065            .find(|item| (item.range.role, item.range.index) == (32, 0))
8066            .ok_or_else(|| {
8067                publication_input_error("publication material omits its acknowledgement queue")
8068            })?;
8069        let receipts =
8070            acknowledgement_receipts(&acknowledgements.bytes, acknowledgements.capacity)?;
8071        if !receipts.is_empty() {
8072            let entries = self
8073                .ranges
8074                .iter()
8075                .find(|item| (item.range.role, item.range.index) == (30, 0))
8076                .ok_or(SemanticTransitionError::ObservationMismatch)?;
8077            let payload = self
8078                .ranges
8079                .iter()
8080                .find(|item| (item.range.role, item.range.index) == (31, 0))
8081                .ok_or(SemanticTransitionError::ObservationMismatch)?;
8082            let intents = output_intents_from_ranges(entries, payload)?;
8083            if receipts.iter().any(|(identity, _)| {
8084                !intents
8085                    .iter()
8086                    .any(|intent| intent.stable_identity == *identity)
8087            }) {
8088                return Err(publication_input_error(
8089                    "publication acknowledges an absent native intent",
8090                ));
8091            }
8092        }
8093        self.model_numerical_mode()?;
8094        Ok(())
8095    }
8096}
8097
8098struct PublicationStorage {
8099    control: TrackedCudaSlice<PublicationControl>,
8100    banks: [TrackedCudaSlice<PublicationBank>; 2],
8101    directories: [TrackedCudaSlice<PublicationRange>; 2],
8102    storage: TrackedCudaSlice<PublicationStorageEntry>,
8103    contract: TrackedCudaSlice<PublicationContract>,
8104    role_counts: TrackedCudaSlice<PublicationRoleCount>,
8105    terminals: TrackedCudaSlice<u64>,
8106    continuation: TrackedCudaSlice<PendingContinuation>,
8107    continuation_directory: TrackedCudaSlice<PublicationRange>,
8108    allocations: Vec<TrackedCudaSlice<u8>>,
8109    model_memory: ModelMemoryGeometry,
8110    physical_parameter_roster: Option<Vec<String>>,
8111    model_slots: Vec<[usize; 2]>,
8112    bank_templates: [Vec<PublicationRange>; 2],
8113    continuation_templates: Vec<PublicationRange>,
8114    layouts: BTreeMap<(u64, u64), SemanticTensorLayout>,
8115    contract_value: PublicationContract,
8116    instance: Identity256,
8117}
8118
8119fn allocate_publication<T: DeviceRepr>(
8120    provider: &CudaKernelProvider,
8121    count: usize,
8122) -> Result<TrackedCudaSlice<T>, SemanticTransitionError> {
8123    provider
8124        .memory()
8125        .alloc::<T>(count)
8126        .map_err(|error| runtime_error("publication allocation", error))
8127}
8128
8129fn upload_publication<T: DeviceRepr>(
8130    provider: &CudaKernelProvider,
8131    values: &[T],
8132    destination: &TrackedCudaSlice<T>,
8133) -> Result<(), SemanticTransitionError> {
8134    let mut destination = destination.view();
8135    provider
8136        .htod_launch_metadata_sync_copy_into(values, &mut destination)
8137        .map_err(|error| runtime_error("publication cold metadata upload", error))
8138}
8139
8140#[cfg(feature = "semantic-policy")]
8141fn account_tracked_allocation<T: cudarc::driver::DeviceRepr>(
8142    allocations: &mut Vec<DeviceAllocationProvenance>,
8143    slice: &TrackedCudaSlice<T>,
8144) -> Result<(), SemanticTransitionError> {
8145    let provenance = slice
8146        .view()
8147        .allocation_provenance()
8148        .ok_or(SemanticTransitionError::ObservationMismatch)?;
8149    if !allocations
8150        .iter()
8151        .any(|known| provenance.same_allocation(known))
8152    {
8153        allocations.push(provenance);
8154    }
8155    Ok(())
8156}
8157
8158#[cfg(feature = "semantic-policy")]
8159fn accounted_tracked_bytes(
8160    allocations: Vec<DeviceAllocationProvenance>,
8161) -> Result<u64, SemanticTransitionError> {
8162    allocations.into_iter().try_fold(0u64, |total, allocation| {
8163        total
8164            .checked_add(allocation.allocation_bytes())
8165            .ok_or(SemanticTransitionError::GenerationExhausted)
8166    })
8167}
8168
8169impl PublicationStorage {
8170    fn continuation_block_contract(
8171        &self,
8172        kind: SemanticTransitionKind,
8173        input: &SemanticContinuationInput,
8174        prepared: bool,
8175    ) -> Result<(Option<usize>, Identity256, Identity256), SemanticTransitionError> {
8176        let expected = if kind == SemanticTransitionKind::Proposal {
8177            self.physical_parameter_roster.as_ref().map(Vec::len)
8178        } else {
8179            None
8180        };
8181        let host_identities = expected.is_some() && !prepared;
8182        if input.numerical_blocks.is_some() != expected.is_some()
8183            || input.model_schema_digest.is_some() != host_identities
8184            || input.model_identity.is_some() != host_identities
8185        {
8186            return Err(publication_input_error(
8187                "proposal block bounds require their original roster; only acquired replay accepts host model identities",
8188            ));
8189        }
8190        let schema = input.model_schema_digest.unwrap_or_default();
8191        let identity = input.model_identity.unwrap_or_default();
8192        if host_identities
8193            && (schema == Identity256::default() || identity == Identity256::default())
8194        {
8195            return Err(publication_input_error(
8196                "proposal block bounds require nonzero original model identities",
8197            ));
8198        }
8199        Ok((expected, schema, identity))
8200    }
8201
8202    #[cfg(feature = "semantic-policy")]
8203    fn accounted_allocation_bytes(&self) -> Result<u64, SemanticTransitionError> {
8204        let mut allocations = Vec::new();
8205        account_tracked_allocation(&mut allocations, &self.control)?;
8206        for bank in &self.banks {
8207            account_tracked_allocation(&mut allocations, bank)?;
8208        }
8209        for directory in &self.directories {
8210            account_tracked_allocation(&mut allocations, directory)?;
8211        }
8212        account_tracked_allocation(&mut allocations, &self.storage)?;
8213        account_tracked_allocation(&mut allocations, &self.contract)?;
8214        account_tracked_allocation(&mut allocations, &self.role_counts)?;
8215        account_tracked_allocation(&mut allocations, &self.terminals)?;
8216        account_tracked_allocation(&mut allocations, &self.continuation)?;
8217        account_tracked_allocation(&mut allocations, &self.continuation_directory)?;
8218        for allocation in &self.allocations {
8219            account_tracked_allocation(&mut allocations, allocation)?;
8220        }
8221        accounted_tracked_bytes(allocations)
8222    }
8223
8224    #[expect(
8225        clippy::too_many_arguments,
8226        reason = "the guard records each authenticated publication coordinate explicitly"
8227    )]
8228    fn enqueue_content_guard(
8229        &self,
8230        domain: &ResidentExecutionDomain,
8231        poisoned: &mut bool,
8232        reader: DeviceMemoryView<PublicationLease>,
8233        execute: &CudaFunction,
8234        role: u64,
8235        index: u64,
8236        layout: SemanticTensorLayout,
8237    ) -> Result<(), SemanticTransitionError> {
8238        let mut recorder = domain.new_strict_recorder();
8239        recorder.read(&reader);
8240        recorder.read(&self.control);
8241        recorder.read(&self.storage);
8242        recorder.read(&self.contract);
8243        for bank in &self.banks {
8244            recorder.read(bank);
8245        }
8246        for directory in &self.directories {
8247            recorder.read(directory);
8248        }
8249        for allocation in &self.allocations {
8250            recorder.read(allocation);
8251        }
8252        let arguments = (
8253            self.control.device_ptr_value(),
8254            role,
8255            index,
8256            layout,
8257            u64::from(is_tensor_role(role)),
8258            *reader.device_ptr(),
8259        );
8260        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
8261            // SAFETY: the original device lease selects its actual directory;
8262            // every selectable bank, range, seal and allocation remains owned.
8263            unsafe {
8264                execute.clone().launch_in(
8265                    enqueue,
8266                    LaunchConfig {
8267                        grid_dim: (1, 1, 1),
8268                        block_dim: (1, 1, 1),
8269                        shared_mem_bytes: 0,
8270                    },
8271                    arguments,
8272                )
8273            }
8274            .map_err(|error| XlogError::Kernel(error.to_string()))
8275        })
8276    }
8277
8278    #[expect(
8279        clippy::too_many_arguments,
8280        reason = "cold allocation consumes the complete independently owned publication contract"
8281    )]
8282    fn allocate(
8283        provider: &CudaKernelProvider,
8284        plans: &[PublicationAllocationPlan],
8285        layouts: BTreeMap<(u64, u64), SemanticTensorLayout>,
8286        model_memory: ModelMemoryGeometry,
8287        model_payloads: &[PublicationPayload],
8288        mut contract: PublicationContract,
8289        terminal_tokens: &[u64],
8290        instance: Identity256,
8291    ) -> Result<(Self, Vec<(usize, PublicationPayload)>), SemanticTransitionError> {
8292        let mut allocations = Vec::new();
8293        let mut bank_templates = [Vec::new(), Vec::new()];
8294        let mut uploads = Vec::new();
8295        model_memory.validate(&layouts)?;
8296        if model_payloads.len() != model_memory.allocation_bytes.len() {
8297            return Err(publication_input_error(
8298                "model backing upload roster differs from its complete memory map",
8299            ));
8300        }
8301        let physical_parameter_roster = plans
8302            .iter()
8303            .find(|plan| (plan.role, plan.index) == (44, 0))
8304            .and_then(|plan| match &plan.payload {
8305                PublicationPayload::Metadata(bytes) => Some(bytes.as_slice()),
8306                _ => None,
8307            })
8308            .map(|record| model_physical_parameter_roster(record, contract.model_contract_layout))
8309            .transpose()?
8310            .flatten();
8311        let mut model_slots = Vec::new();
8312        for (&bytes, payload) in model_memory.allocation_bytes.iter().zip(model_payloads) {
8313            let mut slots = [0; 2];
8314            for slot in &mut slots {
8315                *slot = allocations.len();
8316                allocations.push(allocate_publication::<u8>(provider, bytes as usize)?);
8317                uploads.push((*slot, payload.clone()));
8318            }
8319            model_slots.push(slots);
8320        }
8321        for plan in plans {
8322            if (plan.capacity == 0
8323                && !layouts
8324                    .get(&(plan.role, plan.index))
8325                    .is_some_and(empty_model_tensor_layout))
8326                || plan.length > plan.capacity
8327                || (layouts
8328                    .get(&(plan.role, plan.index))
8329                    .is_some_and(empty_model_tensor_layout)
8330                    && (plan.logical_begin != 0 || plan.logical_end != 0))
8331            {
8332                return Err(publication_input_error(
8333                    "owned publication allocation has invalid capacity",
8334                ));
8335            }
8336            let mut slot = 0;
8337            let model_view = if matches!(plan.role, 18..=25) {
8338                Some(model_memory.location(plan.role, plan.index)?)
8339            } else {
8340                None
8341            };
8342            for (bank, directory) in bank_templates.iter_mut().enumerate() {
8343                if let Some((allocation, offset)) = model_view {
8344                    slot = model_slots[allocation][bank];
8345                    if plan.capacity != allocations[slot].len() - offset {
8346                        return Err(publication_input_error(
8347                            "model range capacity differs from its actual backing view",
8348                        ));
8349                    }
8350                } else if bank == 0 || publication_mutable_role(plan.role) {
8351                    slot = allocations.len();
8352                    allocations.push(allocate_publication::<u8>(provider, plan.capacity)?);
8353                    uploads.push((slot, plan.payload.clone()));
8354                }
8355                directory.push(PublicationRange {
8356                    role: plan.role,
8357                    index: plan.index,
8358                    storage_slot: slot as u64,
8359                    generation: 1,
8360                    offset_bytes: model_view.map_or(0, |(_, offset)| offset as u64),
8361                    length_bytes: plan.length as u64,
8362                    logical_begin: plan.logical_begin,
8363                    logical_end: plan.logical_end,
8364                    digest: Identity256::default(),
8365                    backing_digest: Identity256::default(),
8366                });
8367            }
8368        }
8369        let pending_layouts = layouts
8370            .values()
8371            .filter(|layout| continuation_role(layout.role))
8372            .map(|layout| continuation_allocation_layout(*layout))
8373            .collect::<Result<Vec<_>, _>>()?;
8374        let pending_table = tensor_table_bytes(&pending_layouts, true, &[])?;
8375        let mut continuation_templates = Vec::new();
8376        for plan in plans.iter().filter(|plan| continuation_role(plan.role)) {
8377            let capacity = if plan.role == 1 {
8378                32 * size_of::<SemanticTextSlot>()
8379            } else if plan.role == 39 {
8380                plan.capacity
8381            } else if plan.role == 55 {
8382                tensor_table_capacity(pending_layouts.len(), 32 + contract.feedback_capacity)?
8383            } else {
8384                tensor_layout_bytes(&continuation_allocation_layout(
8385                    layouts[&(plan.role, plan.index)],
8386                )?)?
8387            };
8388            if capacity == 0 {
8389                return Err(publication_input_error(
8390                    "continuation destination has no actual capacity",
8391                ));
8392            }
8393            let slot = allocations.len();
8394            allocations.push(allocate_publication::<u8>(provider, capacity)?);
8395            let length = if plan.role == 55 {
8396                uploads.push((slot, PublicationPayload::Metadata(pending_table.clone())));
8397                pending_table.len()
8398            } else if matches!(plan.role, 1 | 39) {
8399                0
8400            } else {
8401                capacity
8402            };
8403            continuation_templates.push(PublicationRange {
8404                role: plan.role,
8405                index: plan.index,
8406                storage_slot: slot as u64,
8407                generation: 1,
8408                length_bytes: length as u64,
8409                ..PublicationRange::default()
8410            });
8411        }
8412        let terminals = allocate_publication::<u64>(provider, terminal_tokens.len())?;
8413        let role_counts = allocate_publication::<PublicationRoleCount>(provider, 55)?;
8414        contract.terminal_tokens = terminals.device_ptr_value();
8415        contract.role_counts = role_counts.device_ptr_value();
8416        let contract_value = contract;
8417        Ok((
8418            Self {
8419                control: allocate_publication(provider, 1)?,
8420                banks: [
8421                    allocate_publication(provider, 1)?,
8422                    allocate_publication(provider, 1)?,
8423                ],
8424                directories: [
8425                    allocate_publication(provider, plans.len())?,
8426                    allocate_publication(provider, plans.len())?,
8427                ],
8428                storage: allocate_publication(provider, allocations.len())?,
8429                contract: allocate_publication(provider, 1)?,
8430                role_counts,
8431                terminals,
8432                continuation: allocate_publication(provider, 1)?,
8433                continuation_directory: allocate_publication(
8434                    provider,
8435                    continuation_templates.len(),
8436                )?,
8437                allocations,
8438                model_memory,
8439                physical_parameter_roster,
8440                model_slots,
8441                bank_templates,
8442                continuation_templates,
8443                layouts,
8444                contract_value,
8445                instance,
8446            },
8447            uploads,
8448        ))
8449    }
8450
8451    fn record(&self, recorder: &mut LaunchRecorder) {
8452        recorder.read_write(&self.control);
8453        for bank in &self.banks {
8454            recorder.read_write(bank);
8455        }
8456        for directory in &self.directories {
8457            recorder.read_write(directory);
8458        }
8459        recorder.read(&self.storage);
8460        recorder.read(&self.contract);
8461        recorder.read(&self.role_counts);
8462        recorder.read(&self.terminals);
8463        recorder.read_write(&self.continuation);
8464        recorder.read_write(&self.continuation_directory);
8465        for allocation in &self.allocations {
8466            recorder.read_write(allocation);
8467        }
8468    }
8469}
8470
8471struct PreparedContinuation {
8472    storage: Arc<PublicationStorage>,
8473    reader: DeviceMemoryView<PublicationLease>,
8474    text_binding: Arc<TextBindingStorage>,
8475    sources: Vec<PreparedSemanticTensor>,
8476    copies: Vec<(u64, u64, usize)>,
8477    inputs: ContinuationInputs,
8478    training_selection: Option<DeviceMemoryView<SemanticTrainingViewSelection>>,
8479    execute: CudaFunction,
8480}
8481
8482type ContinuationPayloadPlan = (
8483    Vec<(usize, PublicationPayload)>,
8484    BTreeMap<(u64, u64), SemanticTensorLayout>,
8485);
8486
8487fn prepare_continuation_payloads(
8488    storage: &PublicationStorage,
8489    original: &[PreparedSemanticTensor],
8490    authority_decisions: &[u8],
8491    kind: SemanticTransitionKind,
8492) -> Result<ContinuationPayloadPlan, SemanticTransitionError> {
8493    let mut pending_layouts = BTreeMap::new();
8494    let mut inputs = BTreeMap::new();
8495    for tensor in original {
8496        let key = (tensor.layout.role, tensor.layout.index);
8497        let model = storage.layouts.get(&key).ok_or_else(|| {
8498            publication_input_error("continuation tensor has no cold model owner")
8499        })?;
8500        if !continuation_role(key.0) || !is_tensor_role(key.0) || inputs.contains_key(&key) {
8501            return Err(publication_input_error(
8502                "continuation tensor type or role differs from the model",
8503            ));
8504        }
8505        let destination = continuation_tensor_layout_for_kind(
8506            &tensor.layout,
8507            tensor.logical_begin,
8508            tensor.logical_end,
8509            model,
8510            kind,
8511        )?;
8512        pending_layouts.insert(key, destination);
8513        inputs.insert(key, tensor.clone());
8514    }
8515    let mut uploads = Vec::new();
8516    for range in &storage.continuation_templates {
8517        let key = (range.role, range.index);
8518        if matches!(range.role, 1 | 55) {
8519            continue;
8520        }
8521        let payload = if range.role == 39 {
8522            PublicationPayload::Metadata(authority_decisions.to_vec())
8523        } else {
8524            PublicationPayload::Tensor(inputs.remove(&key).ok_or_else(|| {
8525                publication_input_error("continuation omits an actual required forward tensor")
8526            })?)
8527        };
8528        let length = match &payload {
8529            PublicationPayload::Metadata(bytes) => bytes.len(),
8530            PublicationPayload::Tensor(_) => tensor_layout_bytes(&pending_layouts[&key])?,
8531            PublicationPayload::Uncomputed => {
8532                unreachable!("continuation accepts original computed tensors only")
8533            }
8534        };
8535        if length > storage.allocations[range.storage_slot as usize].len() {
8536            return Err(publication_input_error(
8537                "actual continuation exceeds its owned fixed destination capacity",
8538            ));
8539        }
8540        uploads.push((range.storage_slot as usize, payload));
8541    }
8542    if !inputs.is_empty() {
8543        return Err(publication_input_error(
8544            "continuation contains an undeclared tensor owner",
8545        ));
8546    }
8547    Ok((uploads, pending_layouts))
8548}
8549
8550impl PreparedContinuation {
8551    // Cold geometry and owner preparation. Counts remain original device
8552    // pointers in inputs; this never snapshots their values or changes layout.
8553    #[expect(
8554        clippy::too_many_arguments,
8555        reason = "continuation preparation binds all retained producer and publication owners"
8556    )]
8557    fn prepare(
8558        provider: &CudaKernelProvider,
8559        storage: Arc<PublicationStorage>,
8560        reader: DeviceMemoryView<PublicationLease>,
8561        text_binding: Arc<TextBindingStorage>,
8562        inputs: ContinuationInputs,
8563        training_selection: Option<DeviceMemoryView<SemanticTrainingViewSelection>>,
8564        uploads: &[(usize, PublicationPayload)],
8565        layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
8566    ) -> Result<Self, SemanticTransitionError> {
8567        let mut sources = Vec::new();
8568        let mut copies = Vec::new();
8569        for (slot, payload) in uploads {
8570            let PublicationPayload::Tensor(tensor) = payload else {
8571                continue;
8572            };
8573            let destination = storage
8574                .allocations
8575                .get(*slot)
8576                .ok_or(SemanticTransitionError::ObservationMismatch)?;
8577            if let Some(source) = &tensor.source {
8578                let layout = layouts
8579                    .get(&(tensor.layout.role, tensor.layout.index))
8580                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
8581                for (source_offset, destination_offset, bytes) in
8582                    tensor_copy_plan(&tensor.layout, layout)?
8583                {
8584                    if source_offset
8585                        .checked_add(bytes as u64)
8586                        .is_none_or(|end| end > source.len() as u64)
8587                        || destination_offset
8588                            .checked_add(bytes as u64)
8589                            .is_none_or(|end| end > destination.len() as u64)
8590                    {
8591                        return Err(SemanticTransitionError::ObservationMismatch);
8592                    }
8593                    let source = source
8594                        .device_ptr()
8595                        .checked_add(source_offset)
8596                        .ok_or(SemanticTransitionError::ObservationMismatch)?;
8597                    let destination = destination
8598                        .device_ptr_value()
8599                        .checked_add(destination_offset)
8600                        .ok_or(SemanticTransitionError::ObservationMismatch)?;
8601                    copies.push((source, destination, bytes));
8602                }
8603            }
8604            // Empty tensors retain their real producer token as well.
8605            sources.push(tensor.clone());
8606        }
8607        let execute = provider
8608            .device()
8609            .inner()
8610            .get_func(
8611                "xlog_semantic_transition",
8612                "semantic_publication_prepare_continuation",
8613            )
8614            .ok_or_else(|| {
8615                runtime_error("kernel lookup", "continuation preparation unavailable")
8616            })?;
8617        Ok(Self {
8618            storage,
8619            reader,
8620            text_binding,
8621            sources,
8622            copies,
8623            inputs,
8624            training_selection,
8625            execute,
8626        })
8627    }
8628
8629    // Enqueue only: original source owners, fixed copy spans and the kernel
8630    // are already prepared. Authority upload and stream joins belong outside.
8631    fn enqueue(
8632        &self,
8633        domain: &ResidentExecutionDomain,
8634        poisoned: &mut bool,
8635    ) -> Result<(), SemanticTransitionError> {
8636        let mut recorder = domain.new_strict_recorder();
8637        self.storage.record(&mut recorder);
8638        recorder.read(&self.reader);
8639        self.text_binding.record(&mut recorder);
8640        if let Some(selection) = &self.training_selection {
8641            recorder.read(selection);
8642        }
8643        for tensor in &self.sources {
8644            if let Some(source) = &tensor.source {
8645                recorder.read(source);
8646            }
8647        }
8648        let arguments = (
8649            self.storage.control.device_ptr_value(),
8650            *self.reader.device_ptr(),
8651            self.inputs,
8652        );
8653        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
8654            for &(source, destination, bytes) in &self.copies {
8655                // SAFETY: cold geometry bounds both addresses to the original
8656                // witnessed source and retained fixed destination allocation.
8657                unsafe {
8658                    sys::cuMemcpyDtoDAsync_v2(
8659                        destination,
8660                        source,
8661                        bytes,
8662                        enqueue.stream().cu_stream(),
8663                    )
8664                }
8665                .result()
8666                .map_err(|error| XlogError::Kernel(error.to_string()))?;
8667            }
8668            // SAFETY: the actual acquired reader, original service producers
8669            // and complete pending storage share this recorded lifetime.
8670            unsafe {
8671                self.execute.clone().launch_in(
8672                    enqueue,
8673                    LaunchConfig {
8674                        grid_dim: (1, 1, 1),
8675                        block_dim: (1, 1, 1),
8676                        shared_mem_bytes: 0,
8677                    },
8678                    arguments,
8679                )
8680            }
8681            .map_err(|error| XlogError::Kernel(error.to_string()))
8682        })
8683    }
8684}
8685
8686struct PublishedReader {
8687    device: TrackedCudaSlice<PublicationLease>,
8688    aliases: Arc<()>,
8689    consumer_streams: BTreeSet<u64>,
8690}
8691
8692#[repr(C)]
8693#[derive(Clone, Copy)]
8694struct PublicationStepInput {
8695    role: u64,
8696    index: u64,
8697    destination: u64,
8698    capacity_bytes: u64,
8699    backing: u64,
8700    backing_bytes: u64,
8701    layout: SemanticTensorLayout,
8702}
8703
8704// SAFETY: the fixed CUDA ABI contains only u64 words and the checked tensor layout.
8705unsafe impl DeviceRepr for PublicationStepInput {}
8706const _: () = assert!(size_of::<PublicationStepInput>() == 160);
8707
8708#[derive(Clone, Debug)]
8709struct StepInputBankPlan {
8710    storage_slot: usize,
8711    span: std::ops::Range<usize>,
8712}
8713
8714#[derive(Clone)]
8715struct StepInputPlan {
8716    role: u64,
8717    index: u64,
8718    layout: SemanticTensorLayout,
8719    banks: [StepInputBankPlan; 2],
8720}
8721
8722fn step_input_overlap(
8723    data: u64,
8724    bytes: usize,
8725    base: u64,
8726    capacity: usize,
8727) -> Result<bool, SemanticTransitionError> {
8728    let end = data
8729        .checked_add(bytes as u64)
8730        .ok_or(SemanticTransitionError::ObservationMismatch)?;
8731    let limit = base
8732        .checked_add(capacity as u64)
8733        .ok_or(SemanticTransitionError::ObservationMismatch)?;
8734    Ok(if bytes == 0 {
8735        data >= base && data < limit
8736    } else {
8737        data < limit && base < end
8738    })
8739}
8740
8741fn plan_step_inputs(
8742    banks: &[Vec<PublicationRange>; 2],
8743    layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
8744    prefix_capacity: u64,
8745    allocation_bytes: &[usize],
8746) -> Result<Vec<StepInputPlan>, SemanticTransitionError> {
8747    let mut expected = BTreeSet::from([(1, 0), (3, 0), (15, 0), (16, 0), (17, 0), (44, 0)]);
8748    expected.extend(
8749        banks[0]
8750            .iter()
8751            .filter(|range| matches!(range.role, 16 | 17))
8752            .map(|range| (range.role, range.index)),
8753    );
8754    for (&key, layout) in layouts
8755        .iter()
8756        .filter(|(key, _)| matches!(key.0, 4..=13 | 18..=25))
8757    {
8758        let model = matches!(key.0, 18..=25);
8759        let bytes = tensor_layout_bytes(layout)?;
8760        if key != (layout.role, layout.index)
8761            || (!model && (canonical_tensor_layout(*layout)? != *layout || bytes == 0))
8762            || (model && layout.logical_axis != u64::MAX)
8763        {
8764            return Err(publication_input_error(
8765                "step input must retain its original tensor layout",
8766            ));
8767        }
8768        expected.insert(key);
8769    }
8770    for role in (4..=13).chain(15..=25) {
8771        for (index, key) in expected.iter().filter(|key| key.0 == role).enumerate() {
8772            if key.1 != index as u64 {
8773                return Err(publication_input_error(
8774                    "step input tensor indexes must be contiguous",
8775                ));
8776            }
8777        }
8778    }
8779    for bank in banks {
8780        let actual = bank
8781            .iter()
8782            .filter(|range| matches!(range.role, 1 | 3..=13 | 15..=25 | 44))
8783            .map(|range| (range.role, range.index))
8784            .collect::<Vec<_>>();
8785        if actual.len() != expected.len()
8786            || actual.iter().copied().collect::<BTreeSet<_>>() != expected
8787        {
8788            return Err(publication_input_error(
8789                "step input banks must have the exact original input roster",
8790            ));
8791        }
8792    }
8793    let mut plan = Vec::with_capacity(expected.len());
8794    let mut spans = Vec::new();
8795    for (role, index) in expected {
8796        let ranges = banks.each_ref().map(|bank| {
8797            *bank
8798                .iter()
8799                .find(|range| (range.role, range.index) == (role, index))
8800                .expect("validated input roster")
8801        });
8802        let layout = if role == 1 {
8803            committed_prefix_layout(&ranges[0], prefix_capacity)?
8804        } else if matches!(role, 3 | 15..=17 | 44) {
8805            SemanticTensorLayout {
8806                role,
8807                index,
8808                scalar_type: 1,
8809                element_bytes: 1,
8810                rank: 1,
8811                logical_axis: u64::MAX,
8812                dimensions: [ranges[0].length_bytes, 0, 0, 0],
8813                strides_bytes: [1, 0, 0, 0],
8814            }
8815        } else {
8816            layouts[&(role, index)]
8817        };
8818        let bytes = tensor_layout_bytes(&layout)?;
8819        if (bytes == 0 && !matches!(role, 18..=25))
8820            || (role == 3 && ranges.iter().any(|range| range.length_bytes != 32))
8821        {
8822            return Err(publication_input_error(
8823                "step input has no complete fixed physical capacity",
8824            ));
8825        }
8826        if matches!(role, 15..=17)
8827            && ranges.iter().any(|range| {
8828                range.logical_begin != 0
8829                    || if role == 15 {
8830                        range.length_bytes % size_of::<RawFeedbackRecord>() as u64 != 0
8831                            || range.logical_end
8832                                > range.length_bytes / size_of::<RawFeedbackRecord>() as u64
8833                    } else {
8834                        range.logical_end != 0
8835                    }
8836            })
8837        {
8838            return Err(publication_input_error(
8839                "raw feedback input differs from its original record extent",
8840            ));
8841        }
8842        let mut resolved = Vec::with_capacity(2);
8843        for (bank, range) in ranges.iter().enumerate() {
8844            if role == 1 {
8845                committed_prefix_layout(range, prefix_capacity)?;
8846            }
8847            let slot = usize::try_from(range.storage_slot)
8848                .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
8849            let capacity = *allocation_bytes
8850                .get(slot)
8851                .ok_or(SemanticTransitionError::ObservationMismatch)?;
8852            let span = publication_export_span(range, &layout, capacity)?;
8853            if span.len() != bytes {
8854                return Err(publication_input_error(
8855                    "step input differs from its full typed capacity",
8856                ));
8857            }
8858            spans.push((bank, role, index, slot, span.clone()));
8859            resolved.push((slot, span, capacity));
8860        }
8861        if role == 1 && resolved[0] != resolved[1] {
8862            return Err(publication_input_error(
8863                "prefix step inputs must share their original capacity allocation",
8864            ));
8865        }
8866        if matches!(role, 4 | 5 | 15 | 18..=25 | 44)
8867            && (resolved[0].0 == resolved[1].0
8868                || resolved[0].1 != resolved[1].1
8869                || resolved[0].2 != resolved[1].2)
8870        {
8871            return Err(publication_input_error("bank-selected step inputs require disjoint banks with the same complete backing geometry"));
8872        }
8873        plan.push(StepInputPlan {
8874            role,
8875            index,
8876            layout,
8877            banks: resolved
8878                .into_iter()
8879                .map(
8880                    |(storage_slot, span, _allocation_bytes)| StepInputBankPlan {
8881                        storage_slot,
8882                        span,
8883                    },
8884                )
8885                .collect::<Vec<_>>()
8886                .try_into()
8887                .expect("two publication banks"),
8888        });
8889    }
8890    for (ordinal, (bank, role, index, slot, span)) in spans.iter().enumerate() {
8891        for (other_bank, other_role, other_index, other_slot, other_span) in &spans[..ordinal] {
8892            let same_shared = bank != other_bank
8893                && role == other_role
8894                && index == other_index
8895                && slot == other_slot
8896                && span == other_span
8897                && matches!(*role, 1 | 16 | 17);
8898            let same_model =
8899                bank == other_bank && matches!(*role, 18..=25) && matches!(*other_role, 18..=25);
8900            if slot == other_slot
8901                && span.start < other_span.end
8902                && other_span.start < span.end
8903                && !same_shared
8904                && !same_model
8905            {
8906                return Err(publication_input_error(
8907                    "step input caches and distinct tensor ranges must be isolated",
8908                ));
8909            }
8910        }
8911    }
8912    Ok(plan)
8913}
8914
8915/// Fixed inputs are prepared without a host choice of publication bank. The
8916/// producer resolves the actual device lease and preserves its original seals.
8917struct PreparedStepInputs {
8918    storage: Arc<PublicationStorage>,
8919    reader: DeviceMemoryView<PublicationLease>,
8920    header: TrackedCudaSlice<PublicationHeader>,
8921    source: TrackedCudaSlice<SourceSlot>,
8922    ranges: TrackedCudaSlice<PublicationRange>,
8923    metadata_digests: TrackedCudaSlice<u64>,
8924    bindings: [TrackedCudaSlice<PublicationStepInput>; 2],
8925    binding_values: [Vec<PublicationStepInput>; 2],
8926    plans: Vec<StepInputPlan>,
8927    views: [BTreeMap<(u64, u64), DeviceMemoryView<u8>>; 2],
8928    private: Vec<TrackedCudaSlice<u8>>,
8929    execute: CudaFunction,
8930    guard: CudaFunction,
8931    completed_guard: CudaFunction,
8932}
8933
8934impl PreparedStepInputs {
8935    fn plan(storage: &PublicationStorage) -> Result<Vec<StepInputPlan>, SemanticTransitionError> {
8936        plan_step_inputs(
8937            &storage.bank_templates,
8938            &storage.layouts,
8939            storage.contract_value.prefix_capacity,
8940            &storage
8941                .allocations
8942                .iter()
8943                .map(TrackedCudaSlice::len)
8944                .collect::<Vec<_>>(),
8945        )
8946    }
8947
8948    fn allocation_bytes(plans: &[StepInputPlan]) -> Result<usize, SemanticTransitionError> {
8949        let fixed =
8950            size_of::<PublicationHeader>() + 32 * size_of::<SourceSlot>() + u64::BITS as usize;
8951        let bytes = plans
8952            .len()
8953            .checked_mul(size_of::<PublicationRange>() + 2 * size_of::<PublicationStepInput>())
8954            .and_then(|n| n.checked_add(fixed))
8955            .ok_or(SemanticTransitionError::GenerationExhausted)?;
8956        plans
8957            .iter()
8958            .filter(|input| !matches!(input.role, 1 | 4 | 5 | 18..=25))
8959            .try_fold(bytes, |sum, input| {
8960                sum.checked_add(input.banks[0].span.len())
8961                    .ok_or(SemanticTransitionError::GenerationExhausted)
8962            })
8963    }
8964
8965    fn allocate(
8966        provider: &CudaKernelProvider,
8967        storage: Arc<PublicationStorage>,
8968        reader: DeviceMemoryView<PublicationLease>,
8969    ) -> Result<Self, SemanticTransitionError> {
8970        let plans = Self::plan(&storage)?;
8971        let mut reservation = provider
8972            .memory()
8973            .reserve_bytes(Self::allocation_bytes(&plans)? as u64)
8974            .map_err(|error| runtime_error("step input reservation", error))?;
8975        Self::allocate_reserved(provider, storage, reader, plans, &mut reservation)
8976    }
8977
8978    fn allocate_reserved(
8979        provider: &CudaKernelProvider,
8980        storage: Arc<PublicationStorage>,
8981        reader: DeviceMemoryView<PublicationLease>,
8982        plans: Vec<StepInputPlan>,
8983        reservation: &mut GpuMemoryReservation,
8984    ) -> Result<Self, SemanticTransitionError> {
8985        let contract = storage.contract_value;
8986        if contract.abi != 1
8987            || contract.model_generation == 0
8988            || contract.window_capacity != 32
8989            || reader.len() != 1
8990        {
8991            return Err(publication_input_error(
8992                "fixed step inputs require the original admitted model contract and device reader",
8993            ));
8994        }
8995        let execute = provider
8996            .device()
8997            .inner()
8998            .get_func(
8999                "xlog_semantic_transition",
9000                "semantic_publication_step_inputs",
9001            )
9002            .ok_or_else(|| {
9003                runtime_error(
9004                    "kernel lookup",
9005                    "publication step input producer unavailable",
9006                )
9007            })?;
9008        let guard = provider
9009            .device()
9010            .inner()
9011            .get_func(
9012                "xlog_semantic_transition",
9013                "semantic_publication_step_input_guard",
9014            )
9015            .ok_or_else(|| {
9016                runtime_error("kernel lookup", "publication step input guard unavailable")
9017            })?;
9018        let mut private = Vec::new();
9019        let completed_guard = provider
9020            .device()
9021            .inner()
9022            .get_func(
9023                "xlog_semantic_transition",
9024                "semantic_completed_step_input_guard",
9025            )
9026            .ok_or_else(|| runtime_error("kernel lookup", "completed input guard unavailable"))?;
9027        let mut views = [BTreeMap::new(), BTreeMap::new()];
9028        let mut binding_values = [
9029            Vec::with_capacity(plans.len()),
9030            Vec::with_capacity(plans.len()),
9031        ];
9032        for input in &plans {
9033            if matches!(input.role, 1 | 4 | 5 | 18..=25) {
9034                for bank in 0..2 {
9035                    let plan = &input.banks[bank];
9036                    let view = storage.allocations[plan.storage_slot]
9037                        .view()
9038                        .slice(plan.span.clone());
9039                    let backing = if matches!(input.role, 18..=25) {
9040                        view.allocation_view()
9041                            .ok_or(SemanticTransitionError::ObservationMismatch)?
9042                    } else {
9043                        view.clone()
9044                    };
9045                    binding_values[bank].push(PublicationStepInput {
9046                        role: input.role,
9047                        index: input.index,
9048                        destination: *view.device_ptr(),
9049                        capacity_bytes: view.len() as u64,
9050                        backing: *backing.device_ptr(),
9051                        backing_bytes: backing.len() as u64,
9052                        layout: input.layout,
9053                    });
9054                    views[bank].insert((input.role, input.index), view);
9055                }
9056            } else {
9057                private.push(
9058                    reservation
9059                        .alloc::<u8>(input.banks[0].span.len())
9060                        .map_err(|error| runtime_error("step private input allocation", error))?,
9061                );
9062                let view = private
9063                    .last()
9064                    .expect("retained private input allocation")
9065                    .view();
9066                for bank in 0..2 {
9067                    binding_values[bank].push(PublicationStepInput {
9068                        role: input.role,
9069                        index: input.index,
9070                        destination: *view.device_ptr(),
9071                        capacity_bytes: view.len() as u64,
9072                        backing: *view.device_ptr(),
9073                        backing_bytes: view.len() as u64,
9074                        layout: if matches!(input.role, 3 | 15..=17 | 44) {
9075                            SemanticTensorLayout::default()
9076                        } else {
9077                            input.layout
9078                        },
9079                    });
9080                    views[bank].insert((input.role, input.index), view.clone());
9081                }
9082            }
9083        }
9084        let owner = Self {
9085            header: reservation
9086                .alloc(1)
9087                .map_err(|error| runtime_error("step header allocation", error))?,
9088            source: reservation
9089                .alloc(32)
9090                .map_err(|error| runtime_error("step source allocation", error))?,
9091            ranges: reservation
9092                .alloc(plans.len())
9093                .map_err(|error| runtime_error("step range allocation", error))?,
9094            metadata_digests: reservation
9095                .alloc(8)
9096                .map_err(|error| runtime_error("step digest allocation", error))?,
9097            bindings: [
9098                reservation
9099                    .alloc(plans.len())
9100                    .map_err(|error| runtime_error("step binding allocation", error))?,
9101                reservation
9102                    .alloc(plans.len())
9103                    .map_err(|error| runtime_error("step binding allocation", error))?,
9104            ],
9105            storage,
9106            reader,
9107            plans,
9108            views,
9109            private,
9110            binding_values,
9111            execute,
9112            guard,
9113            completed_guard,
9114        };
9115        owner.validate_output_regions()?;
9116        Ok(owner)
9117    }
9118
9119    fn validate_output_regions(&self) -> Result<(), SemanticTransitionError> {
9120        let mut output = vec![
9121            (
9122                self.header.device_ptr_value(),
9123                size_of::<PublicationHeader>(),
9124            ),
9125            (self.source.device_ptr_value(), 32 * size_of::<SourceSlot>()),
9126            (
9127                self.ranges.device_ptr_value(),
9128                self.ranges.len() * size_of::<PublicationRange>(),
9129            ),
9130            (self.metadata_digests.device_ptr_value(), u64::BITS as usize),
9131            (
9132                self.bindings[0].device_ptr_value(),
9133                self.bindings[0].len() * size_of::<PublicationStepInput>(),
9134            ),
9135            (
9136                self.bindings[1].device_ptr_value(),
9137                self.bindings[1].len() * size_of::<PublicationStepInput>(),
9138            ),
9139        ];
9140        output.extend(
9141            self.private
9142                .iter()
9143                .map(|allocation| (allocation.device_ptr_value(), allocation.len())),
9144        );
9145        let mut original = self
9146            .storage
9147            .allocations
9148            .iter()
9149            .map(|allocation| (allocation.device_ptr_value(), allocation.len()))
9150            .collect::<Vec<_>>();
9151        original.extend(
9152            self.storage
9153                .banks
9154                .iter()
9155                .map(|bank| (bank.device_ptr_value(), size_of::<PublicationBank>())),
9156        );
9157        original.extend(self.storage.directories.iter().map(|directory| {
9158            (
9159                directory.device_ptr_value(),
9160                directory.len() * size_of::<PublicationRange>(),
9161            )
9162        }));
9163        original.extend([
9164            (*self.reader.device_ptr(), size_of::<PublicationLease>()),
9165            (
9166                self.storage.control.device_ptr_value(),
9167                size_of::<PublicationControl>(),
9168            ),
9169            (
9170                self.storage.contract.device_ptr_value(),
9171                size_of::<PublicationContract>(),
9172            ),
9173            (
9174                self.storage.storage.device_ptr_value(),
9175                self.storage.storage.len() * size_of::<PublicationStorageEntry>(),
9176            ),
9177            (
9178                self.storage.role_counts.device_ptr_value(),
9179                self.storage.role_counts.len() * size_of::<PublicationRoleCount>(),
9180            ),
9181            (
9182                self.storage.terminals.device_ptr_value(),
9183                self.storage.terminals.len() * size_of::<u64>(),
9184            ),
9185        ]);
9186        for (ordinal, &(begin, bytes)) in output.iter().enumerate() {
9187            if bytes == 0 {
9188                continue;
9189            }
9190            let end = begin
9191                .checked_add(bytes as u64)
9192                .filter(|&end| begin != 0 && end > begin)
9193                .ok_or(SemanticTransitionError::ObservationMismatch)?;
9194            for &(other, other_bytes) in original.iter().chain(&output[..ordinal]) {
9195                let other_end = other
9196                    .checked_add(other_bytes as u64)
9197                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
9198                if begin < other_end && other < end {
9199                    return Err(publication_input_error(
9200                        "fixed step outputs overlap original storage or another output",
9201                    ));
9202                }
9203            }
9204        }
9205        Ok(())
9206    }
9207
9208    // Session installs this owner before uploading fixed pointer/layout metadata.
9209    // No numerical values or expected digests travel through the host.
9210    fn initialize(&self, provider: &CudaKernelProvider) -> Result<(), SemanticTransitionError> {
9211        for bank in 0..2 {
9212            upload_publication(provider, &self.binding_values[bank], &self.bindings[bank])?;
9213        }
9214        Ok(())
9215    }
9216
9217    fn enqueue(
9218        &self,
9219        domain: &ResidentExecutionDomain,
9220        poisoned: &mut bool,
9221    ) -> Result<(), SemanticTransitionError> {
9222        let mut recorder = domain.new_strict_recorder();
9223        recorder.read(&self.reader);
9224        recorder.read(&self.storage.control);
9225        recorder.read(&self.storage.storage);
9226        recorder.read(&self.storage.contract);
9227        recorder.read(&self.storage.role_counts);
9228        recorder.read(&self.storage.terminals);
9229        for bank in &self.storage.banks {
9230            recorder.read(bank);
9231        }
9232        for directory in &self.storage.directories {
9233            recorder.read(directory);
9234        }
9235        for allocation in &self.storage.allocations {
9236            recorder.read(allocation);
9237        }
9238        for bindings in &self.bindings {
9239            recorder.read(bindings);
9240        }
9241        recorder.write(&self.header);
9242        recorder.write(&self.source);
9243        recorder.write(&self.ranges);
9244        recorder.write(&self.metadata_digests);
9245        for allocation in &self.private {
9246            recorder.write(allocation);
9247        }
9248        let arguments = (
9249            self.storage.control.device_ptr_value(),
9250            *self.reader.device_ptr(),
9251            self.bindings[0].device_ptr_value(),
9252            self.bindings[1].device_ptr_value(),
9253            self.bindings[0].len() as u64,
9254            self.header.device_ptr_value(),
9255            self.source.device_ptr_value(),
9256            self.ranges.device_ptr_value(),
9257            self.metadata_digests.device_ptr_value(),
9258        );
9259        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
9260            // SAFETY: every selectable bank and disjoint output is owned before
9261            // enqueue. The kernel validates all original seals before writing.
9262            unsafe {
9263                self.execute.clone().launch_in(
9264                    enqueue,
9265                    LaunchConfig {
9266                        grid_dim: (1, 1, 1),
9267                        block_dim: (1, 1, 1),
9268                        shared_mem_bytes: 0,
9269                    },
9270                    arguments,
9271                )
9272            }
9273            .map_err(|error| XlogError::Kernel(error.to_string()))
9274        })
9275    }
9276
9277    fn verify(
9278        &self,
9279        domain: &ResidentExecutionDomain,
9280        poisoned: &mut bool,
9281    ) -> Result<(), SemanticTransitionError> {
9282        self.verify_basis(domain, poisoned, None, false)
9283    }
9284
9285    fn verify_completed(
9286        &self,
9287        domain: &ResidentExecutionDomain,
9288        poisoned: &mut bool,
9289        custody: Option<&PreparedReplayCustody>,
9290    ) -> Result<(), SemanticTransitionError> {
9291        self.verify_basis(domain, poisoned, custody, true)
9292    }
9293
9294    fn verify_basis(
9295        &self,
9296        domain: &ResidentExecutionDomain,
9297        poisoned: &mut bool,
9298        custody: Option<&PreparedReplayCustody>,
9299        completed: bool,
9300    ) -> Result<(), SemanticTransitionError> {
9301        let mut recorder = domain.new_strict_recorder();
9302        recorder.read(&self.header);
9303        recorder.read(&self.source);
9304        recorder.read(&self.ranges);
9305        recorder.read(&self.reader);
9306        for bindings in &self.bindings {
9307            recorder.read(bindings);
9308        }
9309        recorder.read(&self.metadata_digests);
9310        for bank in &self.views {
9311            for view in bank.values() {
9312                recorder.read(view);
9313            }
9314        }
9315        for allocation in &self.private {
9316            recorder.read(allocation);
9317        }
9318        let bindings = if let Some(custody) = custody {
9319            if !custody.owns_inputs(self) {
9320                return Err(publication_input_error(
9321                    "retained input guard belongs to another original step",
9322                ));
9323            }
9324            let bindings = custody.input_bindings();
9325            recorder.read(bindings);
9326            for input in &self.plans {
9327                if matches!(input.role, 1 | 4 | 5 | 18..=25) {
9328                    let view = custody.input_view(input.role, input.index)?.0;
9329                    recorder.read(&view);
9330                    if matches!(input.role, 18..=25) {
9331                        recorder.read(
9332                            &view
9333                                .allocation_view()
9334                                .ok_or(SemanticTransitionError::ObservationMismatch)?,
9335                        );
9336                    }
9337                }
9338            }
9339            [bindings, bindings]
9340        } else {
9341            [&self.bindings[0], &self.bindings[1]]
9342        };
9343        let arguments = (
9344            *self.reader.device_ptr(),
9345            self.header.device_ptr_value(),
9346            self.source.device_ptr_value(),
9347            bindings[0].device_ptr_value(),
9348            bindings[1].device_ptr_value(),
9349            bindings[0].len() as u64,
9350            self.ranges.device_ptr_value(),
9351            self.metadata_digests.device_ptr_value(),
9352        );
9353        let guard = if completed {
9354            &self.completed_guard
9355        } else {
9356            &self.guard
9357        };
9358        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
9359            // SAFETY: private producer snapshots and original shared aliases are
9360            // retained. No later bank or digest can replace this original basis.
9361            unsafe {
9362                guard.clone().launch_in(
9363                    enqueue,
9364                    LaunchConfig {
9365                        grid_dim: (1, 1, 1),
9366                        block_dim: (1, 1, 1),
9367                        shared_mem_bytes: 0,
9368                    },
9369                    arguments,
9370                )
9371            }
9372            .map_err(|error| XlogError::Kernel(error.to_string()))
9373        })
9374    }
9375
9376    fn field_view(
9377        &self,
9378        field: PublicationBankField,
9379    ) -> Result<DeviceMemoryView<u8>, SemanticTransitionError> {
9380        let (span, _, _) = field.layout();
9381        // SAFETY: only initialized public Source/scalar fields of the checked
9382        // padding-free ABI are exposed, never the private header or hash words.
9383        unsafe {
9384            match field {
9385                PublicationBankField::Source => self
9386                    .source
9387                    .view()
9388                    .cast::<u8>()
9389                    .ok_or(SemanticTransitionError::ObservationMismatch),
9390                _ => self
9391                    .header
9392                    .view()
9393                    .cast::<u8>()
9394                    .map(|view| view.slice(span))
9395                    .ok_or(SemanticTransitionError::ObservationMismatch),
9396            }
9397        }
9398    }
9399
9400    fn training_coordinates_view(&self) -> Result<DeviceMemoryView<u64>, SemanticTransitionError> {
9401        let begin = std::mem::offset_of!(PublicationHeader, training_cursor);
9402        let end = begin
9403            .checked_add(5 * size_of::<u64>())
9404            .ok_or(SemanticTransitionError::GenerationExhausted)?;
9405        unsafe {
9406            self.header
9407                .view()
9408                .cast::<u8>()
9409                .map(|view| view.slice(begin..end))
9410                .and_then(|view| view.cast::<u64>())
9411                .ok_or(SemanticTransitionError::ObservationMismatch)
9412        }
9413    }
9414
9415    fn owns_tensor(
9416        &self,
9417        tensor: &PreparedSemanticTensor,
9418    ) -> Result<bool, SemanticTransitionError> {
9419        let bytes = tensor.source.as_ref().map_or(0, DeviceMemoryView::len);
9420        for field in [
9421            PublicationBankField::Source,
9422            PublicationBankField::PrefixExtent,
9423            PublicationBankField::RingHead,
9424            PublicationBankField::Terminal,
9425        ] {
9426            let view = self.field_view(field)?;
9427            let start = *view.device_ptr();
9428            if !step_input_overlap(tensor.data, bytes, start, view.len())? {
9429                continue;
9430            }
9431            let (_, shape, strides) = field.layout();
9432            let mut layout = SemanticTensorLayout {
9433                role: 0,
9434                index: tensor.layout.index,
9435                scalar_type: 3,
9436                element_bytes: 8,
9437                rank: shape.len() as u64,
9438                logical_axis: u64::MAX,
9439                ..SemanticTensorLayout::default()
9440            };
9441            for (axis, dimension) in shape.into_iter().enumerate() {
9442                layout.dimensions[axis] = dimension as u64;
9443            }
9444            for (axis, stride) in strides.into_iter().enumerate() {
9445                layout.strides_bytes[axis] = stride as u64 * 8;
9446            }
9447            if tensor.data != start
9448                || bytes != view.len()
9449                || tensor.layout != layout
9450                || (tensor.logical_begin, tensor.logical_end) != (0, 0)
9451            {
9452                return Err(publication_input_error("native source and scalar aliases must retain their exact exported type and extent"));
9453            }
9454            if !step_input_allocation_matches(tensor, &view) {
9455                return Err(publication_input_error(
9456                    "native source and scalar allocation origin does not match its producer",
9457                ));
9458            }
9459            return Ok(true);
9460        }
9461        for (pointer, capacity) in [
9462            (
9463                self.header.device_ptr_value(),
9464                size_of::<PublicationHeader>(),
9465            ),
9466            (
9467                self.ranges.device_ptr_value(),
9468                self.ranges.len() * size_of::<PublicationRange>(),
9469            ),
9470            (
9471                self.bindings[0].device_ptr_value(),
9472                self.bindings[0].len() * size_of::<PublicationStepInput>(),
9473            ),
9474            (
9475                self.bindings[1].device_ptr_value(),
9476                self.bindings[1].len() * size_of::<PublicationStepInput>(),
9477            ),
9478            (
9479                self.metadata_digests.device_ptr_value(),
9480                self.metadata_digests.len() * size_of::<u64>(),
9481            ),
9482        ] {
9483            if step_input_overlap(tensor.data, bytes, pointer, capacity)? {
9484                return Err(publication_input_error("native private header, range and digest storage cannot become a content operand"));
9485            }
9486        }
9487        // Select by the original typed coordinate before testing overlap: two
9488        // legitimate model views can share any subset of the same backing.
9489        if let Some(input) = self
9490            .plans
9491            .iter()
9492            .find(|input| (input.role, input.index) == (tensor.layout.role, tensor.layout.index))
9493        {
9494            if (18..=25).contains(&input.role) && bytes == 0 && tensor.native_allocation.is_none() {
9495                return Err(publication_input_error("empty prepared model inputs require their original native allocation provenance"));
9496            }
9497            for bank in 0..2 {
9498                let view = &self.views[bank][&(input.role, input.index)];
9499                let range = self.storage.bank_templates[bank]
9500                    .iter()
9501                    .find(|range| (range.role, range.index) == (input.role, input.index))
9502                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
9503                if step_input_alias_matches(
9504                    input,
9505                    range,
9506                    *view.device_ptr(),
9507                    view.len(),
9508                    tensor_content_identity(tensor),
9509                ) && step_input_allocation_matches(tensor, view)
9510                {
9511                    return Ok(true);
9512                }
9513            }
9514        }
9515        for bank in 0..2 {
9516            for input in &self.plans {
9517                let view = &self.views[bank][&(input.role, input.index)];
9518                let start = *view.device_ptr();
9519                if !(step_input_overlap(tensor.data, bytes, start, view.len())?
9520                    || input.role == 1 && bytes == 0 && tensor.data == start)
9521                {
9522                    continue;
9523                }
9524                let range = self.storage.bank_templates[bank]
9525                    .iter()
9526                    .find(|range| (range.role, range.index) == (input.role, input.index))
9527                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
9528                if input.role == 1
9529                    && step_input_alias_matches(
9530                        input,
9531                        range,
9532                        start,
9533                        view.len(),
9534                        tensor_content_identity(tensor),
9535                    )
9536                    && step_input_allocation_matches(tensor, view)
9537                {
9538                    return Ok(true);
9539                }
9540                return Err(publication_input_error("native step aliases must retain their original type, capacity, interval and coordinate"));
9541            }
9542        }
9543        for allocation in &self.private {
9544            let retained_origin = tensor.native_allocation.as_ref().is_some_and(|origin| {
9545                allocation
9546                    .view()
9547                    .allocation_provenance()
9548                    .is_some_and(|expected| origin.same_allocation(&expected))
9549            });
9550            if retained_origin
9551                || step_input_overlap(
9552                    tensor.data,
9553                    bytes,
9554                    allocation.device_ptr_value(),
9555                    allocation.len(),
9556                )?
9557            {
9558                return Err(publication_input_error(
9559                    "native step backing padding cannot become a separate content operand",
9560                ));
9561            }
9562        }
9563        Ok(false)
9564    }
9565
9566    fn owns_bank_model_tensor(
9567        &self,
9568        bank: usize,
9569        tensor: &PreparedSemanticTensor,
9570    ) -> Result<bool, SemanticTransitionError> {
9571        if bank > 1 || !(18..=25).contains(&tensor.layout.role) {
9572            return Ok(false);
9573        }
9574        let Some(input) = self
9575            .plans
9576            .iter()
9577            .find(|input| (input.role, input.index) == (tensor.layout.role, tensor.layout.index))
9578        else {
9579            return Ok(false);
9580        };
9581        let view = &self.views[bank][&(input.role, input.index)];
9582        let range = self.storage.bank_templates[bank]
9583            .iter()
9584            .find(|range| (range.role, range.index) == (input.role, input.index))
9585            .ok_or(SemanticTransitionError::ObservationMismatch)?;
9586        Ok(step_input_alias_matches(
9587            input,
9588            range,
9589            *view.device_ptr(),
9590            view.len(),
9591            tensor_content_identity(tensor),
9592        ) && step_input_allocation_matches(tensor, view))
9593    }
9594}
9595
9596fn step_input_allocation_matches(
9597    tensor: &PreparedSemanticTensor,
9598    view: &DeviceMemoryView<u8>,
9599) -> bool {
9600    match &tensor.native_allocation {
9601        Some(origin) => view
9602            .allocation_provenance()
9603            .is_some_and(|expected| origin.same_allocation(&expected)),
9604        // An address locates nonempty retained storage, but all independent
9605        // zero-byte native allocations may have the same null address.
9606        None => !view.is_empty(),
9607    }
9608}
9609
9610fn step_input_alias_matches(
9611    input: &StepInputPlan,
9612    range: &PublicationRange,
9613    data: u64,
9614    capacity: usize,
9615    actual: (SemanticTensorLayout, u64, u64, u64, usize),
9616) -> bool {
9617    if actual.3 != data {
9618        return false;
9619    }
9620    let typed_capacity = actual.4 == capacity
9621        && actual.0 == input.layout
9622        && (actual.1, actual.2) == (range.logical_begin, range.logical_end);
9623    // The public raw prefix export is the exact committed byte interval of
9624    // this same original capacity allocation. It still uses the producer's
9625    // original raw prefix seal, including the legal empty prefix.
9626    let raw_prefix = input.role == 1
9627        && input.index == 0
9628        && range.role == 1
9629        && range.index == 0
9630        && actual.0 == publication_record_layout(range)
9631        && (actual.1, actual.2) == (0, 0)
9632        && u64::try_from(actual.4).ok() == Some(range.length_bytes)
9633        && actual.4 <= capacity;
9634    typed_capacity || raw_prefix
9635}
9636
9637// Numerical producers and their original seals outlive the bank they consumed.
9638// A step is installed alongside acquisition, before any operation can enqueue.
9639// Its identity is set only after that actual device acquisition is validated.
9640struct StepContentStorage {
9641    identity: Option<SemanticPublishedIdentity>,
9642    content_witnesses: Arc<()>,
9643    aliases: Arc<()>,
9644    consumer_streams: BTreeSet<u64>,
9645    inputs: Option<Arc<PreparedStepInputs>>,
9646    // Deleters do not establish completion. Final step retirement joins every
9647    // recorded consumer before clearing any of these actual output owners.
9648    feedback: Vec<FeedbackBuffers>,
9649    content: Vec<TensorContentBuffers>,
9650    #[cfg_attr(
9651        not(feature = "semantic-policy"),
9652        expect(
9653            dead_code,
9654            reason = "adjoints are consumed by the semantic-policy VJP path"
9655        )
9656    )]
9657    adjoints: Vec<DeviceMemoryView<u8>>,
9658    #[cfg(feature = "semantic-policy")]
9659    policy_vjp_workspaces: Vec<Arc<PolicyVjpWorkspace>>,
9660    prepared: Option<PreparedStepStorage>,
9661    #[cfg(feature = "semantic-policy")]
9662    evaluation: Option<model_evaluation::EvaluationStorage>,
9663}
9664
9665impl StepContentStorage {
9666    fn new() -> Self {
9667        Self {
9668            identity: None,
9669            content_witnesses: Arc::new(()),
9670            aliases: Arc::new(()),
9671            consumer_streams: BTreeSet::new(),
9672            inputs: None,
9673            feedback: Vec::new(),
9674            content: Vec::new(),
9675            adjoints: Vec::new(),
9676            #[cfg(feature = "semantic-policy")]
9677            policy_vjp_workspaces: Vec::new(),
9678            prepared: None,
9679            #[cfg(feature = "semantic-policy")]
9680            evaluation: None,
9681        }
9682    }
9683}
9684
9685/// A fixed future step issued by its Session during cold segment construction.
9686/// It owns no host publication identity; its actual parent is acquired on device.
9687#[derive(Clone, Debug)]
9688pub struct SemanticPreparedStep {
9689    issuer: Arc<()>,
9690    scope: Arc<()>,
9691    token: u64,
9692}
9693
9694impl SemanticPreparedStep {
9695    pub fn same_handle(&self, other: &Self) -> bool {
9696        Arc::ptr_eq(&self.issuer, &other.issuer)
9697            && Arc::ptr_eq(&self.scope, &other.scope)
9698            && self.token == other.token
9699    }
9700}
9701
9702/// Immutable CPU custody of one joined original step observation. The issued
9703/// step contains identity tokens only, not CUDA storage, graphs or readers.
9704#[cfg(feature = "semantic-policy")]
9705pub struct SemanticCompletedExecutionObservation {
9706    original: SemanticPreparedStep,
9707    requested_transition: SemanticTransitionKind,
9708    outcome: SemanticPreparedStepOutcome,
9709    predecessor: Option<SemanticPublishedIdentity>,
9710    successor: Option<SemanticPublishedIdentity>,
9711    model_binding: Option<(u64, Identity256, Identity256)>,
9712    quantities: [u64; 4],
9713}
9714
9715#[cfg(feature = "semantic-policy")]
9716impl SemanticCompletedExecutionObservation {
9717    pub fn quantities(&self) -> [u64; 4] {
9718        self.quantities
9719    }
9720
9721    pub fn same_execution(&self, other: &Self) -> bool {
9722        self.original.same_handle(&other.original)
9723    }
9724
9725    pub fn belongs_to(&self, session: &SemanticTransitionSession) -> bool {
9726        Arc::ptr_eq(&self.original.issuer, &session.publication_issuer)
9727    }
9728
9729    pub fn predecessor(&self) -> Option<SemanticPublishedIdentity> {
9730        self.predecessor
9731    }
9732
9733    pub fn successor(&self) -> Option<SemanticPublishedIdentity> {
9734        self.successor
9735    }
9736
9737    /// Original checked outcome, retained without its retired device owners.
9738    pub fn outcome(&self) -> &SemanticPreparedStepOutcome {
9739        &self.outcome
9740    }
9741
9742    pub fn requested_transition(&self) -> SemanticTransitionKind {
9743        self.requested_transition
9744    }
9745
9746    pub fn model_binding(&self) -> Option<(u64, Identity256, Identity256)> {
9747        self.model_binding
9748    }
9749}
9750
9751/// Lexical native graph construction. The caller owns this outside any Session
9752/// mutex while invoking original model producers and instantiating the graph.
9753pub struct SemanticPreparedSegmentCapture {
9754    builder: crate::cuda_graph::ConditionalCudaGraphSequenceBuilder,
9755    scope: Arc<()>,
9756}
9757
9758impl SemanticPreparedSegmentCapture {
9759    pub fn add_conditional_if<P, F, E>(
9760        &mut self,
9761        stream: &CudaStream,
9762        preflight: P,
9763        body: F,
9764    ) -> Result<u64, crate::cuda_graph::CudaConditionalGraphUnavailable>
9765    where
9766        P: FnOnce(u64) -> Result<(), E>,
9767        E: fmt::Display,
9768        F: FnOnce(
9769            &crate::cuda_graph::ConditionalCudaGraphBody,
9770        ) -> Result<(), crate::cuda_graph::CudaConditionalGraphUnavailable>,
9771    {
9772        self.builder.add_conditional_if(stream, preflight, body)
9773    }
9774
9775    pub fn instantiate(self) -> Result<SemanticPreparedExecutable, SemanticTransitionError> {
9776        let graph = self
9777            .builder
9778            .instantiate()
9779            .map_err(|error| runtime_error("bounded segment instantiation", error))?;
9780        Ok(SemanticPreparedExecutable {
9781            scope: self.scope,
9782            graph,
9783        })
9784    }
9785}
9786
9787/// A graph produced by one authentic Session construction scope. Only the
9788/// owning Session can take it; the caller retains it on installation failure.
9789pub struct SemanticPreparedExecutable {
9790    scope: Arc<()>,
9791    graph: CapturedCudaGraph,
9792}
9793
9794struct PreparedSegmentState {
9795    issuer: Arc<()>,
9796    scope: Arc<()>,
9797    tokens: Vec<u64>,
9798    transitions: Vec<SemanticTransitionKind>,
9799    cold_capacity: SemanticSegmentColdCapacity,
9800    cold_reservation: Option<GpuMemoryReservation>,
9801    next: usize,
9802    active: bool,
9803    finished: bool,
9804    capturing: bool,
9805    submitted: bool,
9806    completed: bool,
9807}
9808
9809impl PreparedSegmentState {
9810    fn new(
9811        issuer: Arc<()>,
9812        tokens: Vec<u64>,
9813        transitions: impl ExactSizeIterator<Item = SemanticTransitionKind> + Clone,
9814        cold_capacity: SemanticSegmentColdCapacity,
9815    ) -> Result<Self, SemanticTransitionError> {
9816        if tokens.is_empty()
9817            || tokens.contains(&0)
9818            || tokens.iter().copied().collect::<BTreeSet<_>>().len() != tokens.len()
9819            || tokens.len() != transitions.len()
9820            || transitions
9821                .clone()
9822                .any(|kind| kind == SemanticTransitionKind::Drain)
9823        {
9824            return Err(publication_input_error("a prepared segment requires distinct owned steps and one frozen proposal, recompute, or update mode per step"));
9825        }
9826        let mut owned = Vec::new();
9827        owned
9828            .try_reserve_exact(transitions.len())
9829            .map_err(|error| runtime_error("prepared schedule reservation", error))?;
9830        owned.extend(transitions);
9831        cold_capacity.external_floor()?;
9832        Ok(Self {
9833            issuer,
9834            scope: Arc::new(()),
9835            tokens,
9836            transitions: owned,
9837            cold_capacity,
9838            cold_reservation: None,
9839            next: 0,
9840            active: false,
9841            finished: false,
9842            capturing: false,
9843            submitted: false,
9844            completed: false,
9845        })
9846    }
9847
9848    fn handles(&self) -> Result<Vec<SemanticPreparedStep>, SemanticTransitionError> {
9849        let mut handles = Vec::new();
9850        handles
9851            .try_reserve_exact(self.tokens.len())
9852            .map_err(|error| runtime_error("prepared handle reservation", error))?;
9853        handles.extend(self.tokens.iter().map(|&token| SemanticPreparedStep {
9854            issuer: Arc::clone(&self.issuer),
9855            scope: Arc::clone(&self.scope),
9856            token,
9857        }));
9858        Ok(handles)
9859    }
9860
9861    fn check(
9862        &self,
9863        step: &SemanticPreparedStep,
9864        issuer: &Arc<()>,
9865        recording: bool,
9866    ) -> Result<(), SemanticTransitionError> {
9867        self.check_retained(step, issuer)?;
9868        if self.finished
9869            || (recording && (!self.active || self.tokens.get(self.next) != Some(&step.token)))
9870        {
9871            return Err(publication_input_error(
9872                "prepared step differs from its owning Session or active construction scope",
9873            ));
9874        }
9875        Ok(())
9876    }
9877
9878    fn check_retained(
9879        &self,
9880        step: &SemanticPreparedStep,
9881        issuer: &Arc<()>,
9882    ) -> Result<(), SemanticTransitionError> {
9883        if !Arc::ptr_eq(issuer, &self.issuer)
9884            || !Arc::ptr_eq(&step.issuer, issuer)
9885            || !Arc::ptr_eq(&step.scope, &self.scope)
9886            || !self.tokens.contains(&step.token)
9887        {
9888            return Err(publication_input_error(
9889                "retained prepared step differs from its original Session and construction scope",
9890            ));
9891        }
9892        Ok(())
9893    }
9894
9895    fn requested_kind(
9896        &self,
9897        step: &SemanticPreparedStep,
9898        issuer: &Arc<()>,
9899    ) -> Result<SemanticTransitionKind, SemanticTransitionError> {
9900        self.check_retained(step, issuer)?;
9901        let index = self
9902            .tokens
9903            .iter()
9904            .position(|&token| token == step.token)
9905            .ok_or(SemanticTransitionError::ObservationMismatch)?;
9906        Ok(self.transitions[index])
9907    }
9908
9909    fn enter(
9910        &mut self,
9911        step: &SemanticPreparedStep,
9912        issuer: &Arc<()>,
9913    ) -> Result<SemanticTransitionKind, SemanticTransitionError> {
9914        self.check(step, issuer, false)?;
9915        if self.active || self.tokens.get(self.next) != Some(&step.token) {
9916            return Err(publication_input_error(
9917                "prepared steps must record once in their original bounded order",
9918            ));
9919        }
9920        self.active = true;
9921        Ok(self.transitions[self.next])
9922    }
9923
9924    fn leave(
9925        &mut self,
9926        step: &SemanticPreparedStep,
9927        issuer: &Arc<()>,
9928    ) -> Result<(), SemanticTransitionError> {
9929        self.check(step, issuer, true)?;
9930        self.active = false;
9931        self.next += 1;
9932        Ok(())
9933    }
9934
9935    fn finish(&mut self) -> Result<(), SemanticTransitionError> {
9936        if self.finished || self.active || self.next != self.tokens.len() {
9937            return Err(publication_input_error(
9938                "prepared segment has unrecorded or unfinished steps",
9939            ));
9940        }
9941        self.finished = true;
9942        Ok(())
9943    }
9944
9945    #[cfg(any(test, feature = "semantic-policy"))]
9946    fn submit(&mut self) -> Result<(), SemanticTransitionError> {
9947        if !self.finished
9948            || self.active
9949            || self.next != self.tokens.len()
9950            || self.submitted
9951            || self.completed
9952        {
9953            return Err(publication_input_error(
9954                "prepared segment submission requires one complete unused construction",
9955            ));
9956        }
9957        self.submitted = true;
9958        Ok(())
9959    }
9960}
9961
9962struct PreparedStepStorage {
9963    reader: TrackedCudaSlice<PublicationLease>,
9964    replay_custody: Option<PreparedReplayCustody>,
9965    branches: [PreparedBranchStorage; 2],
9966    digests: Option<Arc<TrackedCudaSlice<u64>>>,
9967    next_digest: usize,
9968    model_work: Option<PreparedModelWork>,
9969    admit: CudaFunction,
9970    kind_gate: CudaFunction,
9971    kind_bank_gate: CudaFunction,
9972    active_gate: CudaFunction,
9973    #[cfg_attr(
9974        not(feature = "semantic-policy"),
9975        expect(
9976            dead_code,
9977            reason = "drain preparation is captured by the semantic-policy graph"
9978        )
9979    )]
9980    drain_prepare: CudaFunction,
9981    release: CudaFunction,
9982    witness: CudaFunction,
9983    content_guard: CudaFunction,
9984    inputs_recorded: bool,
9985    model_content_recorded: u8,
9986    transition_recorded: u8,
9987    drain_recorded: bool,
9988    observed: bool,
9989    // Original reconciled CPU evidence survives prepared-storage retirement in
9990    // the issued execution observation; it owns no graph, reader or tensor.
9991    #[cfg(feature = "semantic-policy")]
9992    observed_outcome: Option<SemanticPreparedStepOutcome>,
9993    #[cfg(feature = "semantic-policy")]
9994    observed_parent: Option<PublicationHeader>,
9995    #[cfg(feature = "semantic-policy")]
9996    observed_result: Option<PreparedStepResult>,
9997    result: TrackedCudaSlice<PreparedStepResult>,
9998    training_origin: Option<DeviceMemoryView<SemanticTrainingViewOriginRecord>>,
9999    training_view: Option<SemanticSelectedTrainingView>,
10000    #[cfg(feature = "semantic-policy")]
10001    group_vjp_members: [BTreeSet<u64>; 2],
10002    #[cfg(feature = "semantic-policy")]
10003    group_edit_members: [BTreeSet<u64>; 2],
10004    #[cfg(feature = "semantic-policy")]
10005    group_imported_vjp_members: [BTreeSet<u64>; 2],
10006    #[cfg(feature = "semantic-policy")]
10007    group_gradient_members: [BTreeSet<u64>; 2],
10008    #[cfg(feature = "semantic-policy")]
10009    group_critic_recorded: u8,
10010    #[cfg(feature = "semantic-policy")]
10011    group_update_published: bool,
10012    result_kernel: CudaFunction,
10013}
10014
10015struct PreparedBranchStorage {
10016    model_update: Option<PreparedModelUpdate>,
10017    continuation: Option<PreparedContinuation>,
10018    numerical_block_snapshot: Option<Arc<TrackedCudaSlice<f64>>>,
10019    #[cfg(feature = "semantic-policy")]
10020    policy_buffers: Option<PolicyBuffers>,
10021    #[cfg(feature = "semantic-policy")]
10022    policy: Option<PolicyStorage>,
10023    #[cfg(feature = "semantic-policy")]
10024    support: Option<TrackedCudaSlice<u8>>,
10025    #[cfg(feature = "semantic-policy")]
10026    receipts: Option<TrackedCudaSlice<SemanticTransitionReceipt>>,
10027    #[cfg(feature = "semantic-policy")]
10028    state: TrackedCudaSlice<DeviceState>,
10029    #[cfg(feature = "semantic-policy")]
10030    policy_sources: Vec<PreparedSemanticTensor>,
10031    #[cfg(feature = "semantic-policy")]
10032    policy_witness: Option<SemanticTensorContentWitness>,
10033}
10034
10035struct PreparedModelUpdate {
10036    bindings: TrackedCudaSlice<ModelUpdateBinding>,
10037    evidence: Arc<TrackedCudaSlice<ModelUpdateEvidenceSource>>,
10038    evidence_owners: Arc<Vec<ModelUpdateEvidenceOwner>>,
10039    forward_seals: TrackedCudaSlice<ModelForwardSealInput>,
10040    forward_receipts: TrackedCudaSlice<ModelForwardReceipt>,
10041    admissibility: TrackedCudaSlice<u8>,
10042    canary_results: TrackedCudaSlice<SemanticTrainingCanaryResultRecord>,
10043    refusal: TrackedCudaSlice<SemanticTrainingCanaryRefusalRecord>,
10044    output: Option<BoundModelUpdate>,
10045    forward_recorded: u8,
10046    #[cfg_attr(
10047        not(feature = "semantic-policy"),
10048        expect(
10049            dead_code,
10050            reason = "update admissibility is copied by the semantic-policy graph"
10051        )
10052    )]
10053    admissibility_copy: CudaFunction,
10054    forward_receipt: CudaFunction,
10055    #[cfg_attr(
10056        not(feature = "semantic-policy"),
10057        expect(
10058            dead_code,
10059            reason = "model updates are copied by the semantic-policy graph"
10060        )
10061    )]
10062    copy: CudaFunction,
10063}
10064
10065struct BoundModelUpdate {
10066    values: Vec<ModelUpdateBinding>,
10067    forward_seal_values: Vec<ModelForwardSealInput>,
10068    digest_cells: Vec<Arc<TrackedCudaSlice<u64>>>,
10069    allocations: Vec<PreparedSemanticTensor>,
10070    admissibility: PreparedSemanticTensor,
10071    baseline_logits: PreparedSemanticTensor,
10072    candidate_logits: PreparedSemanticTensor,
10073    _slab_backing: PreparedSemanticTensor,
10074    #[cfg(feature = "semantic-policy")]
10075    accounted_reserved_bytes: u64,
10076    #[cfg(feature = "semantic-policy")]
10077    copy_bytes: u64,
10078    _witness: SemanticTensorContentWitness,
10079    _forward_witnesses: [SemanticModelForwardWitness; 2],
10080}
10081
10082struct ModelUpdateEvidenceOwner {
10083    lease: DeviceMemoryView<PublicationLease>,
10084    parent_header: DeviceMemoryView<PublicationHeader>,
10085    result: DeviceMemoryView<PreparedStepResult>,
10086    origin: DeviceMemoryView<SemanticTrainingViewOriginRecord>,
10087    states: [DeviceMemoryView<DeviceState>; 2],
10088}
10089
10090impl PreparedModelUpdate {
10091    #[cfg(feature = "semantic-policy")]
10092    fn accounted_allocation_bytes(&self) -> Result<u64, SemanticTransitionError> {
10093        let mut allocations = Vec::new();
10094        account_tracked_allocation(&mut allocations, &self.bindings)?;
10095        account_tracked_allocation(&mut allocations, self.evidence.as_ref())?;
10096        account_tracked_allocation(&mut allocations, &self.forward_seals)?;
10097        account_tracked_allocation(&mut allocations, &self.forward_receipts)?;
10098        account_tracked_allocation(&mut allocations, &self.admissibility)?;
10099        account_tracked_allocation(&mut allocations, &self.canary_results)?;
10100        account_tracked_allocation(&mut allocations, &self.refusal)?;
10101        accounted_tracked_bytes(allocations)
10102    }
10103
10104    fn descriptor(&self) -> ModelUpdateContinuationInputs {
10105        ModelUpdateContinuationInputs {
10106            bindings: self.bindings.device_ptr_value(),
10107            binding_count: self.bindings.len() as u64,
10108            admissibility: self.admissibility.device_ptr_value(),
10109            refusal: self.refusal.device_ptr_value(),
10110            canary_results: self.canary_results.device_ptr_value(),
10111        }
10112    }
10113
10114    fn record(&self, recorder: &mut LaunchRecorder) {
10115        recorder.read(&self.bindings);
10116        recorder.read(self.evidence.as_ref());
10117        for evidence in self.evidence_owners.iter() {
10118            recorder.read(&evidence.lease);
10119            recorder.read(&evidence.parent_header);
10120            recorder.read(&evidence.result);
10121            recorder.read(&evidence.origin);
10122            recorder.read(&evidence.states[0]);
10123            recorder.read(&evidence.states[1]);
10124        }
10125        recorder.read(&self.forward_seals);
10126        recorder.read_write(&self.forward_receipts);
10127        recorder.read_write(&self.admissibility);
10128        recorder.read_write(&self.refusal);
10129        recorder.read(&self.canary_results);
10130        if let Some(output) = &self.output {
10131            for allocation in &output.allocations {
10132                if let Some(source) = &allocation.source {
10133                    recorder.read(source);
10134                }
10135            }
10136            if let Some(source) = &output.admissibility.source {
10137                recorder.read(source);
10138            }
10139            if let Some(source) = &output.baseline_logits.source {
10140                recorder.read(source);
10141            }
10142            if let Some(source) = &output.candidate_logits.source {
10143                recorder.read(source);
10144            }
10145            for cells in &output.digest_cells {
10146                recorder.read(cells.as_ref());
10147            }
10148        }
10149    }
10150
10151    #[cfg(feature = "semantic-policy")]
10152    #[expect(
10153        clippy::too_many_arguments,
10154        reason = "the update gate joins publication, training, task and original model-work owners"
10155    )]
10156    fn enqueue_copy(
10157        &self,
10158        domain: &ResidentExecutionDomain,
10159        poisoned: &mut bool,
10160        storage: &PublicationStorage,
10161        reader: &TrackedCudaSlice<PublicationLease>,
10162        training_view: &SemanticSelectedTrainingView,
10163        task: &TrackedCudaSlice<u64>,
10164        model_work: &PreparedModelWork,
10165    ) -> Result<(), SemanticTransitionError> {
10166        let output = self.output.as_ref().ok_or_else(|| {
10167            publication_input_error("prepared update has no original model output binding")
10168        })?;
10169        let allocation_count = u32::try_from(output.values.len())
10170            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
10171        if allocation_count == 0 || allocation_count > 65_535 {
10172            return Err(publication_input_error(
10173                "prepared update model allocation roster exceeds the CUDA launch geometry",
10174            ));
10175        }
10176        let maximum_bytes = output
10177            .values
10178            .iter()
10179            .map(|binding| binding.bytes)
10180            .max()
10181            .unwrap_or(0);
10182        let blocks = maximum_bytes.div_ceil(256).clamp(1, 65_535) as u32;
10183        let mut recorder = domain.new_strict_recorder();
10184        storage.record(&mut recorder);
10185        recorder.read(reader);
10186        self.record(&mut recorder);
10187        model_work.record_reads(&mut recorder);
10188        recorder.read(task);
10189        let selection = training_view.selection();
10190        let roster_rows = training_view.roster_rows();
10191        let objective = training_view.objective();
10192        let canaries = training_view.canaries();
10193        let protected_members = training_view.protected_members();
10194        let retention_labels = training_view.retention_labels();
10195        let kinds = training_view.kinds();
10196        recorder.read(&selection);
10197        recorder.read(&roster_rows);
10198        recorder.read(&objective);
10199        recorder.read(&canaries);
10200        recorder.read(&protected_members);
10201        recorder.read(&retention_labels);
10202        recorder.read(&kinds);
10203        recorder.write(&self.canary_results);
10204        recorder.write(&self.admissibility);
10205        recorder.write(&self.refusal);
10206        let admissibility_source = output.admissibility.data;
10207        let canary_results = self.canary_results.device_ptr_value();
10208        let admissibility_destination = self.admissibility.device_ptr_value();
10209        let refusal_destination = self.refusal.device_ptr_value();
10210        let training_view_bytes = training_view.accounted_allocation_bytes()?;
10211        let model_work_bytes = model_work.accounted_allocation_bytes()?;
10212        let update_bytes = self.accounted_allocation_bytes()?;
10213        let task_bytes = task
10214            .view()
10215            .allocation_provenance()
10216            .ok_or(SemanticTransitionError::ObservationMismatch)?
10217            .allocation_bytes();
10218        let accounted_reserved_bytes = output
10219            .accounted_reserved_bytes
10220            .checked_add(storage.accounted_allocation_bytes()?)
10221            .and_then(|bytes| bytes.checked_add(training_view_bytes))
10222            .and_then(|bytes| bytes.checked_add(task_bytes))
10223            .and_then(|bytes| bytes.checked_add(model_work_bytes))
10224            .and_then(|bytes| bytes.checked_add(update_bytes))
10225            .ok_or(SemanticTransitionError::GenerationExhausted)?;
10226        let logits = output.baseline_logits.layout;
10227        let canary_inputs = ModelUpdateCanaryInputs {
10228            control: storage.control.device_ptr_value(),
10229            lease: reader.device_ptr_value(),
10230            selection: *selection.device_ptr(),
10231            roster_rows: *roster_rows.device_ptr(),
10232            objective: *objective.device_ptr(),
10233            canaries: *canaries.device_ptr(),
10234            canary_count: canaries.len() as u64,
10235            protected_members: *protected_members.device_ptr(),
10236            protected_member_count: protected_members.len() as u64,
10237            task: task.device_ptr_value(),
10238            task_words: task.len() as u64,
10239            evidence: self.evidence.device_ptr_value(),
10240            evidence_count: self.evidence.len() as u64,
10241            forward_receipts: self.forward_receipts.device_ptr_value(),
10242            candidate_seal_count: self.forward_seals.len() as u64,
10243            retention_labels: *retention_labels.device_ptr(),
10244            kinds: *kinds.device_ptr(),
10245            baseline_logits: output.baseline_logits.data,
10246            candidate_logits: output.candidate_logits.data,
10247            scalar_type: logits.scalar_type,
10248            row_count: logits.dimensions[0],
10249            capacity: logits.dimensions[1],
10250            vocabulary: logits.dimensions[2],
10251            row_stride_bytes: logits.strides_bytes[0],
10252            position_stride_bytes: logits.strides_bytes[1],
10253            vocabulary_stride_bytes: logits.strides_bytes[2],
10254            model_work: model_work.descriptor(),
10255            accounted_reserved_bytes,
10256            copy_bytes: output.copy_bytes,
10257            admissibility_source,
10258            results: canary_results,
10259            admissibility_destination,
10260            refusal_destination,
10261        };
10262        let arguments = (
10263            storage.control.device_ptr_value(),
10264            reader.device_ptr_value(),
10265        );
10266        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
10267            // SAFETY: the producer gate was checked by the same captured
10268            // content witness as the complete update backing. The native byte
10269            // is the stable predicate consumed by both copy and publication.
10270            unsafe {
10271                self.admissibility_copy.clone().launch_in(
10272                    enqueue,
10273                    LaunchConfig {
10274                        grid_dim: (1, 1, 1),
10275                        block_dim: (1, 1, 1),
10276                        shared_mem_bytes: 0,
10277                    },
10278                    (canary_inputs,),
10279                )
10280            }
10281            .map_err(|error| XlogError::Kernel(error.to_string()))?;
10282            // SAFETY: the continuation kernel validated this immutable binding
10283            // roster first. Each CUDA grid row copies one disjoint allocation
10284            // into the inactive neural bank retained by PublicationStorage.
10285            unsafe {
10286                self.copy.clone().launch_in(
10287                    enqueue,
10288                    LaunchConfig {
10289                        grid_dim: (blocks, allocation_count, 1),
10290                        block_dim: (256, 1, 1),
10291                        shared_mem_bytes: 0,
10292                    },
10293                    arguments,
10294                )
10295            }
10296            .map_err(|error| XlogError::Kernel(error.to_string()))
10297        })
10298    }
10299}
10300
10301struct PreparedModelWork {
10302    recording: ModelWorkRecording,
10303    device: TrackedCudaSlice<ModelWorkEvent>,
10304    actual: TrackedCudaSlice<u64>,
10305    reset: CudaFunction,
10306    invocation: CudaFunction,
10307    capture_bank: Option<usize>,
10308    replay_cursor: usize,
10309    evaluation_recording: bool,
10310}
10311
10312const PREPARED_TRANSITION_BANKS: u8 = 0b11;
10313
10314#[repr(C)]
10315#[derive(Clone, Copy, Default)]
10316struct ModelWorkInput {
10317    events: u64,
10318    count: u64,
10319    bound: u64,
10320}
10321
10322#[repr(C)]
10323#[derive(Clone, Copy, Default)]
10324struct ModelUpdateCanaryInputs {
10325    control: u64,
10326    lease: u64,
10327    selection: u64,
10328    roster_rows: u64,
10329    objective: u64,
10330    canaries: u64,
10331    canary_count: u64,
10332    protected_members: u64,
10333    protected_member_count: u64,
10334    task: u64,
10335    task_words: u64,
10336    evidence: u64,
10337    evidence_count: u64,
10338    forward_receipts: u64,
10339    candidate_seal_count: u64,
10340    retention_labels: u64,
10341    kinds: u64,
10342    baseline_logits: u64,
10343    candidate_logits: u64,
10344    scalar_type: u64,
10345    row_count: u64,
10346    capacity: u64,
10347    vocabulary: u64,
10348    row_stride_bytes: u64,
10349    position_stride_bytes: u64,
10350    vocabulary_stride_bytes: u64,
10351    model_work: ModelWorkInput,
10352    accounted_reserved_bytes: u64,
10353    copy_bytes: u64,
10354    admissibility_source: u64,
10355    results: u64,
10356    admissibility_destination: u64,
10357    refusal_destination: u64,
10358}
10359
10360const _: () = assert!(size_of::<ModelUpdateCanaryInputs>() == 280);
10361
10362struct ModelForwardReceiptInputsParam(ModelForwardReceiptInputs);
10363
10364impl crate::cuda_compat::KernelParamStorage for ModelForwardReceiptInputsParam {
10365    fn as_kernel_param(&self) -> *mut std::ffi::c_void {
10366        (&self.0 as *const ModelForwardReceiptInputs)
10367            .cast_mut()
10368            .cast()
10369    }
10370}
10371
10372impl crate::cuda_compat::IntoKernelParamStorage for ModelForwardReceiptInputs {
10373    type Storage = ModelForwardReceiptInputsParam;
10374
10375    fn into_kernel_param_storage(self) -> Self::Storage {
10376        ModelForwardReceiptInputsParam(self)
10377    }
10378}
10379
10380struct ModelUpdateCanaryInputsParam(ModelUpdateCanaryInputs);
10381
10382impl crate::cuda_compat::KernelParamStorage for ModelUpdateCanaryInputsParam {
10383    fn as_kernel_param(&self) -> *mut std::ffi::c_void {
10384        (&self.0 as *const ModelUpdateCanaryInputs)
10385            .cast_mut()
10386            .cast()
10387    }
10388}
10389
10390impl crate::cuda_compat::IntoKernelParamStorage for ModelUpdateCanaryInputs {
10391    type Storage = ModelUpdateCanaryInputsParam;
10392
10393    fn into_kernel_param_storage(self) -> Self::Storage {
10394        ModelUpdateCanaryInputsParam(self)
10395    }
10396}
10397
10398impl PreparedModelWork {
10399    fn allocate(
10400        provider: &Arc<CudaKernelProvider>,
10401        reservation: &mut crate::memory::GpuMemoryReservation,
10402        capacity: usize,
10403    ) -> Result<Self, SemanticTransitionError> {
10404        let recording = ModelWorkRecording::new(capacity).map_err(publication_input_error)?;
10405        let reset = provider
10406            .device()
10407            .inner()
10408            .get_func("xlog_semantic_transition", "semantic_model_work_reset")
10409            .ok_or_else(|| runtime_error("kernel lookup", "model work reset unavailable"))?;
10410        let invocation = provider
10411            .device()
10412            .inner()
10413            .get_func("xlog_semantic_transition", "semantic_model_invocation")
10414            .ok_or_else(|| runtime_error("kernel lookup", "model invocation marker unavailable"))?;
10415        Ok(Self {
10416            recording,
10417            device: reservation
10418                .alloc(capacity)
10419                .map_err(|error| runtime_error("original model work allocation", error))?,
10420            actual: reservation
10421                .alloc(
10422                    capacity
10423                        .checked_mul(3)
10424                        .ok_or(SemanticTransitionError::GenerationExhausted)?,
10425                )
10426                .map_err(|error| runtime_error("original device work allocation", error))?,
10427            reset,
10428            invocation,
10429            capture_bank: None,
10430            replay_cursor: 0,
10431            evaluation_recording: false,
10432        })
10433    }
10434
10435    #[cfg(feature = "semantic-policy")]
10436    fn accounted_allocation_bytes(&self) -> Result<u64, SemanticTransitionError> {
10437        let mut allocations = Vec::new();
10438        account_tracked_allocation(&mut allocations, &self.device)?;
10439        account_tracked_allocation(&mut allocations, &self.actual)?;
10440        accounted_tracked_bytes(allocations)
10441    }
10442
10443    #[cfg(feature = "semantic-policy")]
10444    fn record_reads(&self, recorder: &mut LaunchRecorder) {
10445        recorder.read(&self.device);
10446        recorder.read(&self.actual);
10447    }
10448
10449    #[cfg(feature = "semantic-policy")]
10450    fn begin_capture(&mut self, bank: usize, recorded: u8) -> Result<(), &'static str> {
10451        if bank > 1 || self.capture_bank.is_some() || self.evaluation_recording {
10452            return Err("model work capture requires one inactive bank recording");
10453        }
10454        if (bank == 0 && (recorded != 0 || self.recording.frozen_bound().is_some()))
10455            || (bank == 1 && (recorded != 1 || self.recording.frozen_bound().is_none()))
10456        {
10457            return Err("model work banks must record in zero then one order");
10458        }
10459        self.capture_bank = Some(bank);
10460        self.replay_cursor = 0;
10461        Ok(())
10462    }
10463
10464    fn next_slot(&self) -> Result<usize, &'static str> {
10465        match self.capture_bank {
10466            Some(0) => Ok(self.recording.events().len()),
10467            Some(1) => Ok(self.replay_cursor),
10468            None if self.evaluation_recording => Ok(self.recording.events().len()),
10469            _ => Err("model work event requires an active prepared bank capture"),
10470        }
10471    }
10472
10473    fn record_event(&mut self, event: ModelWorkEvent) -> Result<usize, &'static str> {
10474        let slot = self.next_slot()?;
10475        match self.capture_bank {
10476            Some(0) => self.recording.push(event)?,
10477            None if self.evaluation_recording => self.recording.push(event)?,
10478            Some(1) => {
10479                if self.recording.events().get(slot) != Some(&event) {
10480                    return Err("second model branch differs from original work geometry");
10481                }
10482                self.replay_cursor += 1;
10483            }
10484            _ => return Err("model work event requires an active prepared bank capture"),
10485        }
10486        Ok(slot)
10487    }
10488
10489    #[cfg(feature = "semantic-policy")]
10490    fn finish_capture(&mut self, bank: usize) -> Result<(), &'static str> {
10491        if self.capture_bank != Some(bank) {
10492            return Err("prepared transition differs from its active model work bank");
10493        }
10494        if bank == 0 {
10495            self.recording.require_model_invocations()?;
10496            self.recording.freeze()?;
10497        } else if self.replay_cursor != self.recording.events().len() {
10498            return Err("second model branch omitted original work occurrences");
10499        }
10500        self.capture_bank = None;
10501        self.replay_cursor = 0;
10502        Ok(())
10503    }
10504
10505    fn reset_slots(
10506        &self,
10507        domain: &ResidentExecutionDomain,
10508        poisoned: &mut bool,
10509        first: usize,
10510        count: usize,
10511    ) -> Result<(), SemanticTransitionError> {
10512        let end = first
10513            .checked_add(count)
10514            .filter(|end| *end <= self.actual.len() / 3)
10515            .ok_or(SemanticTransitionError::ObservationMismatch)?;
10516        let mut recorder = domain.new_strict_recorder();
10517        recorder.write(&self.actual);
10518        let arguments = (
10519            self.actual.device_ptr_value() + (first * 3 * size_of::<u64>()) as u64,
10520            ((end - first) * 3) as u64,
10521        );
10522        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
10523            // SAFETY: the checked range belongs to this original step's cold
10524            // allocation. Reset and producer kernels share the capture stream.
10525            unsafe {
10526                self.reset.clone().launch_in(
10527                    enqueue,
10528                    LaunchConfig {
10529                        grid_dim: (1, 1, 1),
10530                        block_dim: (32, 1, 1),
10531                        shared_mem_bytes: 0,
10532                    },
10533                    arguments,
10534                )
10535            }
10536            .map_err(|error| XlogError::Kernel(error.to_string()))
10537        })
10538    }
10539
10540    fn record_invocation(
10541        &mut self,
10542        domain: &ResidentExecutionDomain,
10543        poisoned: &mut bool,
10544    ) -> Result<(), SemanticTransitionError> {
10545        let slot = self.next_slot().map_err(publication_input_error)?;
10546        if slot >= self.actual.len() / 3 {
10547            return Err(publication_input_error(
10548                "model invocation exceeds its original cold event capacity",
10549            ));
10550        }
10551        let actual = self
10552            .actual
10553            .device_ptr_value()
10554            .checked_add((slot * 3 * size_of::<u64>()) as u64)
10555            .ok_or(SemanticTransitionError::GenerationExhausted)?;
10556        let event = ModelWorkEvent::invocation(actual).map_err(publication_input_error)?;
10557        self.record_event(event).map_err(publication_input_error)?;
10558        self.reset_slots(domain, poisoned, slot, 1)?;
10559        let mut recorder = domain.new_strict_recorder();
10560        recorder.write(&self.actual);
10561        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
10562            // SAFETY: this scalar slot is retained by the original invocation;
10563            // reset, marker and model execution share its actual capture stream.
10564            unsafe {
10565                self.invocation.clone().launch_in(
10566                    enqueue,
10567                    LaunchConfig {
10568                        grid_dim: (1, 1, 1),
10569                        block_dim: (1, 1, 1),
10570                        shared_mem_bytes: 0,
10571                    },
10572                    (actual,),
10573                )
10574            }
10575            .map_err(|error| XlogError::Kernel(error.to_string()))
10576        })
10577    }
10578
10579    #[cfg(feature = "semantic-policy")]
10580    fn completed_model_calls(
10581        &self,
10582        actual: &[u64],
10583        executed: bool,
10584    ) -> Result<u64, SemanticTransitionError> {
10585        if actual.len() != self.actual.len() || self.recording.frozen_bound().is_none() {
10586            return Err(SemanticTransitionError::ObservationMismatch);
10587        }
10588        let mut calls = 0u64;
10589        let mut original_markers = 0u64;
10590        for (slot, event) in self.recording.events().iter().enumerate() {
10591            if event.kind != ModelWorkKind::ModelInvocation as u64 {
10592                continue;
10593            }
10594            original_markers = original_markers
10595                .checked_add(1)
10596                .ok_or(SemanticTransitionError::GenerationExhausted)?;
10597            let value = &actual[slot * 3..slot * 3 + 3];
10598            match value {
10599                [0, 0, 0] if !executed => (),
10600                [1, 0, 1] => {
10601                    calls = calls
10602                        .checked_add(1)
10603                        .ok_or(SemanticTransitionError::GenerationExhausted)?;
10604                }
10605                _ => return Err(SemanticTransitionError::ObservationMismatch),
10606            }
10607        }
10608        // Scratch is exported to the model and may retain writable aliases.
10609        // A complete original receipt certifies consumption of every frozen
10610        // event; an erased marker cannot turn that execution into zero calls.
10611        if (executed && (original_markers == 0 || calls != original_markers))
10612            || (!executed && calls != 0)
10613        {
10614            return Err(SemanticTransitionError::ObservationMismatch);
10615        }
10616        Ok(calls)
10617    }
10618
10619    fn descriptor(&self) -> ModelWorkInput {
10620        ModelWorkInput {
10621            events: self.device.device_ptr_value(),
10622            count: self.recording.events().len() as u64,
10623            bound: self
10624                .recording
10625                .frozen_bound()
10626                .expect("original work frozen before enqueue"),
10627        }
10628    }
10629}
10630
10631#[repr(C)]
10632#[derive(Clone, Copy, Default, PartialEq, Eq)]
10633struct PreparedStepResult {
10634    abi: u64,
10635    word: u64,
10636    refusal: u64,
10637    header: PublicationHeader,
10638    advanced: u64,
10639    attempt: AttemptReceipt,
10640}
10641
10642#[derive(Clone, Copy)]
10643#[cfg(feature = "semantic-policy")]
10644struct PreparedTransitionEvidence {
10645    transition: SemanticTransitionKind,
10646    canary_refusal: Option<SemanticTrainingCanaryRefusalRecord>,
10647}
10648
10649// SAFETY: the C ABI contains initialized padding-free U64 fields and the
10650// already verified padding-free publication header representation.
10651unsafe impl DeviceRepr for PreparedStepResult {}
10652
10653/// Private device content witness for the exact tensors of one retained parent.
10654/// Transient witnesses prove stability after capture; model witnesses compare
10655/// against the originally sealed model baseline. Neither proves computation.
10656/// The trusted model owner binds the witness to its actual original execution.
10657/// No digest, device pointer, status, or writable witness storage is exported.
10658#[derive(Clone)]
10659pub struct SemanticTensorContentWitness {
10660    issuer: Arc<()>,
10661    reader_token: u64,
10662    index: usize,
10663    _witness: Arc<()>,
10664}
10665
10666/// Opaque proof that the native receipt node for one exact logits occurrence
10667/// was inserted while its model producer's prepared bank capture was active.
10668#[derive(Clone)]
10669pub struct SemanticModelForwardWitness {
10670    issuer: Arc<()>,
10671    reader_token: u64,
10672    bank: usize,
10673    role: usize,
10674    content: SemanticTensorContentWitness,
10675}
10676
10677struct TensorContentBuffers {
10678    tensors: Vec<PreparedSemanticTensor>,
10679    seals: TensorContentSeals,
10680    // A verification may hand off additional managed aliases. Keep them even
10681    // after enqueue failure; final step release joins consumer completion.
10682    verification_inputs: Vec<PreparedSemanticTensor>,
10683}
10684
10685enum TensorContentSeals {
10686    Captured(Vec<CapturedTensorDigest>),
10687    // Original device seals and contract bytes, not a later bank directory or
10688    // a replacement baseline computed from the live numerical producer.
10689    Model(ModelContentSeals),
10690}
10691
10692struct ModelContentSeals {
10693    ranges: TrackedCudaSlice<PublicationRange>,
10694    contract: TrackedCudaSlice<u8>,
10695    guard: CudaFunction,
10696    prepared: Option<PreparedModelContentSeals>,
10697}
10698
10699struct PreparedModelContentSeals {
10700    bank: usize,
10701    #[cfg(feature = "semantic-policy")]
10702    storage: Arc<PublicationStorage>,
10703    #[cfg(feature = "semantic-policy")]
10704    reader: DeviceMemoryView<PublicationLease>,
10705    roster: TrackedCudaSlice<u64>,
10706    #[cfg(feature = "semantic-policy")]
10707    execute: CudaFunction,
10708}
10709
10710struct ModelContentCopyPlan {
10711    directory_offsets: Vec<usize>,
10712    contract_storage_slot: usize,
10713    contract_span: std::ops::Range<usize>,
10714}
10715
10716fn model_content_copy_plan(
10717    directory: &[PublicationRange],
10718    tensor_ranges: &[usize],
10719    allocation_bytes: &[usize],
10720) -> Result<ModelContentCopyPlan, SemanticTransitionError> {
10721    let mut contracts = directory
10722        .iter()
10723        .enumerate()
10724        .filter(|(_, range)| range.role == 44);
10725    let (contract_index, contract) = contracts
10726        .next()
10727        .ok_or(SemanticTransitionError::ObservationMismatch)?;
10728    let mut seen = BTreeSet::new();
10729    if contracts.next().is_some()
10730        || contract.index != 0
10731        || contract.generation != 1
10732        || contract.length_bytes == 0
10733        || tensor_ranges.is_empty()
10734        || tensor_ranges.iter().any(|&index| {
10735            !seen.insert(index)
10736                || directory
10737                    .get(index)
10738                    .is_none_or(|range| !matches!(range.role, 18..=20))
10739        })
10740    {
10741        return Err(SemanticTransitionError::ObservationMismatch);
10742    }
10743    let contract_storage_slot = usize::try_from(contract.storage_slot)
10744        .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
10745    let allocation = *allocation_bytes
10746        .get(contract_storage_slot)
10747        .ok_or(SemanticTransitionError::ObservationMismatch)?;
10748    let begin = usize::try_from(contract.offset_bytes)
10749        .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
10750    let bytes = usize::try_from(contract.length_bytes)
10751        .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
10752    let end = begin
10753        .checked_add(bytes)
10754        .filter(|&end| end <= allocation)
10755        .ok_or(SemanticTransitionError::ObservationMismatch)?;
10756    let directory_offsets = tensor_ranges
10757        .iter()
10758        .copied()
10759        .chain(std::iter::once(contract_index))
10760        .map(|index| {
10761            index
10762                .checked_mul(size_of::<PublicationRange>())
10763                .ok_or(SemanticTransitionError::ObservationMismatch)
10764        })
10765        .collect::<Result<Vec<_>, _>>()?;
10766    directory_offsets
10767        .len()
10768        .checked_mul(size_of::<PublicationRange>())
10769        .ok_or(SemanticTransitionError::ObservationMismatch)?;
10770    Ok(ModelContentCopyPlan {
10771        directory_offsets,
10772        contract_storage_slot,
10773        contract_span: begin..end,
10774    })
10775}
10776
10777impl ModelContentSeals {
10778    fn allocate(
10779        provider: &CudaKernelProvider,
10780        plan: &ModelContentCopyPlan,
10781    ) -> Result<Self, SemanticTransitionError> {
10782        Self::with_allocations(
10783            provider,
10784            allocate_publication(provider, plan.directory_offsets.len())?,
10785            allocate_publication(provider, plan.contract_span.len())?,
10786        )
10787    }
10788
10789    fn allocate_reserved(
10790        provider: &CudaKernelProvider,
10791        plan: &ModelContentCopyPlan,
10792        reservation: &mut GpuMemoryReservation,
10793    ) -> Result<Self, SemanticTransitionError> {
10794        Self::with_allocations(
10795            provider,
10796            reservation
10797                .alloc(plan.directory_offsets.len())
10798                .map_err(|error| runtime_error("prepared model seal range allocation", error))?,
10799            reservation
10800                .alloc(plan.contract_span.len())
10801                .map_err(|error| runtime_error("prepared model contract allocation", error))?,
10802        )
10803    }
10804
10805    fn with_allocations(
10806        provider: &CudaKernelProvider,
10807        ranges: TrackedCudaSlice<PublicationRange>,
10808        contract: TrackedCudaSlice<u8>,
10809    ) -> Result<Self, SemanticTransitionError> {
10810        let guard = provider
10811            .device()
10812            .inner()
10813            .get_func(
10814                "xlog_semantic_transition",
10815                "semantic_retained_model_contract_guard",
10816            )
10817            .ok_or_else(|| {
10818                runtime_error("kernel lookup", "retained model contract guard unavailable")
10819            })?;
10820        Ok(Self {
10821            ranges,
10822            contract,
10823            guard,
10824            prepared: None,
10825        })
10826    }
10827
10828    #[cfg(feature = "semantic-policy")]
10829    fn snapshot_prepared(
10830        &self,
10831        domain: &ResidentExecutionDomain,
10832        poisoned: &mut bool,
10833    ) -> Result<(), SemanticTransitionError> {
10834        let source = self
10835            .prepared
10836            .as_ref()
10837            .ok_or(SemanticTransitionError::ObservationMismatch)?;
10838        let mut recorder = domain.new_strict_recorder();
10839        source.storage.record(&mut recorder);
10840        recorder.read(&source.reader);
10841        recorder.read(&source.roster);
10842        recorder.write(&self.ranges);
10843        recorder.write(&self.contract);
10844        let arguments = (
10845            source.storage.control.device_ptr_value(),
10846            *source.reader.device_ptr(),
10847            source.roster.device_ptr_value(),
10848            (source.roster.len() / 2) as u64,
10849            self.ranges.device_ptr_value(),
10850            self.contract.device_ptr_value(),
10851            self.contract.len() as u64,
10852        );
10853        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
10854            // SAFETY: fixed roster and output capacities are cold-owned; the
10855            // kernel selects and validates the actual device lease and copies
10856            // original model seals and contract bytes without resealing them.
10857            unsafe {
10858                source.execute.clone().launch_in(
10859                    enqueue,
10860                    LaunchConfig {
10861                        grid_dim: (1, 1, 1),
10862                        block_dim: (1, 1, 1),
10863                        shared_mem_bytes: 0,
10864                    },
10865                    arguments,
10866                )
10867            }
10868            .map_err(|error| XlogError::Kernel(error.to_string()))
10869        })
10870    }
10871
10872    fn snapshot(
10873        &self,
10874        domain: &ResidentExecutionDomain,
10875        poisoned: &mut bool,
10876        directory: &TrackedCudaSlice<PublicationRange>,
10877        source: &TrackedCudaSlice<u8>,
10878        plan: &ModelContentCopyPlan,
10879    ) -> Result<(), SemanticTransitionError> {
10880        let row_bytes = size_of::<PublicationRange>();
10881        let directory_bytes = directory
10882            .len()
10883            .checked_mul(row_bytes)
10884            .ok_or(SemanticTransitionError::ObservationMismatch)?;
10885        if self.ranges.len() != plan.directory_offsets.len()
10886            || self.contract.len() != plan.contract_span.len()
10887            || plan.contract_span.end > source.len()
10888            || plan.directory_offsets.iter().any(|&offset| {
10889                offset
10890                    .checked_add(row_bytes)
10891                    .is_none_or(|end| end > directory_bytes)
10892            })
10893        {
10894            return Err(SemanticTransitionError::ObservationMismatch);
10895        }
10896        let mut recorder = domain.new_strict_recorder();
10897        recorder.read(directory);
10898        recorder.read(source);
10899        recorder.write(&self.ranges);
10900        recorder.write(&self.contract);
10901        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
10902            // SAFETY: every complete original row and the raw contract interval
10903            // are bounded above by their actual tracked allocations. Private
10904            // destinations are retained by Session before this first enqueue.
10905            unsafe {
10906                for (index, &offset) in plan.directory_offsets.iter().enumerate() {
10907                    sys::cuMemcpyDtoDAsync_v2(
10908                        self.ranges.device_ptr_value() + (index * row_bytes) as u64,
10909                        directory.device_ptr_value() + offset as u64,
10910                        row_bytes,
10911                        enqueue.stream().cu_stream(),
10912                    )
10913                    .result()
10914                    .map_err(|e| XlogError::Kernel(format!("original model seal snapshot: {e}")))?;
10915                }
10916                sys::cuMemcpyDtoDAsync_v2(
10917                    self.contract.device_ptr_value(),
10918                    source.device_ptr_value() + plan.contract_span.start as u64,
10919                    self.contract.len(),
10920                    enqueue.stream().cu_stream(),
10921                )
10922                .result()
10923                .map_err(|e| XlogError::Kernel(format!("original model contract snapshot: {e}")))?;
10924            }
10925            Ok::<(), XlogError>(())
10926        })
10927    }
10928
10929    fn verify_contract(
10930        &self,
10931        domain: &ResidentExecutionDomain,
10932        poisoned: &mut bool,
10933    ) -> Result<(), SemanticTransitionError> {
10934        let mut recorder = domain.new_strict_recorder();
10935        recorder.read(&self.ranges);
10936        recorder.read(&self.contract);
10937        let arguments = (
10938            self.contract.device_ptr_value(),
10939            self.contract.len() as u64,
10940            self.ranges.device_ptr_value()
10941                + ((self.ranges.len() - 1) * size_of::<PublicationRange>()) as u64,
10942        );
10943        let execute = self.guard.clone();
10944        enqueue_recorded(domain, poisoned, recorder, |enqueue| {
10945            // SAFETY: the last retained row is the original nonempty model
10946            // contract range; payload and expected seal remain private device
10947            // copies. No current directory or replacement model digest is read.
10948            unsafe {
10949                execute.launch_in(
10950                    enqueue,
10951                    LaunchConfig {
10952                        grid_dim: (1, 1, 1),
10953                        block_dim: (1, 1, 1),
10954                        shared_mem_bytes: 0,
10955                    },
10956                    arguments,
10957                )
10958            }
10959            .map_err(|e| XlogError::Kernel(e.to_string()))
10960        })
10961    }
10962}
10963
10964enum CapturedTensorDigest {
10965    Tensor {
10966        cells: Arc<TrackedCudaSlice<u64>>,
10967        offset: usize,
10968        // Native outputs are sealed by their producer before export.
10969        producer_sealed: bool,
10970    },
10971    // Range inputs retain the producer's raw/typed seals. Source and scalar
10972    // views retain the producer's private complete metadata snapshot.
10973    Publication(Arc<PreparedStepInputs>),
10974}
10975
10976fn captured_tensor_digest_pointer(
10977    digests: &[CapturedTensorDigest],
10978    index: usize,
10979) -> Result<(u64, Arc<TrackedCudaSlice<u64>>), SemanticTransitionError> {
10980    let CapturedTensorDigest::Tensor { cells, offset, .. } = digests
10981        .get(index)
10982        .ok_or(SemanticTransitionError::ObservationMismatch)?
10983    else {
10984        return Err(publication_input_error(
10985            "model forward receipt requires an original transient tensor seal",
10986        ));
10987    };
10988    if offset.checked_add(4).is_none_or(|end| end > cells.len()) {
10989        return Err(SemanticTransitionError::ObservationMismatch);
10990    }
10991    Ok((
10992        cells.device_ptr_value() + (*offset * size_of::<u64>()) as u64,
10993        Arc::clone(cells),
10994    ))
10995}
10996
10997fn tensor_content_identity(
10998    tensor: &PreparedSemanticTensor,
10999) -> (SemanticTensorLayout, u64, u64, u64, usize) {
11000    (
11001        tensor.layout,
11002        tensor.logical_begin,
11003        tensor.logical_end,
11004        tensor.data,
11005        tensor.source.as_ref().map_or(0, DeviceMemoryView::len),
11006    )
11007}
11008
11009#[cfg(feature = "semantic-policy")]
11010fn cuda_backing_allocation(
11011    pointer: u64,
11012    required_bytes: usize,
11013) -> Result<(u64, u64), SemanticTransitionError> {
11014    if pointer == 0 || required_bytes == 0 {
11015        return Err(publication_input_error(
11016            "accounted update tensor requires a nonempty CUDA allocation",
11017        ));
11018    }
11019    let mut base = 0;
11020    let mut bytes = 0usize;
11021    // SAFETY: the prepared tensor was already validated as a live CUDA pointer
11022    // on this session's current context. This query neither reads nor mutates it.
11023    let result = unsafe { sys::cuMemGetAddressRange_v2(&mut base, &mut bytes, pointer) };
11024    if result != sys::cudaError_enum::CUDA_SUCCESS {
11025        return Err(runtime_error(
11026            "update backing-allocation query",
11027            format!("cuMemGetAddressRange_v2 failed with {result:?}"),
11028        ));
11029    }
11030    let bytes = u64::try_from(bytes).map_err(|_| SemanticTransitionError::GenerationExhausted)?;
11031    let required =
11032        u64::try_from(required_bytes).map_err(|_| SemanticTransitionError::GenerationExhausted)?;
11033    if pointer < base
11034        || pointer
11035            .checked_add(required)
11036            .is_none_or(|end| end > base.saturating_add(bytes))
11037    {
11038        return Err(publication_input_error(
11039            "update tensor span exceeds its actual CUDA backing allocation",
11040        ));
11041    }
11042    Ok((base, bytes))
11043}
11044
11045#[cfg(feature = "semantic-policy")]
11046fn accounted_tensor_allocations(
11047    tensors: &[&PreparedSemanticTensor],
11048    slab: &PreparedSemanticTensor,
11049) -> Result<u64, SemanticTransitionError> {
11050    let slab_bytes = tensor_layout_bytes(&slab.layout)?;
11051    let slab_end = slab
11052        .data
11053        .checked_add(slab_bytes as u64)
11054        .ok_or(SemanticTransitionError::GenerationExhausted)?;
11055    let (slab_base, slab_allocation_bytes) = cuda_backing_allocation(slab.data, slab_bytes)?;
11056    for tensor in tensors {
11057        let bytes = tensor_layout_bytes(&tensor.layout)?;
11058        if bytes == 0 {
11059            continue;
11060        }
11061        let (base, allocation_bytes) = cuda_backing_allocation(tensor.data, bytes)?;
11062        if tensor.data < slab.data
11063            || tensor
11064                .data
11065                .checked_add(bytes as u64)
11066                .is_none_or(|end| end > slab_end)
11067            || base != slab_base
11068            || allocation_bytes != slab_allocation_bytes
11069        {
11070            return Err(publication_input_error(
11071                "update output or logits differ from the original slab backing allocation",
11072            ));
11073        }
11074    }
11075    Ok(slab_allocation_bytes)
11076}
11077
11078fn same_tensor_content_owner(
11079    expected: &PreparedSemanticTensor,
11080    actual: &PreparedSemanticTensor,
11081) -> bool {
11082    tensor_content_identity(expected) == tensor_content_identity(actual)
11083        && match (&expected.native_allocation, &actual.native_allocation) {
11084            (Some(expected), Some(actual)) => expected.same_allocation(actual),
11085            (None, None) => true,
11086            _ => false,
11087        }
11088}
11089
11090impl StepContentStorage {
11091    fn feedback_origin_digest(
11092        &self,
11093        tensor: &PreparedSemanticTensor,
11094    ) -> Result<Option<CapturedTensorDigest>, SemanticTransitionError> {
11095        let bytes = tensor.source.as_ref().map_or(0, DeviceMemoryView::len) as u64;
11096        let end = tensor
11097            .data
11098            .checked_add(bytes)
11099            .ok_or(SemanticTransitionError::ObservationMismatch)?;
11100        for feedback in &self.feedback {
11101            for (index, original) in feedback.content.tensors.iter().enumerate() {
11102                let source = original
11103                    .source
11104                    .as_ref()
11105                    .expect("native feedback output owner");
11106                let original_end = original
11107                    .data
11108                    .checked_add(source.len() as u64)
11109                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
11110                if bytes == 0 || tensor.data >= original_end || original.data >= end {
11111                    continue;
11112                }
11113                if tensor_content_identity(tensor) != tensor_content_identity(original) {
11114                    return Err(publication_input_error("native feedback aliases must retain their original type, shape, interval and roster coordinate"));
11115                }
11116                let TensorContentSeals::Captured(digests) = &feedback.content.seals else {
11117                    return Err(SemanticTransitionError::ObservationMismatch);
11118                };
11119                let CapturedTensorDigest::Tensor { cells, offset, .. } = &digests[index] else {
11120                    return Err(SemanticTransitionError::ObservationMismatch);
11121                };
11122                return Ok(Some(CapturedTensorDigest::Tensor {
11123                    cells: Arc::clone(cells),
11124                    offset: *offset,
11125                    producer_sealed: true,
11126                }));
11127            }
11128        }
11129        Ok(None)
11130    }
11131}
11132
11133impl TensorContentBuffers {
11134    fn enqueue(
11135        &self,
11136        domain: &ResidentExecutionDomain,
11137        poisoned: &mut bool,
11138        execute: &CudaFunction,
11139        verify: bool,
11140    ) -> Result<(), SemanticTransitionError> {
11141        self.enqueue_with_custody(domain, poisoned, execute, verify, None, false)
11142    }
11143
11144    fn enqueue_with_custody(
11145        &self,
11146        domain: &ResidentExecutionDomain,
11147        poisoned: &mut bool,
11148        execute: &CudaFunction,
11149        verify: bool,
11150        custody: Option<&PreparedReplayCustody>,
11151        completed: bool,
11152    ) -> Result<(), SemanticTransitionError> {
11153        if let TensorContentSeals::Model(model) = &self.seals {
11154            if !verify || model.ranges.len() != self.tensors.len() + 1 {
11155                return Err(SemanticTransitionError::ObservationMismatch);
11156            }
11157            model.verify_contract(domain, poisoned)?;
11158        }
11159        for (ordinal, tensor) in self.tensors.iter().enumerate() {
11160            if let TensorContentSeals::Captured(digests) = &self.seals {
11161                if let CapturedTensorDigest::Publication(inputs) = &digests[ordinal] {
11162                    if !digests[..ordinal].iter().any(|digest| matches!(digest,
11163                        CapturedTensorDigest::Publication(previous) if Arc::ptr_eq(inputs, previous))) {
11164                        if completed {
11165                            inputs.verify_completed(domain, poisoned, custody)?;
11166                        } else {
11167                            inputs.verify(domain, poisoned)?;
11168                        }
11169                    }
11170                    // The full-capacity alias may have a shorter original
11171                    // logical interval. Its original device range is the basis.
11172                    continue;
11173                }
11174            }
11175            // Keep the caller's original tensor owners in `self.tensors` for
11176            // every ownership check. Only completed prepared model verification
11177            // reads the pre-mutation native backing under its original seal.
11178            let retained;
11179            let retained_view = match (&self.seals, custody) {
11180                (TensorContentSeals::Model(model), Some(custody)) => {
11181                    let bank = model
11182                        .prepared
11183                        .as_ref()
11184                        .ok_or(SemanticTransitionError::ObservationMismatch)?
11185                        .bank;
11186                    custody.model_content_view(tensor, bank)?
11187                }
11188                _ => None,
11189            };
11190            let tensor = if let Some((view, layout)) = retained_view {
11191                if layout != tensor.layout {
11192                    return Err(SemanticTransitionError::ObservationMismatch);
11193                }
11194                retained = PreparedSemanticTensor {
11195                    layout,
11196                    data: *view.device_ptr(),
11197                    native_allocation: view.allocation_provenance(),
11198                    source: Some(view),
11199                    ..tensor.clone()
11200                };
11201                &retained
11202            } else {
11203                tensor
11204            };
11205            let (pointer, bytes) = tensor
11206                .source
11207                .as_ref()
11208                .map_or((0, 0), |source| (*source.device_ptr(), source.len()));
11209            let range = tensor_content_range(
11210                &tensor.layout,
11211                tensor.logical_begin,
11212                tensor.logical_end,
11213                bytes,
11214            )?;
11215            let mut recorder = domain.new_strict_recorder();
11216            if let Some(source) = &tensor.source {
11217                recorder.read(source);
11218            }
11219            let (expected, verify) = match &self.seals {
11220                TensorContentSeals::Captured(digests) => {
11221                    let CapturedTensorDigest::Tensor {
11222                        cells,
11223                        offset,
11224                        producer_sealed,
11225                    } = &digests[ordinal]
11226                    else {
11227                        return Err(SemanticTransitionError::ObservationMismatch);
11228                    };
11229                    let verify = verify || *producer_sealed;
11230                    if verify {
11231                        recorder.read(cells.as_ref());
11232                    } else {
11233                        recorder.write(cells.as_ref());
11234                    }
11235                    if offset.checked_add(4).is_none_or(|end| end > cells.len()) {
11236                        return Err(SemanticTransitionError::ObservationMismatch);
11237                    }
11238                    (
11239                        cells.device_ptr_value() + (*offset * size_of::<u64>()) as u64,
11240                        verify,
11241                    )
11242                }
11243                TensorContentSeals::Model(model) => {
11244                    recorder.read(&model.ranges);
11245                    (
11246                        model.ranges.device_ptr_value()
11247                            + (ordinal * size_of::<PublicationRange>()
11248                                + std::mem::offset_of!(PublicationRange, digest))
11249                                as u64,
11250                        true,
11251                    )
11252                }
11253            };
11254            let arguments = (
11255                pointer,
11256                bytes as u64,
11257                range,
11258                tensor.layout,
11259                expected,
11260                u64::from(verify),
11261            );
11262            let execute = execute.clone();
11263            enqueue_recorded(domain, poisoned, recorder, |enqueue| {
11264                // SAFETY: the original managed source and exact layout retain
11265                // their allocation; all four private digest cells or the
11266                // original copied publication rows are retained and recorded.
11267                unsafe {
11268                    execute.launch_in(
11269                        enqueue,
11270                        LaunchConfig {
11271                            grid_dim: (1, 1, 1),
11272                            block_dim: (1, 1, 1),
11273                            shared_mem_bytes: 0,
11274                        },
11275                        arguments,
11276                    )
11277                }
11278                .map_err(|e| XlogError::Kernel(e.to_string()))
11279            })?;
11280        }
11281        Ok(())
11282    }
11283}
11284
11285#[cfg(feature = "semantic-policy")]
11286type InitialPrefillSealSource = (u64, u64, Arc<TrackedCudaSlice<u64>>, usize);
11287
11288#[cfg(feature = "semantic-policy")]
11289fn initial_prefill_seal_sources(
11290    content: &TensorContentBuffers,
11291) -> Result<Vec<InitialPrefillSealSource>, SemanticTransitionError> {
11292    let TensorContentSeals::Captured(digests) = &content.seals else {
11293        return Err(SemanticTransitionError::ObservationMismatch);
11294    };
11295    if content.tensors.len() != digests.len() {
11296        return Err(SemanticTransitionError::ObservationMismatch);
11297    }
11298    content
11299        .tensors
11300        .iter()
11301        .zip(digests)
11302        .map(|(tensor, digest)| {
11303            let CapturedTensorDigest::Tensor { cells, offset, .. } = digest else {
11304                return Err(SemanticTransitionError::ObservationMismatch);
11305            };
11306            if offset.checked_add(4).is_none_or(|end| end > cells.len()) {
11307                return Err(SemanticTransitionError::ObservationMismatch);
11308            }
11309            Ok((
11310                tensor.layout.role,
11311                tensor.layout.index,
11312                Arc::clone(cells),
11313                *offset,
11314            ))
11315        })
11316        .collect()
11317}
11318
11319fn model_content_ranges(
11320    directory: &[PublicationRange],
11321    layouts: &BTreeMap<(u64, u64), SemanticTensorLayout>,
11322    tensors: impl Iterator<Item = (SemanticTensorLayout, u64, u64, usize)>,
11323) -> Result<Vec<usize>, SemanticTransitionError> {
11324    // This cold plan fixes geometry only. The original device reader selects
11325    // and authenticates the model record before its expected seals are copied.
11326    if directory.iter().filter(|range| range.role == 44).count() != 1
11327        || !directory.iter().any(|range| {
11328            range.role == 44 && range.index == 0 && range.generation == 1 && range.length_bytes != 0
11329        })
11330        || !directory.iter().any(|range| range.role == 18)
11331    {
11332        return Err(publication_input_error(
11333            "model content requires the complete original roster and sealed model contract",
11334        ));
11335    }
11336    let expected: BTreeSet<_> = directory
11337        .iter()
11338        .filter(|range| matches!(range.role, 18..=20))
11339        .map(|range| (range.role, range.index))
11340        .collect();
11341    let mut seen = BTreeSet::new();
11342    let mut ranges = Vec::new();
11343    for (actual, begin, end, bytes) in tensors {
11344        let key = (actual.role, actual.index);
11345        if !expected.contains(&key) || !seen.insert(key) {
11346            return Err(publication_input_error(
11347                "model content must name each original model tensor exactly once",
11348            ));
11349        }
11350        tensor_content_range(&actual, begin, end, bytes)?;
11351        let (ordinal, range) = directory
11352            .iter()
11353            .enumerate()
11354            .find(|(_, range)| (range.role, range.index) == key)
11355            .ok_or(SemanticTransitionError::ObservationMismatch)?;
11356        let mut original = *layouts
11357            .get(&key)
11358            .ok_or(SemanticTransitionError::ObservationMismatch)?;
11359        if original.logical_axis != u64::MAX {
11360            let axis = usize::try_from(original.logical_axis)
11361                .ok()
11362                .filter(|&axis| axis < 4)
11363                .ok_or(SemanticTransitionError::ObservationMismatch)?;
11364            original.dimensions[axis] = range
11365                .logical_end
11366                .checked_sub(range.logical_begin)
11367                .ok_or(SemanticTransitionError::ObservationMismatch)?;
11368        }
11369        // Logical content includes type, shape and interval, but neither the
11370        // producer address nor its valid, independently checked physical strides.
11371        original.strides_bytes = actual.strides_bytes;
11372        if original != actual
11373            || range.generation != 1
11374            || (range.logical_begin, range.logical_end) != (begin, end)
11375        {
11376            return Err(publication_input_error(
11377                "live model tensor differs from the original logical type, shape or interval",
11378            ));
11379        }
11380        ranges.push(ordinal);
11381    }
11382    if seen != expected {
11383        return Err(publication_input_error(
11384            "model content omits an original model tensor",
11385        ));
11386    }
11387    Ok(ranges)
11388}
11389
11390fn tensor_content_range(
11391    layout: &SemanticTensorLayout,
11392    begin: u64,
11393    end: u64,
11394    bytes: usize,
11395) -> Result<PublicationRange, SemanticTransitionError> {
11396    if (layout.role != 0 && SemanticStateRole::from_code(layout.role).is_none())
11397        || end < begin
11398        || tensor_layout_bytes(layout)? != bytes
11399        || if layout.logical_axis == u64::MAX {
11400            begin != 0 || end != 0
11401        } else {
11402            end - begin != layout.dimensions[layout.logical_axis as usize]
11403        }
11404    {
11405        return Err(publication_input_error(
11406            "content tensor must retain its exact type, shape, interval and byte extent",
11407        ));
11408    }
11409    Ok(PublicationRange {
11410        role: layout.role,
11411        index: layout.index,
11412        length_bytes: bytes as u64,
11413        logical_begin: begin,
11414        logical_end: end,
11415        ..PublicationRange::default()
11416    })
11417}
11418
11419fn validate_content_coordinates(
11420    coordinates: impl Iterator<Item = (u64, u64)>,
11421) -> Result<(), SemanticTransitionError> {
11422    validate_content_coordinates_after(coordinates, 0)
11423}
11424
11425fn validate_content_coordinates_after(
11426    coordinates: impl Iterator<Item = (u64, u64)>,
11427    private_prefix: usize,
11428) -> Result<(), SemanticTransitionError> {
11429    let mut distinct = BTreeSet::new();
11430    for (ordinal, (role, index)) in coordinates.enumerate() {
11431        if (role == 0
11432            && ordinal
11433                .checked_sub(private_prefix)
11434                .is_none_or(|allocation| index != allocation as u64))
11435            || (role != 0 && SemanticStateRole::from_code(role).is_none())
11436            || !distinct.insert((role, index))
11437        {
11438            return Err(publication_input_error(
11439                "content coordinates require unique state roles or exact private capture positions",
11440            ));
11441        }
11442    }
11443    Ok(())
11444}
11445
11446/// An actual device-acquired reader. Only its originating Session can inspect,
11447/// export or release it; it is neither cloneable nor externally constructible.
11448pub struct SemanticPublishedLease {
11449    issuer: Arc<()>,
11450    token: u64,
11451    identity: SemanticPublishedIdentity,
11452    header: PublicationHeader,
11453    source: [SemanticTextSlot; 32],
11454    directory: Vec<PublicationRange>,
11455    active: bool,
11456}
11457
11458fn committed_prefix_layout(
11459    range: &PublicationRange,
11460    prefix_capacity: u64,
11461) -> Result<SemanticTensorLayout, SemanticTransitionError> {
11462    let row_bytes = size_of::<SemanticTextSlot>() as u64;
11463    if range.role != SemanticStateRole::PrefixSource as u64
11464        || range.index != 0
11465        || range.logical_begin != 0
11466        || range.logical_end > prefix_capacity
11467        || range.logical_end.checked_mul(row_bytes) != Some(range.length_bytes)
11468        || i64::try_from(prefix_capacity).is_err()
11469        || !range
11470            .offset_bytes
11471            .is_multiple_of(std::mem::align_of::<SemanticTextSlot>() as u64)
11472    {
11473        return Err(SemanticTransitionError::ObservationMismatch);
11474    }
11475    let layout = SemanticTensorLayout {
11476        role: SemanticStateRole::PrefixSource as u64,
11477        index: 0,
11478        scalar_type: 3,
11479        element_bytes: 8,
11480        rank: 2,
11481        logical_axis: 0,
11482        dimensions: [prefix_capacity, 8, 0, 0],
11483        strides_bytes: [row_bytes, 8, 0, 0],
11484    };
11485    tensor_layout_bytes(&layout)?;
11486    Ok(layout)
11487}
11488
11489/// Bound a view using its cold geometry without widening the sealed logical
11490/// range. Only prefix/cache owners expose reserved row capacity. Other records
11491/// and model tensors remain bounded by their complete original sealed extent.
11492fn publication_export_span(
11493    range: &PublicationRange,
11494    layout: &SemanticTensorLayout,
11495    allocation_bytes: usize,
11496) -> Result<std::ops::Range<usize>, SemanticTransitionError> {
11497    let bytes = tensor_layout_bytes(layout)?;
11498    let begin = usize::try_from(range.offset_bytes)
11499        .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
11500    let sealed_bytes = usize::try_from(range.length_bytes)
11501        .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
11502    let capacity = matches!(range.role, 1 | 4 | 5 | 51..=54);
11503    if range.generation != 1
11504        || (range.role, range.index) != (layout.role, layout.index)
11505        || !range.offset_bytes.is_multiple_of(layout.element_bytes)
11506        || begin
11507            .checked_add(sealed_bytes)
11508            .is_none_or(|end| end > allocation_bytes)
11509        || range.logical_end < range.logical_begin
11510        || (layout.logical_axis != u64::MAX
11511            && (range.logical_begin != 0
11512                || range.logical_end > layout.dimensions[layout.logical_axis as usize]))
11513        || (!capacity && bytes > sealed_bytes)
11514    {
11515        return Err(SemanticTransitionError::ObservationMismatch);
11516    }
11517    let end = begin
11518        .checked_add(bytes.max(sealed_bytes))
11519        .filter(|&end| end <= allocation_bytes)
11520        .ok_or(SemanticTransitionError::ObservationMismatch)?;
11521    Ok(begin..end)
11522}
11523
11524fn publication_record_layout(range: &PublicationRange) -> SemanticTensorLayout {
11525    SemanticTensorLayout {
11526        role: range.role,
11527        index: range.index,
11528        element_bytes: 1,
11529        scalar_type: 1,
11530        rank: 1,
11531        logical_axis: u64::MAX,
11532        dimensions: [range.length_bytes, 0, 0, 0],
11533        strides_bytes: [1, 0, 0, 0],
11534    }
11535}
11536
11537impl SemanticPublishedLease {
11538    fn model_context_header(&self) -> Result<PublicationHeader, SemanticTransitionError> {
11539        let header = self.header;
11540        if header.abi != 1
11541            || header.instance != self.identity.instance
11542            || header.publication_word != self.identity.word
11543            || header.sealed_epoch != self.identity.word >> 1
11544            || header.logical_digest != self.identity.logical_digest
11545            || header.state_digest != self.identity.state_digest
11546        {
11547            return Err(SemanticTransitionError::ObservationMismatch);
11548        }
11549        Ok(header)
11550    }
11551}
11552
11553/// Value-independent flat coordinates emitted by the native feedback producer.
11554#[derive(Clone, Debug, PartialEq, Eq)]
11555pub struct SemanticFeedbackSchema {
11556    pub identity: [u8; 32],
11557    pub statement_bytes: usize,
11558    pub feature_width: usize,
11559}
11560
11561impl SemanticFeedbackSchema {
11562    pub fn new(statements: [&[u8]; 3]) -> Result<Self, SemanticTransitionError> {
11563        if statements.iter().any(|statement| statement.is_empty()) {
11564            return Err(publication_input_error(
11565                "native feedback requires three nonempty typed statements",
11566            ));
11567        }
11568        let statement_bytes = statements
11569            .iter()
11570            .map(|statement| statement.len())
11571            .max()
11572            .unwrap();
11573        let feature_width = statement_bytes
11574            .checked_mul(9)
11575            .and_then(|n| n.checked_add(4))
11576            .filter(|&n| i64::try_from(n).is_ok())
11577            .ok_or_else(|| publication_input_error("native feedback schema width overflows"))?;
11578        let mut hash = Sha256::new();
11579        hash.update(b"xlog.feedback.flat-bit-presence.v1\0");
11580        hash.update((statement_bytes as u64).to_le_bytes());
11581        hash.update(b"byte[i]:bits[0..8],presence;pro,1,contra,1;invalid:all-zero");
11582        Ok(Self {
11583            identity: hash.finalize().into(),
11584            statement_bytes,
11585            feature_width,
11586        })
11587    }
11588}
11589
11590/// Named columns of each current feedback support row. These service values do
11591/// not enter the learned feature schema. Rows follow newest-to-oldest ancestry.
11592pub const SEMANTIC_FEEDBACK_SUPPORT_FIELDS: [&str; 12] = [
11593    "original_statement",
11594    "original_support",
11595    "support_slot",
11596    "support_generation",
11597    "version_slot",
11598    "version_generation",
11599    "insertion_ordinal",
11600    "polarity",
11601    "support_digest_0",
11602    "support_digest_1",
11603    "support_digest_2",
11604    "support_digest_3",
11605];
11606
11607/// Features, validity and current causal provenance from one acquired bank.
11608/// Original outputs retain their step independently of later bank retirement.
11609pub struct SemanticFeedback {
11610    pub parent: SemanticPublishedIdentity,
11611    pub schema: SemanticFeedbackSchema,
11612    features: DlpackManagedTensor,
11613    device_validity: DlpackManagedTensor,
11614    query_receipts: DlpackManagedTensor,
11615    original_statements: DlpackManagedTensor,
11616    support_offsets: DlpackManagedTensor,
11617    supports: DlpackManagedTensor,
11618}
11619
11620impl SemanticFeedback {
11621    /// Features, validity, opaque native current receipts, original statement
11622    /// indices, support offsets, and named support rows, respectively. All
11623    /// service tensors are U64. Invalid slots have no receipt/contributors and
11624    /// original index U64::MAX; valid Neither has an original index and no rows.
11625    pub fn into_dlpack(self) -> [DlpackManagedTensor; 6] {
11626        [
11627            self.features,
11628            self.device_validity,
11629            self.query_receipts,
11630            self.original_statements,
11631            self.support_offsets,
11632            self.supports,
11633        ]
11634    }
11635}
11636
11637struct FeedbackBuffers {
11638    schema: SemanticFeedbackSchema,
11639    slots: usize,
11640    support_capacity: usize,
11641    encode: CudaFunction,
11642    project: CudaFunction,
11643    witness: CudaFunction,
11644    content: TensorContentBuffers,
11645    features: TrackedCudaSlice<f32>,
11646    validity: TrackedCudaSlice<u8>,
11647    status: TrackedCudaSlice<u64>,
11648    query_receipts: TrackedCudaSlice<u64>,
11649    original_statements: TrackedCudaSlice<u64>,
11650    support_offsets: TrackedCudaSlice<u64>,
11651    supports: TrackedCudaSlice<u64>,
11652}
11653
11654#[derive(Clone, Copy)]
11655struct FeedbackAllocationPlan {
11656    slots: usize,
11657    support_capacity: usize,
11658    cells: usize,
11659    query_cells: usize,
11660    support_cells: usize,
11661    offset_cells: usize,
11662    bytes: usize,
11663}
11664
11665impl FeedbackAllocationPlan {
11666    fn new(
11667        schema: &SemanticFeedbackSchema,
11668        slots: u64,
11669        support_capacity: u64,
11670    ) -> Result<Self, SemanticTransitionError> {
11671        let slots = usize::try_from(slots)
11672            .ok()
11673            .filter(|&n| n >= 2 && i64::try_from(n).is_ok())
11674            .ok_or_else(|| {
11675                publication_input_error("feedback slot capacity is not representable")
11676            })?;
11677        let support_capacity = usize::try_from(support_capacity)
11678            .ok()
11679            .filter(|&n| n != 0 && i64::try_from(n).is_ok())
11680            .ok_or_else(|| {
11681                publication_input_error("feedback support capacity is not representable")
11682            })?;
11683        let cells = slots
11684            .checked_mul(schema.feature_width)
11685            .ok_or_else(|| publication_input_error("feedback feature extent overflows"))?;
11686        let query_cells = slots
11687            .checked_mul(42)
11688            .ok_or_else(|| publication_input_error("feedback receipt extent overflows"))?;
11689        let support_cells = support_capacity
11690            .checked_mul(SEMANTIC_FEEDBACK_SUPPORT_FIELDS.len())
11691            .ok_or_else(|| publication_input_error("feedback support extent overflows"))?;
11692        let offset_cells = slots
11693            .checked_add(1)
11694            .ok_or_else(|| publication_input_error("feedback offset extent overflows"))?;
11695        let service_bytes = query_cells
11696            .checked_add(slots)
11697            .and_then(|n| n.checked_add(offset_cells))
11698            .and_then(|n| n.checked_add(support_cells))
11699            .and_then(|n| n.checked_mul(8))
11700            .ok_or_else(|| publication_input_error("feedback service extent overflows"))?;
11701        let bytes = cells
11702            .checked_mul(size_of::<f32>())
11703            .and_then(|n| {
11704                slots
11705                    .checked_mul(9)
11706                    .and_then(|metadata| n.checked_add(metadata))
11707            })
11708            .and_then(|n| n.checked_add(service_bytes))
11709            .and_then(|n| n.checked_add(6 * 4 * size_of::<u64>()))
11710            .ok_or_else(|| publication_input_error("feedback allocation extent overflows"))?;
11711        Ok(Self {
11712            slots,
11713            support_capacity,
11714            cells,
11715            query_cells,
11716            support_cells,
11717            offset_cells,
11718            bytes,
11719        })
11720    }
11721}
11722
11723impl FeedbackBuffers {
11724    // Cold preparation only. The same fixed outputs and kernels are used by
11725    // enqueue; no acquired parent, device values or digest is cached here.
11726    fn allocate(
11727        provider: &CudaKernelProvider,
11728        schema: SemanticFeedbackSchema,
11729        slots: u64,
11730        support_capacity: u64,
11731    ) -> Result<Self, SemanticTransitionError> {
11732        let plan = FeedbackAllocationPlan::new(&schema, slots, support_capacity)?;
11733        let mut reservation = provider
11734            .memory()
11735            .reserve_bytes(plan.bytes as u64)
11736            .map_err(|error| runtime_error("feedback reservation", error))?;
11737        Self::allocate_reserved(provider, schema, plan, &mut reservation)
11738    }
11739
11740    fn allocate_reserved(
11741        provider: &CudaKernelProvider,
11742        schema: SemanticFeedbackSchema,
11743        plan: FeedbackAllocationPlan,
11744        reservation: &mut GpuMemoryReservation,
11745    ) -> Result<Self, SemanticTransitionError> {
11746        let FeedbackAllocationPlan {
11747            slots,
11748            support_capacity,
11749            cells,
11750            query_cells,
11751            support_cells,
11752            offset_cells,
11753            ..
11754        } = plan;
11755        let encode = provider
11756            .device()
11757            .inner()
11758            .get_func("xlog_semantic_transition", "semantic_feedback_encode")
11759            .ok_or_else(|| {
11760                runtime_error("kernel lookup", "semantic feedback kernel unavailable")
11761            })?;
11762        let project = provider
11763            .device()
11764            .inner()
11765            .get_func("xlog_semantic_transition", "semantic_feedback_project")
11766            .ok_or_else(|| {
11767                runtime_error("kernel lookup", "semantic feedback projection unavailable")
11768            })?;
11769        let witness = provider
11770            .device()
11771            .inner()
11772            .get_func(
11773                "xlog_semantic_transition",
11774                "semantic_tensor_content_witness",
11775            )
11776            .ok_or_else(|| runtime_error("kernel lookup", "tensor content witness unavailable"))?;
11777        let mut buffers = Self {
11778            schema,
11779            slots,
11780            support_capacity,
11781            encode,
11782            project,
11783            witness,
11784            content: TensorContentBuffers {
11785                tensors: Vec::new(),
11786                seals: TensorContentSeals::Captured(Vec::new()),
11787                verification_inputs: Vec::new(),
11788            },
11789            features: reservation
11790                .alloc::<f32>(cells)
11791                .map_err(|error| runtime_error("feedback features allocation", error))?,
11792            validity: reservation
11793                .alloc::<u8>(slots)
11794                .map_err(|error| runtime_error("feedback validity allocation", error))?,
11795            status: reservation
11796                .alloc::<u64>(slots)
11797                .map_err(|error| runtime_error("feedback status allocation", error))?,
11798            query_receipts: reservation
11799                .alloc::<u64>(query_cells)
11800                .map_err(|error| runtime_error("feedback receipt allocation", error))?,
11801            original_statements: reservation
11802                .alloc::<u64>(slots)
11803                .map_err(|error| runtime_error("feedback origin allocation", error))?,
11804            support_offsets: reservation
11805                .alloc::<u64>(offset_cells)
11806                .map_err(|error| runtime_error("feedback offset allocation", error))?,
11807            supports: reservation
11808                .alloc::<u64>(support_cells)
11809                .map_err(|error| runtime_error("feedback support allocation", error))?,
11810        };
11811        let words = |view: DeviceMemoryView<u64>| {
11812            // SAFETY: u64 has no padding. The byte view retains the original
11813            // tracked allocation, without a managed alias that owns its reader.
11814            unsafe { view.cast::<u8>() }.ok_or(SemanticTransitionError::ObservationMismatch)
11815        };
11816        // SAFETY: f32 has no padding and the byte view retains its real owner.
11817        let features = unsafe { buffers.features.view().cast::<u8>() }
11818            .ok_or(SemanticTransitionError::ObservationMismatch)?;
11819        let originals = [
11820            features,
11821            buffers.validity.view(),
11822            words(buffers.query_receipts.view())?,
11823            words(buffers.original_statements.view())?,
11824            words(buffers.support_offsets.view())?,
11825            words(buffers.supports.view())?,
11826        ];
11827        let shapes = [
11828            (
11829                6,
11830                4,
11831                2,
11832                [slots as u64, buffers.schema.feature_width as u64, 0, 0],
11833            ),
11834            (8, 1, 1, [slots as u64, 0, 0, 0]),
11835            (3, 8, 2, [slots as u64, 42, 0, 0]),
11836            (3, 8, 1, [slots as u64, 0, 0, 0]),
11837            (3, 8, 1, [offset_cells as u64, 0, 0, 0]),
11838            (3, 8, 2, [support_capacity as u64, 12, 0, 0]),
11839        ];
11840        let mut digests = Vec::with_capacity(originals.len());
11841        for (index, (source, (scalar_type, element_bytes, rank, dimensions))) in
11842            originals.into_iter().zip(shapes).enumerate()
11843        {
11844            let layout = canonical_tensor_layout(SemanticTensorLayout {
11845                role: 0,
11846                index: index as u64,
11847                scalar_type,
11848                element_bytes,
11849                rank,
11850                dimensions,
11851                logical_axis: u64::MAX,
11852                strides_bytes: [0; 4],
11853            })?;
11854            tensor_content_range(&layout, 0, 0, source.len())?;
11855            buffers.content.tensors.push(PreparedSemanticTensor {
11856                layout,
11857                logical_begin: 0,
11858                logical_end: 0,
11859                data: *source.device_ptr(),
11860                source: Some(source),
11861                native_allocation: None,
11862                _empty_owner: None,
11863            });
11864            digests.push(CapturedTensorDigest::Tensor {
11865                cells: Arc::new(
11866                    reservation
11867                        .alloc::<u64>(4)
11868                        .map_err(|error| runtime_error("feedback witness allocation", error))?,
11869                ),
11870                offset: 0,
11871                producer_sealed: false,
11872            });
11873        }
11874        buffers.content.seals = TensorContentSeals::Captured(digests);
11875        Ok(buffers)
11876    }
11877
11878    // The caller retains these prepared outputs before the first may-enqueue
11879    // boundary, including failures and unwinding. This path does not allocate
11880    // device storage, export tensors, synchronize or insert stream joins.
11881    #[expect(
11882        clippy::too_many_arguments,
11883        reason = "feedback execution records every retained native owner explicitly"
11884    )]
11885    fn enqueue(
11886        &self,
11887        domain: &ResidentExecutionDomain,
11888        poisoned: &mut bool,
11889        graph: &SemanticHypergraph,
11890        storage: &PublicationStorage,
11891        task: &TrackedCudaSlice<u64>,
11892        lease: &TrackedCudaSlice<PublicationLease>,
11893        descriptor: Descriptor,
11894    ) -> Result<(), SemanticTransitionError> {
11895        let mut recorder = domain.new_strict_recorder();
11896        recorder.read(lease);
11897        recorder.read(&storage.control);
11898        recorder.read(&storage.storage);
11899        recorder.read(&storage.contract);
11900        for bank in &storage.banks {
11901            recorder.read(bank);
11902        }
11903        for directory in &storage.directories {
11904            recorder.read(directory);
11905        }
11906        for allocation in &storage.allocations {
11907            recorder.read(allocation);
11908        }
11909        recorder.write(&self.features);
11910        recorder.write(&self.validity);
11911        recorder.write(&self.status);
11912        let arguments = (
11913            storage.control.device_ptr_value(),
11914            lease.device_ptr_value(),
11915            self.schema.statement_bytes as u64,
11916            self.slots as u64,
11917            self.features.device_ptr_value(),
11918            self.validity.device_ptr_value(),
11919            self.status.device_ptr_value(),
11920        );
11921        enqueue_recorded(domain, poisoned, recorder, |stream| {
11922            // SAFETY: both directories and every selectable allocation are
11923            // retained. The kernel resolves and validates the acquired lease's
11924            // original ranges; output extents were checked during preparation.
11925            unsafe {
11926                self.encode.clone().launch_in(
11927                    stream,
11928                    LaunchConfig {
11929                        grid_dim: (self.slots.min(65535) as u32, 1, 1),
11930                        block_dim: (256, 1, 1),
11931                        shared_mem_bytes: 0,
11932                    },
11933                    arguments,
11934                )
11935            }
11936            .map_err(|error| XlogError::Kernel(error.to_string()))
11937        })?;
11938        let mut recorder = domain.new_strict_recorder();
11939        graph.record_transition(&mut recorder);
11940        storage.record(&mut recorder);
11941        recorder.read(lease);
11942        recorder.read(task);
11943        recorder.read_write(&self.status);
11944        recorder.write(&self.query_receipts);
11945        recorder.write(&self.original_statements);
11946        recorder.write(&self.support_offsets);
11947        recorder.write(&self.supports);
11948        let arguments = (
11949            descriptor,
11950            lease.device_ptr_value(),
11951            self.slots as u64,
11952            self.query_receipts.device_ptr_value(),
11953            self.original_statements.device_ptr_value(),
11954            self.support_offsets.device_ptr_value(),
11955            self.supports.device_ptr_value(),
11956            self.support_capacity as u64,
11957            self.status.device_ptr_value(),
11958        );
11959        enqueue_recorded(domain, poisoned, recorder, |stream| {
11960            // SAFETY: the original task, actual arena and publication owners
11961            // are recorded. Lineage is queried from this device-acquired parent,
11962            // never a captured host selection or detached feedback record.
11963            unsafe {
11964                self.project.clone().launch_in(
11965                    stream,
11966                    LaunchConfig {
11967                        grid_dim: (1, 1, 1),
11968                        block_dim: (1, 1, 1),
11969                        shared_mem_bytes: 0,
11970                    },
11971                    arguments,
11972                )
11973            }
11974            .map_err(|error| XlogError::Kernel(error.to_string()))
11975        })?;
11976        // The first seal follows the genuine encoder and lineage producer on
11977        // the same stream, before any dependent consumer receives an alias.
11978        self.content.enqueue(domain, poisoned, &self.witness, false)
11979    }
11980}
11981
11982impl SemanticPublishedLease {
11983    pub fn is_active(&self) -> bool {
11984        self.active
11985    }
11986}
11987
11988#[expect(
11989    clippy::too_many_arguments,
11990    reason = "DLPack export retains independent shape, type, alias, and publication owners"
11991)]
11992fn export_owned_allocation(
11993    view: DeviceMemoryView<u8>,
11994    shape: Vec<i64>,
11995    strides: Vec<i64>,
11996    dtype: (u8, u8),
11997    device_id: i32,
11998    alias_guard: Arc<()>,
11999    publication: Arc<PublicationStorage>,
12000    continuation: Option<Arc<TextBindingStorage>>,
12001    retained_owner: Option<Arc<dyn Send + Sync>>,
12002) -> DlpackManagedTensor {
12003    let mut export = Box::new(PublishedTensorExport {
12004        managed: crate::dlpack::DLManagedTensor {
12005            dl_tensor: crate::dlpack::DLTensor {
12006                data: *view.device_ptr() as usize as *mut std::ffi::c_void,
12007                device: crate::dlpack::DLDevice {
12008                    device_type: 2,
12009                    device_id,
12010                },
12011                ndim: shape.len() as i32,
12012                dtype: crate::dlpack::DLDataType {
12013                    code: dtype.0,
12014                    bits: dtype.1,
12015                    lanes: 1,
12016                },
12017                shape: std::ptr::null_mut(),
12018                strides: std::ptr::null_mut(),
12019                byte_offset: 0,
12020            },
12021            manager_ctx: std::ptr::null_mut(),
12022            deleter: Some(delete_published_tensor),
12023        },
12024        shape,
12025        strides,
12026        _view: view,
12027        _alias_guard: alias_guard,
12028        _publication: publication,
12029        _continuation: continuation,
12030        _retained_owner: retained_owner,
12031    });
12032    export.managed.dl_tensor.shape = export.shape.as_mut_ptr();
12033    export.managed.dl_tensor.strides = export.strides.as_mut_ptr();
12034    let owner = Box::into_raw(export);
12035    // SAFETY: the stable owner contains the genuine native allocation and its
12036    // exact metadata. Its bank or step keeps storage through final completion.
12037    unsafe {
12038        (*owner).managed.manager_ctx = owner.cast();
12039        DlpackManagedTensor::from_raw(&mut (*owner).managed)
12040    }
12041}
12042
12043struct PublishedTensorExport {
12044    managed: crate::dlpack::DLManagedTensor,
12045    shape: Vec<i64>,
12046    strides: Vec<i64>,
12047    _view: DeviceMemoryView<u8>,
12048    _alias_guard: Arc<()>,
12049    _publication: Arc<PublicationStorage>,
12050    _continuation: Option<Arc<TextBindingStorage>>,
12051    _retained_owner: Option<Arc<dyn Send + Sync>>,
12052}
12053
12054unsafe extern "C" fn delete_published_tensor(managed: *mut crate::dlpack::DLManagedTensor) {
12055    if managed.is_null() {
12056        return;
12057    }
12058    // SAFETY: this callback owns exactly the Box installed below. DLPack
12059    // transfers its managed record once; no unrelated pointer is accepted.
12060    let owner = unsafe { (*managed).manager_ctx.cast::<PublishedTensorExport>() };
12061    if !owner.is_null() {
12062        drop(unsafe { Box::from_raw(owner) });
12063    }
12064}
12065
12066fn dlpack_consumer_stream(stream: u64) -> Result<sys::CUstream, SemanticTransitionError> {
12067    if matches!(stream, 0 | 2) {
12068        return Err(publication_input_error("DLPack consumer requires legacy default stream 1 or an explicit live stream; zero and per-thread default are unsupported"));
12069    }
12070    Ok(if stream == 1 {
12071        std::ptr::null_mut()
12072    } else {
12073        stream as usize as sys::CUstream
12074    })
12075}
12076
12077// Every call below uses the fixed integral, padding-free publication ABI checked
12078// above, or SourceSlot's checked eight-u64 layout. This is cold control metadata.
12079fn publication_abi_bytes<T: DeviceRepr>(records: &[T]) -> Vec<u8> {
12080    // SAFETY: callers use initialized padding-free C ABI records only. The byte
12081    // slice is bounded by the live input allocation and copied before return.
12082    unsafe { std::slice::from_raw_parts(records.as_ptr().cast(), std::mem::size_of_val(records)) }
12083        .to_vec()
12084}
12085
12086fn initial_intent_records(
12087    effect: &[u8],
12088    entry_capacity: u64,
12089    payload_capacity: usize,
12090    final_payload_bytes: u64,
12091) -> Result<[SemanticStateRecord; 2], SemanticTransitionError> {
12092    let entries_bytes = usize::try_from(entry_capacity)
12093        .ok()
12094        .and_then(|count| count.checked_mul(size_of::<IntentEntry>()))
12095        .and_then(|bytes| bytes.checked_add(size_of::<IntentQueueHeader>()))
12096        .ok_or_else(|| {
12097            publication_input_error("intent entry capacity overflows its native allocation")
12098        })?;
12099    let required_payload = u64::try_from(effect.len())
12100        .ok()
12101        .and_then(|bytes| bytes.checked_add(final_payload_bytes));
12102    if effect.is_empty()
12103        || entry_capacity == 0
12104        || final_payload_bytes == 0
12105        || required_payload.is_none_or(|bytes| bytes > payload_capacity as u64)
12106    {
12107        return Err(publication_input_error(
12108            "initial intent requires its actual effect and reserved final-output capacity",
12109        ));
12110    }
12111    let header = IntentQueueHeader {
12112        abi: 1,
12113        count: 0,
12114        capacity: entry_capacity,
12115        payload_used_bytes: effect.len() as u64,
12116        payload_capacity_bytes: payload_capacity as u64,
12117        effect_offset_bytes: 0,
12118        effect_length_bytes: effect.len() as u64,
12119        chain_head: Identity256::default(),
12120    };
12121    Ok([
12122        SemanticStateRecord {
12123            role: SemanticStateRole::IntentEntries,
12124            index: 0,
12125            bytes: publication_abi_bytes(&[header]),
12126            capacity_bytes: entries_bytes,
12127        },
12128        SemanticStateRecord {
12129            role: SemanticStateRole::IntentPayload,
12130            index: 0,
12131            bytes: effect.to_vec(),
12132            capacity_bytes: payload_capacity,
12133        },
12134    ])
12135}
12136
12137fn initial_acknowledgement_record(
12138    entry_capacity: u64,
12139    payload_capacity: usize,
12140    intent_payload_capacity: usize,
12141    effect_len: usize,
12142) -> Result<SemanticStateRecord, SemanticTransitionError> {
12143    let count = usize::try_from(entry_capacity).map_err(|_| {
12144        publication_input_error("acknowledgement entry capacity overflows this host")
12145    })?;
12146    let required_receipts = count
12147        .checked_mul(169)
12148        .and_then(|bytes| bytes.checked_add(intent_payload_capacity))
12149        .and_then(|bytes| bytes.checked_add(count.saturating_sub(1).checked_mul(effect_len)?))
12150        .ok_or_else(|| {
12151            publication_input_error("complete acknowledgement reserve overflows this host")
12152        })?;
12153    let capacity_bytes = usize::try_from(entry_capacity)
12154        .ok()
12155        .and_then(|count| count.checked_mul(size_of::<AcknowledgementEntry>()))
12156        .and_then(|bytes| bytes.checked_add(payload_capacity))
12157        .and_then(|bytes| bytes.checked_add(size_of::<AcknowledgementQueueHeader>()))
12158        .ok_or_else(|| {
12159            publication_input_error("acknowledgement capacity overflows its native allocation")
12160        })?;
12161    if entry_capacity == 0 || effect_len == 0 || payload_capacity < required_receipts {
12162        return Err(publication_input_error("acknowledgement queue cannot retain every full receipt within its native intent bounds"));
12163    }
12164    Ok(SemanticStateRecord {
12165        role: SemanticStateRole::Acknowledgements,
12166        index: 0,
12167        bytes: publication_abi_bytes(&[AcknowledgementQueueHeader {
12168            abi: 1,
12169            count: 0,
12170            capacity: entry_capacity,
12171            payload_used_bytes: 0,
12172            payload_capacity_bytes: payload_capacity as u64,
12173            chain_head: Identity256::default(),
12174        }]),
12175        capacity_bytes,
12176    })
12177}
12178
12179fn publication_mutable_role(role: u64) -> bool {
12180    matches!(role, 3..=15 | 18..=25 | 30 | 32 | 33 | 39 | 44 | 51..=55)
12181}
12182
12183fn continuation_role(role: u64) -> bool {
12184    matches!(role, 1 | 4..=13 | 39 | 51..=55)
12185}
12186
12187fn validate_parent_records(
12188    parent: &SemanticParentBinding,
12189    tensors: &[PreparedSemanticTensor],
12190) -> Result<(), SemanticTransitionError> {
12191    validate_publication_counts(&parent.role_counts)?;
12192    validate_text_parent(
12193        &parent.source,
12194        parent.prefix.len() as u64,
12195        parent.prefix_capacity,
12196        parent.feedback_capacity,
12197        parent.max_position,
12198        parent.ring_head,
12199        parent.provenance_records,
12200    )?;
12201    if parent.feedback_capacity < 3
12202        || parent.rng.stream_serial >= 1 << 56
12203        || u64::from(parent.rng.model_generation) != parent.model_generation
12204        || parent.pad_token >= TEXT_CARDINALITY as u64
12205        || parent.terminal_tokens.is_empty()
12206        || parent
12207            .terminal_tokens
12208            .iter()
12209            .any(|&token| token >= TEXT_CARDINALITY as u64)
12210        || parent
12211            .terminal_tokens
12212            .iter()
12213            .copied()
12214            .collect::<BTreeSet<_>>()
12215            .len()
12216            != parent.terminal_tokens.len()
12217    {
12218        return Err(publication_input_error(
12219            "parent generations, feedback extent, or token contract mismatch",
12220        ));
12221    }
12222    for (position, slot) in parent.prefix.iter().enumerate() {
12223        if slot.kind != 1
12224            || slot.valid != 1
12225            || slot.committed != 1
12226            || slot.logical_position != position as u64
12227            || slot.token >= TEXT_CARDINALITY as u64
12228            || !matches!(slot.provenance, 1 | 2)
12229            || slot.provenance_record >= parent.provenance_records
12230            || slot.recomputed > 1
12231        {
12232            return Err(publication_input_error(
12233                "committed prefix source is not the exact ordered valid prefix",
12234            ));
12235        }
12236    }
12237    let mut keys = BTreeSet::new();
12238    for record in &parent.records {
12239        let role = record.role as u64;
12240        if is_tensor_role(role)
12241            || matches!(role, 1 | 3 | 14..=16 | 33 | 43 | 47 | 48 | 55)
12242            || record.index >= parent.role_counts[role as usize - 1]
12243            || (record.bytes.is_empty() && role != 2)
12244            || record.bytes.len() > record.capacity_bytes
12245            || !keys.insert((role, record.index))
12246        {
12247            return Err(publication_input_error(
12248                "duplicate, generated, tensor, empty, or out-of-capacity control record",
12249            ));
12250        }
12251        if role == 2
12252            && (parent
12253                .provenance_records
12254                .checked_mul(size_of::<TokenProvenance>() as u64)
12255                != Some(record.bytes.len() as u64)
12256                || (parent.provenance_records + 32)
12257                    .checked_mul(size_of::<TokenProvenance>() as u64)
12258                    .is_none_or(|n| n > record.capacity_bytes as u64))
12259        {
12260            return Err(publication_input_error(
12261                "token provenance records or append capacity differ from the actual source ledger",
12262            ));
12263        }
12264        if role == 44 {
12265            parent
12266                .model_contract_layout
12267                .validate(record.bytes.len() as u64)?;
12268        }
12269        if role == 30 {
12270            if record.bytes.len() < size_of::<IntentQueueHeader>() {
12271                return Err(publication_input_error(
12272                    "intent queue has no complete owner header",
12273                ));
12274            }
12275            // SAFETY: complete checked header bytes, integral padding-free ABI.
12276            let header = unsafe {
12277                record
12278                    .bytes
12279                    .as_ptr()
12280                    .cast::<IntentQueueHeader>()
12281                    .read_unaligned()
12282            };
12283            if header.abi != 1
12284                || header.count > header.capacity
12285                || header
12286                    .count
12287                    .checked_mul(size_of::<IntentEntry>() as u64)
12288                    .and_then(|n| n.checked_add(size_of::<IntentQueueHeader>() as u64))
12289                    != Some(record.bytes.len() as u64)
12290                || header
12291                    .capacity
12292                    .checked_mul(size_of::<IntentEntry>() as u64)
12293                    .and_then(|n| n.checked_add(size_of::<IntentQueueHeader>() as u64))
12294                    != Some(record.capacity_bytes as u64)
12295                || header.payload_used_bytes > header.payload_capacity_bytes
12296                || header.effect_length_bytes == 0
12297                || header
12298                    .effect_offset_bytes
12299                    .checked_add(header.effect_length_bytes)
12300                    .is_none_or(|n| n > header.payload_used_bytes)
12301            {
12302                return Err(publication_input_error(
12303                    "intent queue count, capacity, or actual effect payload is inconsistent",
12304                ));
12305            }
12306            let payload = parent
12307                .records
12308                .iter()
12309                .find(|record| record.role == SemanticStateRole::IntentPayload)
12310                .ok_or_else(|| publication_input_error("intent queue payload owner is absent"))?;
12311            if payload.bytes.len() as u64 != header.payload_used_bytes
12312                || payload.capacity_bytes as u64 != header.payload_capacity_bytes
12313            {
12314                return Err(publication_input_error(
12315                    "intent queue does not resolve to its actual payload allocation",
12316                ));
12317            }
12318        }
12319        if role == 32 {
12320            acknowledgement_receipts(&record.bytes, record.capacity_bytes)?;
12321        }
12322    }
12323    for tensor in tensors {
12324        let layout = &tensor.layout;
12325        if !is_tensor_role(layout.role)
12326            || layout.role >= 51
12327            || layout.index >= parent.role_counts[layout.role as usize - 1]
12328            || !keys.insert((layout.role, layout.index))
12329        {
12330            return Err(publication_input_error("initial parent tensor role is duplicate, uncomputed-active, or outside its model roster"));
12331        }
12332        tensor_layout_bytes(layout)?;
12333        if matches!(layout.role, 4 | 5) {
12334            if tensor.logical_begin != 0
12335                || tensor.logical_end != parent.prefix.len() as u64
12336                || layout.dimensions[2] != parent.prefix.len() as u64
12337            {
12338                return Err(publication_input_error(
12339                    "initial attention tensor does not cover exactly the acquired prefix",
12340                ));
12341            }
12342            prefix_capacity_layout(*layout, parent.prefix_capacity)?;
12343        } else if layout.logical_axis != u64::MAX
12344            || (matches!(layout.role, 18..=25)
12345                && (tensor.logical_begin != 0 || tensor.logical_end != 0))
12346        {
12347            return Err(publication_input_error(
12348                "non-positional model tensors require a non-sliced exact layout",
12349            ));
12350        }
12351        if matches!(layout.role, 8..=13) && (layout.scalar_type != 6 || layout.element_bytes != 4) {
12352            return Err(publication_input_error(
12353                "value and edit accumulators require original FP32 storage",
12354            ));
12355        }
12356    }
12357    for layout in &parent.active_layouts {
12358        if !matches!(layout.role, 51..=54)
12359            || layout.index >= parent.role_counts[layout.role as usize - 1]
12360            || !keys.insert((layout.role, layout.index))
12361            || tensor_layout_bytes(layout)? == 0
12362        {
12363            return Err(publication_input_error("active output capacity layout is absent, duplicate, or outside the cold model roster"));
12364        }
12365        validate_active_capacity(
12366            layout,
12367            32u64
12368                .checked_add(parent.feedback_capacity)
12369                .ok_or_else(|| publication_input_error("active row capacity overflow"))?,
12370        )?;
12371    }
12372    for role in 1..=55u64 {
12373        if matches!(role, 1 | 3 | 14..=16 | 33 | 43 | 47 | 48 | 55) {
12374            continue;
12375        }
12376        for index in 0..parent.role_counts[role as usize - 1] {
12377            if !keys.contains(&(role, index)) {
12378                return Err(publication_input_error(
12379                    "publication role lacks its actual cold owner",
12380                ));
12381            }
12382        }
12383    }
12384    Ok(())
12385}
12386
12387/// Validate the initial cold text import and derive its structural interval.
12388/// This establishes source metadata, not model completion or cache coverage.
12389fn validate_text_parent(
12390    slots: &[SourceSlot; 32],
12391    prefix_extent: u64,
12392    prefix_capacity: u64,
12393    feedback_capacity: u64,
12394    max_position: u64,
12395    ring_head: u64,
12396    provenance_records: u64,
12397) -> Result<u64, SemanticTransitionError> {
12398    let invalid = |detail: &str| SemanticTransitionError::InvalidInput {
12399        detail: detail.into(),
12400    };
12401    let text_limit = prefix_capacity
12402        .checked_add(32)
12403        .ok_or_else(|| invalid("text capacity overflow"))?;
12404    if prefix_extent > prefix_capacity
12405        || ring_head >= 32
12406        || text_limit
12407            .checked_add(feedback_capacity)
12408            .is_none_or(|limit| limit > max_position)
12409        || max_position != 262144
12410    {
12411        return Err(invalid("text prefix, ring or position capacity mismatch"));
12412    }
12413    let mut positions = BTreeSet::new();
12414    let mut filled = BTreeSet::new();
12415    for slot in slots {
12416        if slot.kind > 2
12417            || (if slot.kind == 2 {
12418                slot.token != MASK_TOKEN as u64
12419            } else {
12420                slot.token >= TEXT_CARDINALITY as u64
12421            })
12422        {
12423            return Err(invalid(
12424                "text token or row kind is outside its cold contract",
12425            ));
12426        }
12427        if slot.kind == 0 {
12428            if slot.logical_position != 0
12429                || slot.provenance != 0
12430                || slot.valid != 0
12431                || slot.committed != 0
12432                || slot.recomputed != 0
12433                || slot.provenance_record != 0
12434            {
12435                return Err(invalid("padding source slot carries active metadata"));
12436            }
12437            continue;
12438        }
12439        if slot.valid != 1
12440            || slot.committed != 0
12441            || slot.recomputed > 1
12442            || slot.logical_position < prefix_extent
12443            || slot.logical_position >= text_limit
12444            || !positions.insert(slot.logical_position)
12445        {
12446            return Err(invalid(
12447                "active source slot has inconsistent position or provenance",
12448            ));
12449        }
12450        if slot.kind == 1 {
12451            if !matches!(slot.provenance, 1 | 2) || slot.provenance_record >= provenance_records {
12452                return Err(invalid(
12453                    "filled source slot requires source or generated provenance",
12454                ));
12455            }
12456            filled.insert(slot.logical_position);
12457        } else if slot.provenance != 0 || slot.provenance_record != 0 || slot.recomputed != 0 {
12458            return Err(invalid(
12459                "mask source slot cannot carry filled-token coverage",
12460            ));
12461        }
12462    }
12463    let mut structural_end = prefix_extent;
12464    while filled.contains(&structural_end) {
12465        if structural_end == prefix_capacity {
12466            return Err(invalid(
12467                "contiguous source completion exceeds prefix capacity",
12468            ));
12469        }
12470        structural_end += 1;
12471    }
12472    Ok(structural_end)
12473}
12474
12475#[repr(C)]
12476#[derive(Clone, Copy)]
12477struct Descriptor {
12478    logits: u64,
12479    support: u64,
12480    scratch: u64,
12481    receipts: u64,
12482    state: u64,
12483    components: u64,
12484    codebooks: u64,
12485    arena: [u64; 7],
12486    policy: PolicyDescriptor,
12487    backward: PolicyBackward,
12488    task: u64,
12489    task_words: u64,
12490    task_return_bound: u64,
12491    publication: PublicationCommand,
12492    text: TextBinding,
12493    model_work: ModelWorkInput,
12494    replay: PreparedReplayDescriptor,
12495}
12496
12497#[derive(Clone, Copy)]
12498struct TransitionKernelPointers {
12499    logits: u64,
12500    support: u64,
12501    receipts: u64,
12502    state: u64,
12503    lease: u64,
12504    text: TextBinding,
12505    policy: PolicyDescriptor,
12506    model_work: ModelWorkInput,
12507}
12508
12509impl Descriptor {
12510    fn with_transition(mut self, original: TransitionKernelPointers) -> Self {
12511        self.logits = original.logits;
12512        self.support = original.support;
12513        self.receipts = original.receipts;
12514        self.state = original.state;
12515        self.publication.lease = original.lease;
12516        self.text = original.text;
12517        self.policy = original.policy;
12518        self.model_work = original.model_work;
12519        self
12520    }
12521}
12522
12523struct TransitionKernelIo<'a> {
12524    logits: &'a TrackedCudaSlice<f32>,
12525    support: &'a TrackedCudaSlice<u8>,
12526    receipts: &'a TrackedCudaSlice<SemanticTransitionReceipt>,
12527    state: &'a TrackedCudaSlice<DeviceState>,
12528    text: Option<&'a TextBindingStorage>,
12529    lease: Option<&'a TrackedCudaSlice<PublicationLease>>,
12530    model_work: Option<&'a PreparedModelWork>,
12531    replay_custody: Option<&'a PreparedReplayCustody>,
12532    model_update: Option<&'a PreparedModelUpdate>,
12533    training_selection: Option<&'a DeviceMemoryView<SemanticTrainingViewSelection>>,
12534    #[cfg(feature = "semantic-policy")]
12535    policy: Option<&'a PolicyStorage>,
12536}
12537
12538#[repr(C)]
12539#[derive(Clone, Copy, Default)]
12540struct PolicyField {
12541    embeddings: u64,
12542    biases: u64,
12543    cardinality: u32,
12544    null_category: i32,
12545    retained_offset: u64,
12546}
12547
12548#[repr(C)]
12549#[derive(Clone, Copy, Default)]
12550struct PolicyDescriptor {
12551    z: u64,
12552    recurrence: u64,
12553    positions: u64,
12554    hidden: u64,
12555    scores: u64,
12556    recurrent: u64,
12557    retained_scores: u64,
12558    retained_score_stride: u64,
12559    final_masks: u64,
12560    active_sets: u64,
12561    pwl_cells: u64,
12562    selected_score_vjps: u64,
12563    component_baselines: u64,
12564    fields: [PolicyField; 18],
12565    numerical: PolicyNumericalDescriptor,
12566}
12567
12568#[repr(C)]
12569#[derive(Clone, Copy, Default)]
12570struct PolicyNumericalDescriptor {
12571    parameter_errors: u64,
12572    baseline_errors: u64,
12573    parameter_domains: u64,
12574    text_domains: u64,
12575    baseline_domains: u64,
12576    hidden_errors: u64,
12577    score_errors: u64,
12578    recurrent_errors: u64,
12579    parameter_cells: u64,
12580    parameter_envelopes: u64,
12581    baseline_envelopes: u64,
12582    uniform: u64,
12583}
12584
12585#[repr(C)]
12586#[derive(Clone, Copy)]
12587struct PolicyUniformDescriptor {
12588    outputs: [u64; 3],
12589    roots: [u64; 3],
12590    recurrent: u64,
12591    hidden: u64,
12592    scores: u64,
12593    recurrent_cotangents: u64,
12594    score_cotangents: u64,
12595    score_roots: u64,
12596    status: u64,
12597    work: u64,
12598    training_rows: u64,
12599    return_bound: u64,
12600    loss_coefficients: [f64; 4],
12601}
12602
12603// SAFETY: repr(C) contains only plain scalar/pointer words; the cold native
12604// owner validates every extent and retains all addressed storage through use.
12605unsafe impl DeviceRepr for PolicyUniformDescriptor {}
12606
12607#[cfg(feature = "semantic-policy")]
12608struct PolicyUniformBuffers {
12609    descriptor: TrackedCudaSlice<PolicyUniformDescriptor>,
12610    initial_descriptor: PolicyUniformDescriptor,
12611    outputs: [TrackedCudaSlice<f64>; 3],
12612    roots: [TrackedCudaSlice<f64>; 3],
12613    scratch: [TrackedCudaSlice<f64>; 6],
12614    status: TrackedCudaSlice<u64>,
12615    work: TrackedCudaSlice<u64>,
12616    execute: CudaFunction,
12617}
12618
12619#[cfg(feature = "semantic-policy")]
12620impl PolicyUniformBuffers {
12621    fn record(&self, recorder: &mut LaunchRecorder) {
12622        recorder.read(&self.descriptor);
12623        for buffer in self.outputs.iter().chain(&self.roots).chain(&self.scratch) {
12624            recorder.read_write(buffer);
12625        }
12626        recorder.read_write(&self.status);
12627        recorder.read_write(&self.work);
12628    }
12629}
12630
12631#[repr(C)]
12632#[derive(Clone, Copy, Default)]
12633struct PolicyBackward {
12634    cotangents: u64,
12635    parameters: u64,
12636    text: u64,
12637    baselines: u64,
12638    recurrent: u64,
12639    scores: u64,
12640    status: u64,
12641    parameter_cells: u64,
12642    text_cells: u64,
12643    selection: u64,
12644    objective: u64,
12645    objective_groups: u64,
12646    objective_group_members: u64,
12647    roster_rows: u64,
12648    origin_candidate: u64,
12649    origin_lease: u64,
12650    origin_bank: u64,
12651    mode: u64,
12652    member_ordinal: u64,
12653    critic_term: u64,
12654    numerical: PolicyAdjointNumericalDescriptor,
12655}
12656
12657#[repr(C)]
12658#[derive(Clone, Copy, Default)]
12659struct PolicyAdjointNumericalDescriptor {
12660    parameter_errors: u64,
12661    text_errors: u64,
12662    baseline_errors: u64,
12663    parameter_domains: u64,
12664    text_domains: u64,
12665    baseline_domains: u64,
12666    recurrent_errors: u64,
12667    score_errors: u64,
12668    coefficient_errors: u64,
12669    parameter_cotangents: u64,
12670    text_cotangents: u64,
12671    baseline_cotangents: u64,
12672}
12673
12674#[cfg(feature = "semantic-policy")]
12675#[expect(
12676    clippy::too_many_arguments,
12677    reason = "policy VJP launch retains each original producer and destination explicitly"
12678)]
12679fn record_policy_vjp(
12680    domain: &ResidentExecutionDomain,
12681    poisoned: &mut bool,
12682    recorder: LaunchRecorder,
12683    execute: CudaFunction,
12684    descriptor: Descriptor,
12685    coefficients: &TrackedCudaSlice<f64>,
12686    score_cotangents: Option<&DeviceMemoryView<f64>>,
12687    baseline_snapshot: Option<&DeviceMemoryView<f32>>,
12688) -> Result<(), SemanticTransitionError> {
12689    enqueue_recorded(domain, poisoned, recorder, |enqueue| {
12690        // SAFETY: the recorder retains every forward/output allocation and,
12691        // for the external mode, the original cotangent producer. The
12692        // destination is the fixed F64 bank owned by this exact invocation.
12693        // The selected mode fills that bank inside the kernel from resident
12694        // objective/state owners and therefore performs no producer copy.
12695        unsafe {
12696            if let Some(score_cotangents) = score_cotangents {
12697                sys::cuMemcpyDtoDAsync_v2(
12698                    coefficients.device_ptr_value(),
12699                    *score_cotangents.device_ptr(),
12700                    COMPONENT_COUNT * 8,
12701                    enqueue.stream().cu_stream(),
12702                )
12703                .result()
12704                .map_err(|error| {
12705                    XlogError::Kernel(format!("policy cotangent snapshot: {error}"))
12706                })?;
12707            }
12708            if let Some(baseline_snapshot) = baseline_snapshot {
12709                sys::cuMemcpyDtoDAsync_v2(
12710                    descriptor.backward.baselines,
12711                    *baseline_snapshot.device_ptr(),
12712                    COMPONENT_COUNT * 4,
12713                    enqueue.stream().cu_stream(),
12714                )
12715                .result()
12716                .map_err(|error| XlogError::Kernel(format!("policy baseline snapshot: {error}")))?;
12717            }
12718            execute
12719                .launch_in(
12720                    enqueue,
12721                    LaunchConfig {
12722                        grid_dim: (1, 1, 1),
12723                        block_dim: (256, 1, 1),
12724                        shared_mem_bytes: 0,
12725                    },
12726                    (descriptor,),
12727                )
12728                .map_err(|error| XlogError::Kernel(format!("policy backward launch: {error}")))?;
12729        }
12730        Ok::<(), XlogError>(())
12731    })
12732}
12733
12734/// Dedicated device-owned adjoints for one exact policy invocation. Their tracked
12735/// allocations can be consumed on another recorded stream without host copies.
12736#[cfg(feature = "semantic-policy")]
12737pub struct SemanticPolicyGradients {
12738    pub binding: SemanticCatalogueBinding,
12739    pub invocation: SemanticRngBinding,
12740    pub layout: SemanticPolicyLayout,
12741    pub parameters: TrackedCudaSlice<f32>,
12742    pub text_logits: TrackedCudaSlice<f32>,
12743    pub component_baselines: TrackedCudaSlice<f32>,
12744    numerical: Arc<PolicyAdjointNumerical>,
12745    provider: Arc<CudaKernelProvider>,
12746    step_aliases: Arc<()>,
12747    publication: Arc<PublicationStorage>,
12748    continuation: Arc<TextBindingStorage>,
12749    vjp_workspace: Arc<PolicyVjpWorkspace>,
12750    support_cells: usize,
12751}
12752
12753#[cfg(feature = "semantic-policy")]
12754impl SemanticPolicyGradients {
12755    /// Export parameter, full MASK and baseline adjoints, then their three
12756    /// FP64 error envelopes and three selected magnitude/error bounds.
12757    /// Baseline adjoints are exact zeros for externally supplied score roots.
12758    /// Backward already ordered the caller's explicit consumer stream after the
12759    /// device error guard. Final step release joins that consumer's last use.
12760    pub fn into_dlpack(self) -> Result<[DlpackManagedTensor; 9], SemanticTransitionError> {
12761        let retained_owner: Arc<dyn Send + Sync> = self.vjp_workspace;
12762        export_policy_gradients(
12763            [
12764                self.parameters.into_bytes().view(),
12765                self.text_logits.into_bytes().view(),
12766                self.component_baselines.into_bytes().view(),
12767            ],
12768            &self.numerical,
12769            self.support_cells,
12770            self.layout.parameter_cells,
12771            self.provider.device().ordinal() as i32,
12772            self.step_aliases,
12773            self.publication,
12774            self.continuation,
12775            retained_owner,
12776        )
12777    }
12778}
12779
12780/// Device-selected actor, critic and cost adjoints for one exact prepared
12781/// policy invocation. Every invocation in the prepared proposal roster may
12782/// consume its original tape; the resident selection predicates all but the
12783/// selected candidate to graph-connected zeros.
12784#[cfg(feature = "semantic-policy")]
12785pub struct SemanticSelectedPolicyGradients {
12786    pub binding: SemanticCatalogueBinding,
12787    pub invocation: SemanticRngBinding,
12788    pub layout: SemanticPolicyLayout,
12789    pub parameters: TrackedCudaSlice<f32>,
12790    pub text_logits: TrackedCudaSlice<f32>,
12791    pub component_baselines: TrackedCudaSlice<f32>,
12792    numerical: Arc<PolicyAdjointNumerical>,
12793    provider: Arc<CudaKernelProvider>,
12794    step_aliases: Arc<()>,
12795    publication: Arc<PublicationStorage>,
12796    continuation: Arc<TextBindingStorage>,
12797    vjp_workspace: Arc<PolicyVjpWorkspace>,
12798    support_cells: usize,
12799}
12800
12801/// Device-selected policy roots recorded inside a prepared Update branch.
12802/// The retained native bank remains reusable while the mutually exclusive
12803/// Update branches are captured; every export is a fresh DLPack view.
12804#[cfg(feature = "semantic-policy")]
12805pub struct SemanticPreparedPolicyGradients {
12806    pub layout: SemanticPolicyLayout,
12807    parameters: DeviceMemoryView<f32>,
12808    text_logits: DeviceMemoryView<f32>,
12809    component_baselines: DeviceMemoryView<f32>,
12810    provider: Arc<CudaKernelProvider>,
12811    step_aliases: Arc<()>,
12812    publication: Arc<PublicationStorage>,
12813    continuation: Arc<TextBindingStorage>,
12814    owner: Arc<PolicyAdjointBuffers>,
12815    support_cells: usize,
12816}
12817
12818/// One fixed FP32[1] device scalar reduced in frozen actor-group order inside
12819/// the prepared Update bank. Its value is detached from the model graph; the
12820/// corresponding critic adjoints are returned with each original policy VJP.
12821#[cfg(feature = "semantic-policy")]
12822pub struct SemanticPreparedGroupCritic {
12823    value: DeviceMemoryView<f32>,
12824    provider: Arc<CudaKernelProvider>,
12825    step_aliases: Arc<()>,
12826    publication: Arc<PublicationStorage>,
12827}
12828
12829#[cfg(feature = "semantic-policy")]
12830impl SemanticPreparedGroupCritic {
12831    pub fn into_dlpack(self) -> Result<DlpackManagedTensor, SemanticTransitionError> {
12832        Ok(export_owned_allocation(
12833            unsafe { self.value.cast::<u8>() }.expect("FP32 group critic byte view"),
12834            vec![1],
12835            vec![1],
12836            (2, 32),
12837            self.provider.device().ordinal() as i32,
12838            self.step_aliases,
12839            self.publication,
12840            None,
12841            None,
12842        ))
12843    }
12844}
12845
12846#[cfg(feature = "semantic-policy")]
12847impl SemanticPreparedPolicyGradients {
12848    pub fn into_dlpack(self) -> Result<[DlpackManagedTensor; 9], SemanticTransitionError> {
12849        let retained_owner: Arc<dyn Send + Sync> = self.owner.clone();
12850        let values = [self.parameters, self.text_logits, self.component_baselines].map(|view| {
12851            // SAFETY: retained original FP32 adjoints have their exact byte span.
12852            unsafe { view.cast::<u8>() }.expect("FP32 policy adjoint byte view")
12853        });
12854        export_policy_gradients(
12855            values,
12856            &self.owner.numerical,
12857            self.support_cells,
12858            self.layout.parameter_cells,
12859            self.provider.device().ordinal() as i32,
12860            self.step_aliases,
12861            self.publication,
12862            self.continuation,
12863            retained_owner,
12864        )
12865    }
12866}
12867
12868#[cfg(feature = "semantic-policy")]
12869impl SemanticSelectedPolicyGradients {
12870    /// Export parameter, full MASK and component-baseline adjoints, in that
12871    /// order. The baseline result is the direct critic root for the retained
12872    /// original model graph; actor and cost share the exact policy tape.
12873    pub fn into_dlpack(self) -> Result<[DlpackManagedTensor; 9], SemanticTransitionError> {
12874        let retained_owner: Arc<dyn Send + Sync> = self.vjp_workspace;
12875        export_policy_gradients(
12876            [
12877                self.parameters.into_bytes().view(),
12878                self.text_logits.into_bytes().view(),
12879                self.component_baselines.into_bytes().view(),
12880            ],
12881            &self.numerical,
12882            self.support_cells,
12883            self.layout.parameter_cells,
12884            self.provider.device().ordinal() as i32,
12885            self.step_aliases,
12886            self.publication,
12887            self.continuation,
12888            retained_owner,
12889        )
12890    }
12891}
12892
12893#[cfg(feature = "semantic-policy")]
12894#[expect(
12895    clippy::too_many_arguments,
12896    reason = "all exports retain one original native tape and its final-use owners"
12897)]
12898fn export_policy_gradients(
12899    values: [DeviceMemoryView<u8>; 3],
12900    numerical: &PolicyAdjointNumerical,
12901    support_cells: usize,
12902    parameter_cells: usize,
12903    device: i32,
12904    step_aliases: Arc<()>,
12905    publication: Arc<PublicationStorage>,
12906    continuation: Arc<TextBindingStorage>,
12907    owner: Arc<dyn Send + Sync>,
12908) -> Result<[DlpackManagedTensor; 9], SemanticTransitionError> {
12909    let original = policy_numerical_producer_layouts(support_cells, parameter_cells)?;
12910    let mut text_error = original[7];
12911    text_error.dimensions[2] = 2;
12912    text_error.strides_bytes = [0; 4];
12913    let text_error = canonical_tensor_layout(text_error)?;
12914    // Native labels are interleaved per coordinate. The kernel explicitly
12915    // packs actor then full into these contiguous region-major exports.
12916    let layouts = [
12917        original[2],
12918        original[0],
12919        original[3],
12920        original[4],
12921        text_error,
12922        original[5],
12923        paired_cotangent_domain(original[6])?,
12924        paired_cotangent_domain(original[7])?,
12925        paired_cotangent_domain(original[8])?,
12926    ];
12927    let numerical_views = numerical.roots.iter().map(|buffer| {
12928        // SAFETY: numerical roots are retained aligned FP64 storage.
12929        unsafe { buffer.view().cast::<u8>() }.expect("FP64 policy numerical byte view")
12930    });
12931    let tensors = values
12932        .into_iter()
12933        .chain(numerical_views)
12934        .zip(layouts)
12935        .map(|(view, layout)| {
12936            let rank = layout.rank as usize;
12937            export_owned_allocation(
12938                view,
12939                layout.dimensions[..rank]
12940                    .iter()
12941                    .map(|&n| n as i64)
12942                    .collect(),
12943                layout.strides_bytes[..rank]
12944                    .iter()
12945                    .map(|&n| (n / layout.element_bytes) as i64)
12946                    .collect(),
12947                (2, (layout.element_bytes * 8) as u8),
12948                device,
12949                Arc::clone(&step_aliases),
12950                Arc::clone(&publication),
12951                Some(Arc::clone(&continuation)),
12952                Some(Arc::clone(&owner)),
12953            )
12954        })
12955        .collect::<Vec<_>>();
12956    Ok(tensors
12957        .try_into()
12958        .unwrap_or_else(|_| unreachable!("nine original policy gradient exports")))
12959}
12960
12961#[cfg(feature = "semantic-policy")]
12962fn policy_producer_layouts(
12963    support_cells: usize,
12964    parameter_cells: usize,
12965) -> Result<[SemanticTensorLayout; 4], SemanticTransitionError> {
12966    let layout = |index, scalar_type, element_bytes, rank, dimensions| {
12967        canonical_tensor_layout(SemanticTensorLayout {
12968            role: 0,
12969            index,
12970            scalar_type,
12971            element_bytes,
12972            rank,
12973            dimensions,
12974            logical_axis: u64::MAX,
12975            strides_bytes: [0; 4],
12976        })
12977    };
12978    Ok([
12979        layout(0, 6, 4, 2, [32, TEXT_CARDINALITY as u64, 0, 0])?,
12980        layout(1, 8, 1, 1, [support_cells as u64, 0, 0, 0])?,
12981        layout(2, 6, 4, 1, [parameter_cells as u64, 0, 0, 0])?,
12982        layout(3, 6, 4, 2, [1, COMPONENT_COUNT as u64, 0, 0])?,
12983    ])
12984}
12985
12986#[cfg(feature = "semantic-policy")]
12987fn policy_numerical_producer_layouts(
12988    support_cells: usize,
12989    parameter_cells: usize,
12990) -> Result<[SemanticTensorLayout; 9], SemanticTransitionError> {
12991    let values = policy_producer_layouts(support_cells, parameter_cells)?;
12992    let layout = |index, rank, dimensions| {
12993        canonical_tensor_layout(SemanticTensorLayout {
12994            role: 0,
12995            index,
12996            scalar_type: 9,
12997            element_bytes: 8,
12998            rank,
12999            dimensions,
13000            logical_axis: u64::MAX,
13001            strides_bytes: [0; 4],
13002        })
13003    };
13004    Ok([
13005        values[0],
13006        values[1],
13007        values[2],
13008        values[3],
13009        layout(4, 2, [parameter_cells as u64, 2, 0, 0])?,
13010        layout(5, 3, [1, COMPONENT_COUNT as u64, 2, 0])?,
13011        layout(6, 2, [parameter_cells as u64, 4, 0, 0])?,
13012        layout(7, 3, [32, TEXT_CARDINALITY as u64, 4, 0])?,
13013        layout(8, 3, [1, COMPONENT_COUNT as u64, 4, 0])?,
13014    ])
13015}
13016
13017#[cfg(feature = "semantic-policy")]
13018struct PolicyNumericalBuffers {
13019    parameter_errors: TrackedCudaSlice<f64>,
13020    baseline_errors: TrackedCudaSlice<f64>,
13021    parameter_domains: TrackedCudaSlice<f64>,
13022    text_domains: TrackedCudaSlice<f64>,
13023    baseline_domains: TrackedCudaSlice<f64>,
13024    hidden_errors: TrackedCudaSlice<f64>,
13025    score_errors: TrackedCudaSlice<f64>,
13026    recurrent_errors: TrackedCudaSlice<f64>,
13027    parameter_envelopes: TrackedCudaSlice<f64>,
13028    baseline_envelopes: TrackedCudaSlice<f64>,
13029    uniform: Arc<PolicyUniformBuffers>,
13030}
13031
13032#[cfg(feature = "semantic-policy")]
13033fn paired_cotangent_domain(
13034    mut layout: SemanticTensorLayout,
13035) -> Result<SemanticTensorLayout, SemanticTransitionError> {
13036    let rank = layout.rank as usize;
13037    layout.dimensions.copy_within(0..rank, 1);
13038    layout.dimensions[0] = 2;
13039    layout.rank += 1;
13040    layout.strides_bytes = [0; 4];
13041    canonical_tensor_layout(layout)
13042}
13043
13044#[cfg(feature = "semantic-policy")]
13045fn enqueue_policy_uniform_domains(
13046    domain: &ResidentExecutionDomain,
13047    poisoned: &mut bool,
13048    buffers: &PolicyBuffers,
13049    components: &TrackedCudaSlice<SemanticComponent>,
13050    support: &TrackedCudaSlice<u8>,
13051) -> Result<(), SemanticTransitionError> {
13052    let mut recorder = domain.new_strict_recorder();
13053    recorder.read(&buffers.parameters);
13054    recorder.read(&buffers.component_baselines);
13055    recorder.read(components);
13056    recorder.read(support);
13057    buffers.numerical.record(&mut recorder);
13058    recorder.write(&buffers.numerical.uniform.descriptor);
13059    let descriptor = SemanticTransitionSession::retained_policy_descriptor(buffers);
13060    enqueue_recorded(domain, poisoned, recorder, |enqueue| {
13061        // SAFETY: cold reservation and the immutable descriptor bind disjoint
13062        // scratch, original snapshots and complete output capacities. The
13063        // recorder orders all nine producers and the private descriptor's
13064        // device initialization before this one native transfer.
13065        unsafe {
13066            buffers.numerical.uniform.execute.clone().launch_in(
13067                enqueue,
13068                LaunchConfig {
13069                    grid_dim: (1, 1, 1),
13070                    block_dim: (256, 1, 1),
13071                    shared_mem_bytes: 0,
13072                },
13073                (
13074                    descriptor,
13075                    buffers.numerical.uniform.initial_descriptor,
13076                    components.device_ptr_value(),
13077                    support.device_ptr_value(),
13078                ),
13079            )
13080        }
13081        .map_err(|error| XlogError::Kernel(error.to_string()))
13082    })
13083}
13084
13085#[cfg(feature = "semantic-policy")]
13086fn export_policy_uniform_domains(
13087    buffers: &PolicyBuffers,
13088    support_cells: usize,
13089    device: i32,
13090    aliases: Arc<()>,
13091    publication: Arc<PublicationStorage>,
13092) -> Result<[DlpackManagedTensor; 3], SemanticTransitionError> {
13093    let original =
13094        policy_numerical_producer_layouts(support_cells, buffers.layout.parameter_cells)?;
13095    let owner: Arc<dyn Send + Sync> = buffers.numerical.uniform.clone();
13096    let tensors = buffers
13097        .numerical
13098        .uniform
13099        .outputs
13100        .iter()
13101        .zip([original[6], original[7], original[8]])
13102        .map(|(buffer, layout)| {
13103            let layout = paired_cotangent_domain(layout)?;
13104            let rank = layout.rank as usize;
13105            // SAFETY: the typed retained FP64 output allocation has the exact
13106            // native layout; no managed tensor or producer is fabricated.
13107            let view = unsafe { buffer.view().cast::<u8>() }.expect("FP64 domain byte view");
13108            Ok(export_owned_allocation(
13109                view,
13110                layout.dimensions[..rank]
13111                    .iter()
13112                    .map(|&n| n as i64)
13113                    .collect(),
13114                layout.strides_bytes[..rank]
13115                    .iter()
13116                    .map(|&n| (n / 8) as i64)
13117                    .collect(),
13118                (2, 64),
13119                device,
13120                Arc::clone(&aliases),
13121                Arc::clone(&publication),
13122                None,
13123                Some(Arc::clone(&owner)),
13124            ))
13125        })
13126        .collect::<Result<Vec<_>, SemanticTransitionError>>()?;
13127    Ok(tensors
13128        .try_into()
13129        .unwrap_or_else(|_| unreachable!("three uniform domain roots")))
13130}
13131
13132#[cfg(feature = "semantic-policy")]
13133impl PolicyNumericalBuffers {
13134    fn buffers(&self) -> [&TrackedCudaSlice<f64>; 10] {
13135        [
13136            &self.parameter_errors,
13137            &self.baseline_errors,
13138            &self.parameter_domains,
13139            &self.text_domains,
13140            &self.baseline_domains,
13141            &self.hidden_errors,
13142            &self.score_errors,
13143            &self.recurrent_errors,
13144            &self.parameter_envelopes,
13145            &self.baseline_envelopes,
13146        ]
13147    }
13148
13149    fn record(&self, recorder: &mut LaunchRecorder) {
13150        for buffer in self.buffers() {
13151            recorder.read_write(buffer);
13152        }
13153        self.uniform.record(recorder);
13154    }
13155
13156    fn descriptor(&self, parameter_cells: usize) -> PolicyNumericalDescriptor {
13157        PolicyNumericalDescriptor {
13158            parameter_errors: self.parameter_errors.device_ptr_value(),
13159            baseline_errors: self.baseline_errors.device_ptr_value(),
13160            parameter_domains: self.parameter_domains.device_ptr_value(),
13161            text_domains: self.text_domains.device_ptr_value(),
13162            baseline_domains: self.baseline_domains.device_ptr_value(),
13163            hidden_errors: self.hidden_errors.device_ptr_value(),
13164            score_errors: self.score_errors.device_ptr_value(),
13165            recurrent_errors: self.recurrent_errors.device_ptr_value(),
13166            parameter_cells: parameter_cells as u64,
13167            parameter_envelopes: self.parameter_envelopes.device_ptr_value(),
13168            baseline_envelopes: self.baseline_envelopes.device_ptr_value(),
13169            uniform: self.uniform.descriptor.device_ptr_value(),
13170        }
13171    }
13172}
13173
13174#[cfg(feature = "semantic-policy")]
13175struct PolicyBuffers {
13176    layout: SemanticPolicyLayout,
13177    parameters: TrackedCudaSlice<f32>,
13178    hidden: TrackedCudaSlice<f32>,
13179    scores: TrackedCudaSlice<f32>,
13180    retained_scores: TrackedCudaSlice<f32>,
13181    final_masks: TrackedCudaSlice<u8>,
13182    active_sets: TrackedCudaSlice<u8>,
13183    pwl_cells: TrackedCudaSlice<SemanticPolicyPwlCell>,
13184    selected_score_vjps: TrackedCudaSlice<SemanticPolicySelectedScoreVjp>,
13185    recurrent: TrackedCudaSlice<f32>,
13186    text_logits: TrackedCudaSlice<f32>,
13187    component_baselines: TrackedCudaSlice<f32>,
13188    numerical: PolicyNumericalBuffers,
13189    adjoints: Option<PolicyAdjointBuffers>,
13190    temporal_adjoints: Arc<PolicyAdjointBuffers>,
13191}
13192
13193/// Reserved with the original forward tape, then consumed by its sole backward.
13194/// Output storage is never recycled into a later invocation's working banks.
13195#[cfg(feature = "semantic-policy")]
13196struct PolicyAdjointBuffers {
13197    parameters: TrackedCudaSlice<f32>,
13198    text_logits: TrackedCudaSlice<f32>,
13199    component_baselines: TrackedCudaSlice<f32>,
13200    recurrent: TrackedCudaSlice<f32>,
13201    scores: TrackedCudaSlice<f32>,
13202    coefficients: TrackedCudaSlice<f64>,
13203    status: TrackedCudaSlice<u64>,
13204    numerical: Arc<PolicyAdjointNumerical>,
13205}
13206
13207#[cfg(feature = "semantic-policy")]
13208struct PolicyAdjointNumerical {
13209    roots: [TrackedCudaSlice<f64>; 6],
13210    recurrent_errors: TrackedCudaSlice<f64>,
13211    score_errors: TrackedCudaSlice<f64>,
13212    coefficient_errors: TrackedCudaSlice<f64>,
13213    root_cotangents: [TrackedCudaSlice<f64>; 3],
13214}
13215
13216#[cfg(feature = "semantic-policy")]
13217impl PolicyAdjointNumerical {
13218    fn buffers(&self) -> [&TrackedCudaSlice<f64>; 12] {
13219        [
13220            &self.roots[0],
13221            &self.roots[1],
13222            &self.roots[2],
13223            &self.roots[3],
13224            &self.roots[4],
13225            &self.roots[5],
13226            &self.recurrent_errors,
13227            &self.score_errors,
13228            &self.coefficient_errors,
13229            &self.root_cotangents[0],
13230            &self.root_cotangents[1],
13231            &self.root_cotangents[2],
13232        ]
13233    }
13234
13235    fn descriptor(&self) -> PolicyAdjointNumericalDescriptor {
13236        let pointers = self.buffers().map(TrackedCudaSlice::device_ptr_value);
13237        PolicyAdjointNumericalDescriptor {
13238            parameter_errors: pointers[0],
13239            text_errors: pointers[1],
13240            baseline_errors: pointers[2],
13241            parameter_domains: pointers[3],
13242            text_domains: pointers[4],
13243            baseline_domains: pointers[5],
13244            recurrent_errors: pointers[6],
13245            score_errors: pointers[7],
13246            coefficient_errors: pointers[8],
13247            parameter_cotangents: pointers[9],
13248            text_cotangents: pointers[10],
13249            baseline_cotangents: pointers[11],
13250        }
13251    }
13252}
13253
13254/// Every allocation referenced by a recorded policy VJP but not exported as an
13255/// adjoint. Exported gradient owners retain this workspace so deferred CUDA work
13256/// cannot observe reclaimed scratch or producer memory.
13257#[cfg(feature = "semantic-policy")]
13258struct PolicyVjpWorkspace {
13259    _component_baselines: Option<TrackedCudaSlice<f32>>,
13260    _recurrent: TrackedCudaSlice<f32>,
13261    _scores: TrackedCudaSlice<f32>,
13262    coefficients: TrackedCudaSlice<f64>,
13263    _status: TrackedCudaSlice<u64>,
13264    score_cotangents: Option<DeviceMemoryView<f64>>,
13265    _numerical: Arc<PolicyAdjointNumerical>,
13266}
13267
13268#[cfg(feature = "semantic-policy")]
13269struct PolicyStorage {
13270    buffers: PolicyBuffers,
13271    text_binding: Arc<TextBindingStorage>,
13272    _policy_witness: Option<SemanticTensorContentWitness>,
13273    replacement: Option<PolicyReplacement>,
13274    tape_live: bool,
13275    temporal_vjp_recorded: BTreeSet<(u64, usize)>,
13276}
13277
13278/// Original policy snapshots awaiting the same parent's continuation. This
13279/// owner is not executable and survives failed continuation handoffs.
13280#[cfg(feature = "semantic-policy")]
13281struct PendingPolicyStorage {
13282    buffers: PolicyBuffers,
13283    replacement: PolicyReplacement,
13284    witness: Option<(SemanticTensorContentWitness, u64)>,
13285    invocation: SemanticRngBinding,
13286}
13287
13288#[cfg(feature = "semantic-policy")]
13289impl std::ops::Deref for PolicyStorage {
13290    type Target = PolicyBuffers;
13291    fn deref(&self) -> &Self::Target {
13292        &self.buffers
13293    }
13294}
13295
13296#[cfg(feature = "semantic-policy")]
13297struct PolicyProducerViews {
13298    text_logits: DeviceMemoryView<f32>,
13299    product_support: DeviceMemoryView<u8>,
13300    parameters: DeviceMemoryView<f32>,
13301    component_baselines: DeviceMemoryView<f32>,
13302    numerical: [DeviceMemoryView<f64>; 5],
13303}
13304
13305#[cfg(feature = "semantic-policy")]
13306fn policy_source_views(
13307    originals: &[PreparedSemanticTensor],
13308) -> Result<PolicyProducerViews, SemanticTransitionError> {
13309    if originals.len() != 9 {
13310        return Err(publication_input_error(
13311            "policy requires its complete original producer roster",
13312        ));
13313    }
13314    let source = |index: usize| {
13315        originals[index]
13316            .source
13317            .clone()
13318            .ok_or_else(|| publication_input_error("policy producer storage is empty"))
13319    };
13320    // SAFETY: policy_producer_layouts and the original witness established
13321    // contiguous F32 shape, byte extents and alignment before this conversion.
13322    let text_logits = unsafe { source(0)?.cast::<f32>() }.ok_or_else(|| {
13323        publication_input_error("original text logits are not aligned F32 storage")
13324    })?;
13325    // SAFETY: the same typed original admission holds for model parameters.
13326    let parameters = unsafe { source(2)?.cast::<f32>() }.ok_or_else(|| {
13327        publication_input_error("original policy parameters are not aligned F32 storage")
13328    })?;
13329    // SAFETY: the fourth admitted producer is the exact rank-two FP32
13330    // component-baseline row issued by the original model invocation.
13331    let component_baselines = unsafe { source(3)?.cast::<f32>() }.ok_or_else(|| {
13332        publication_input_error("original component baselines are not aligned F32 storage")
13333    })?;
13334    let mut numerical = Vec::with_capacity(5);
13335    for index in 4..9 {
13336        // SAFETY: the original F64 layout/witness proves alignment and extent.
13337        numerical.push(unsafe { source(index)?.cast::<f64>() }.ok_or_else(|| {
13338            publication_input_error("original policy numerical view is not aligned F64 storage")
13339        })?);
13340    }
13341    Ok(PolicyProducerViews {
13342        text_logits,
13343        product_support: source(1)?,
13344        parameters,
13345        component_baselines,
13346        numerical: numerical
13347            .try_into()
13348            .unwrap_or_else(|_| unreachable!("five numerical producers")),
13349    })
13350}
13351
13352#[cfg(feature = "semantic-policy")]
13353fn enqueue_policy_snapshots(
13354    domain: &ResidentExecutionDomain,
13355    poisoned: &mut bool,
13356    buffers: &PolicyBuffers,
13357    support: &TrackedCudaSlice<u8>,
13358    original: &PolicyProducerViews,
13359) -> Result<(), SemanticTransitionError> {
13360    if original.text_logits.len() != buffers.text_logits.len()
13361        || original.product_support.len() != support.len()
13362        || original.parameters.len() != buffers.parameters.len()
13363        || original.component_baselines.len() != buffers.component_baselines.len()
13364    {
13365        return Err(publication_input_error(
13366            "original policy producers differ from their fixed native capacities",
13367        ));
13368    }
13369    let numerical_destinations = &buffers.numerical.buffers()[..5];
13370    if numerical_destinations
13371        .iter()
13372        .zip(&original.numerical)
13373        .any(|(destination, source)| destination.len() != source.len())
13374    {
13375        return Err(publication_input_error(
13376            "original numerical policy capacities differ",
13377        ));
13378    }
13379    let mut recorder = domain.new_strict_recorder();
13380    recorder.read(&original.text_logits);
13381    recorder.read(&original.product_support);
13382    recorder.read(&original.parameters);
13383    recorder.read(&original.component_baselines);
13384    recorder.write(&buffers.text_logits);
13385    recorder.write(support);
13386    recorder.write(&buffers.parameters);
13387    recorder.write(&buffers.component_baselines);
13388    for (destination, source) in numerical_destinations.iter().zip(&original.numerical) {
13389        recorder.read(source);
13390        recorder.write(*destination);
13391    }
13392    enqueue_recorded(domain, poisoned, recorder, |enqueue| {
13393        for (destination, source, bytes) in [
13394            (
13395                buffers.text_logits.device_ptr_value(),
13396                *original.text_logits.device_ptr(),
13397                original.text_logits.len() * 4,
13398            ),
13399            (
13400                support.device_ptr_value(),
13401                *original.product_support.device_ptr(),
13402                original.product_support.len(),
13403            ),
13404            (
13405                buffers.parameters.device_ptr_value(),
13406                *original.parameters.device_ptr(),
13407                original.parameters.len() * 4,
13408            ),
13409            (
13410                buffers.component_baselines.device_ptr_value(),
13411                *original.component_baselines.device_ptr(),
13412                original.component_baselines.len() * 4,
13413            ),
13414        ] {
13415            // SAFETY: fixed typed capacities bound each original source and
13416            // distinct retained destination; this performs only device copies.
13417            unsafe {
13418                sys::cuMemcpyDtoDAsync_v2(destination, source, bytes, enqueue.stream().cu_stream())
13419            }
13420            .result()
13421            .map_err(|error| XlogError::Kernel(error.to_string()))?;
13422        }
13423        for (destination, source) in numerical_destinations.iter().zip(&original.numerical) {
13424            // SAFETY: matching F64 original/retained extents are disjoint.
13425            unsafe {
13426                sys::cuMemcpyDtoDAsync_v2(
13427                    destination.device_ptr_value(),
13428                    *source.device_ptr(),
13429                    source.len() * 8,
13430                    enqueue.stream().cu_stream(),
13431                )
13432            }
13433            .result()
13434            .map_err(|error| XlogError::Kernel(error.to_string()))?;
13435        }
13436        Ok::<(), XlogError>(())
13437    })
13438}
13439
13440#[cfg(feature = "semantic-policy")]
13441struct PolicyReplacement {
13442    support: TrackedCudaSlice<u8>,
13443    receipts: TrackedCudaSlice<SemanticTransitionReceipt>,
13444    state: TrackedCudaSlice<DeviceState>,
13445}
13446
13447/// Original numerical inputs and receipts survive later publication and rebinding.
13448/// Backward consumes this exact invocation once, independently of the current bank.
13449#[cfg(feature = "semantic-policy")]
13450struct PolicyTape {
13451    invocation: SemanticRngBinding,
13452    refusal: Option<SemanticTransitionRefusal>,
13453    binding: SemanticCatalogueBinding,
13454    policy: PolicyStorage,
13455    support: TrackedCudaSlice<u8>,
13456    receipts: TrackedCudaSlice<SemanticTransitionReceipt>,
13457    prepared_bank: Option<usize>,
13458    // Ordinary proposals keep the exact device state observed with this tape;
13459    // later restored invocations may rebind the Session's working state.
13460    origin_state: Option<TrackedCudaSlice<DeviceState>>,
13461    // Immutable cold catalogue allocations remain shared by their original
13462    // invocation tapes; no later binding overwrites their bytes.
13463    components: DeviceMemoryView<SemanticComponent>,
13464    codebooks: DeviceMemoryView<u64>,
13465}
13466
13467#[cfg(feature = "semantic-policy")]
13468struct PolicyVjpRecording {
13469    descriptor: Descriptor,
13470    recorder: LaunchRecorder,
13471}
13472
13473#[cfg(feature = "semantic-policy")]
13474#[derive(Clone, Copy)]
13475enum PolicyVjpInput<'a> {
13476    External(&'a DeviceMemoryView<f64>),
13477    UpdateObjective {
13478        training: &'a SemanticSelectedTrainingView,
13479        origin_candidate: u64,
13480        origin_lease: &'a TrackedCudaSlice<PublicationLease>,
13481        origin_bank: usize,
13482    },
13483    GroupMember {
13484        training: &'a SemanticSelectedTrainingView,
13485        member_ordinal: u64,
13486        origin_candidate: u64,
13487        origin_lease: &'a TrackedCudaSlice<PublicationLease>,
13488        origin_bank: usize,
13489        critic_term: &'a DeviceMemoryView<f32>,
13490    },
13491    EditMember {
13492        training: &'a SemanticSelectedTrainingView,
13493        member_ordinal: u64,
13494        origin_candidate: u64,
13495        origin_lease: &'a TrackedCudaSlice<PublicationLease>,
13496        origin_bank: usize,
13497    },
13498}
13499
13500impl crate::cuda_compat::KernelParamStorage for Descriptor {
13501    fn as_kernel_param(&self) -> *mut std::ffi::c_void {
13502        (self as *const Self).cast_mut().cast()
13503    }
13504}
13505impl crate::cuda_compat::IntoKernelParamStorage for Descriptor {
13506    type Storage = Self;
13507    fn into_kernel_param_storage(self) -> Self {
13508        self
13509    }
13510}
13511
13512macro_rules! content_kernel_parameter {
13513    ($ty:ty) => {
13514        impl crate::cuda_compat::KernelParamStorage for $ty {
13515            fn as_kernel_param(&self) -> *mut std::ffi::c_void {
13516                (self as *const Self).cast_mut().cast()
13517            }
13518        }
13519        impl crate::cuda_compat::IntoKernelParamStorage for $ty {
13520            type Storage = Self;
13521            fn into_kernel_param_storage(self) -> Self {
13522                self
13523            }
13524        }
13525    };
13526}
13527content_kernel_parameter!(PublicationRange);
13528content_kernel_parameter!(SemanticTensorLayout);
13529content_kernel_parameter!(ContinuationInputs);
13530content_kernel_parameter!(PolicyDescriptor);
13531content_kernel_parameter!(prepared_replay::ReplayCopyDescriptor);
13532content_kernel_parameter!(learning_phase::FoldDeviceAssignment);
13533#[cfg(feature = "semantic-policy")]
13534content_kernel_parameter!(PolicyUniformDescriptor);
13535
13536const _: () = assert!(size_of::<PendingContinuation>() == 344);
13537const _: () = assert!(size_of::<ContinuationInputs>() == 208);
13538const _: () = assert!(size_of::<SemanticTransitionReceipt>() == 296);
13539const _: () = assert!(size_of::<SemanticTaskFacts>() == 88);
13540const _: () = assert!(size_of::<DeviceTaskEvaluation>() == 3328);
13541const _: () = assert!(size_of::<DeviceState>() == 7568);
13542const _: () = assert!(size_of::<PolicyField>() == 32);
13543const _: () = assert!(size_of::<PolicyNumericalDescriptor>() == 96);
13544const _: () = assert!(size_of::<PolicyUniformDescriptor>() == 160);
13545const _: () = assert!(size_of::<PolicyAdjointNumericalDescriptor>() == 96);
13546const _: () = assert!(size_of::<PolicyDescriptor>() == 776);
13547const _: () = assert!(size_of::<PolicyBackward>() == 256);
13548const _: () = assert!(size_of::<Descriptor>() == 1368);
13549const OBSERVATION_BYTES: usize =
13550    size_of::<DeviceState>() + COMPONENT_COUNT * size_of::<SemanticTransitionReceipt>();
13551
13552#[cfg(test)]
13553mod task_state_contract {
13554    use super::*;
13555
13556    #[test]
13557    fn text_null_requires_the_complete_singleton_receipt() {
13558        let mut receipt = SemanticTransitionReceipt {
13559            kind: COMPONENT_KIND_TEXT as u32,
13560            choice: TEXT_NULL as u32,
13561            legal_count: 1,
13562            active_count: 1,
13563            p: [1, 0, 0],
13564            q: [1, 0, 0],
13565            factor_denominator: [1, 0, 0],
13566            cdf_end: 1 << 63,
13567            mass: 1 << 63,
13568            ..SemanticTransitionReceipt::default()
13569        };
13570        assert!(canonical_text_null(&receipt));
13571        let exact = receipt;
13572        receipt.choice = 0;
13573        assert!(!canonical_text_null(&receipt));
13574        receipt = exact;
13575        receipt.p[1] = 1;
13576        assert!(!canonical_text_null(&receipt));
13577        receipt = exact;
13578        receipt.cdf_start = 1;
13579        assert!(!canonical_text_null(&receipt));
13580        receipt = exact;
13581        receipt.active_count = 2;
13582        assert!(!canonical_text_null(&receipt));
13583        receipt = exact;
13584        receipt.mass -= 1;
13585        assert!(!canonical_text_null(&receipt));
13586    }
13587
13588    #[test]
13589    fn task_state_bank_includes_actual_query_receipts() {
13590        assert_eq!(size_of::<DeviceState>(), 7568);
13591        assert_eq!(size_of::<Descriptor>(), 1368);
13592    }
13593
13594    #[test]
13595    fn ordinary_refusal_requires_original_coordinates_and_completed_cleanup() {
13596        let rng = SemanticRngBinding {
13597            model_generation: 3,
13598            family_id: 4,
13599            stream_serial: 5,
13600            proposal: 6,
13601        };
13602        let binding = SemanticActionCatalogue::current().binding();
13603        let original = DeviceState {
13604            model_generation: rng.model_generation,
13605            family_id: u32::from(rng.family_id),
13606            stream_serial: rng.stream_serial,
13607            proposal: 6,
13608            next_proposal: 6,
13609            catalogue_generation: binding.generation,
13610            catalogue_digest: binding.digest,
13611            binding_digest: binding.digest,
13612            status: 5,
13613            ..DeviceState::default()
13614        };
13615        assert_eq!(
13616            refused_terminal(&original, rng, binding, binding.digest, None).unwrap(),
13617            SemanticTransitionRefusal::NonFinitePolicyInput { completed_draws: 0 }
13618        );
13619        for mutation in 0..8 {
13620            let mut state = original;
13621            match mutation {
13622                0 => state.model_generation += 1,
13623                1 => state.family_id += 1,
13624                2 => state.stream_serial += 1,
13625                3 => state.next_proposal += 1,
13626                4 => state.blocks = COMPONENT_COUNT as u64,
13627                5 => state.importance_weight = 1.0,
13628                6 => state.cleanup_receipts[0][0] = 1,
13629                _ => state.retired_roots_mask = 4,
13630            }
13631            assert!(refused_terminal(&state, rng, binding, binding.digest, None).is_err());
13632        }
13633        for status in [0, 1, 3, 4, 6, 7, 8, 9, 10] {
13634            let mut state = original;
13635            state.status = status;
13636            assert!(refused_terminal(&state, rng, binding, binding.digest, None).is_err());
13637        }
13638        let mut state = original;
13639        state.status = 2;
13640        state.blocks = 50;
13641        assert_eq!(
13642            refused_terminal(&state, rng, binding, binding.digest, None).unwrap(),
13643            SemanticTransitionRefusal::InvalidFinalSupport {
13644                completed_draws: 50
13645            }
13646        );
13647        state.status = 11;
13648        assert!(refused_terminal(&state, rng, binding, binding.digest, None).is_err());
13649        state.execution_work.overflow = 1;
13650        assert_eq!(
13651            refused_terminal(&state, rng, binding, binding.digest, None).unwrap(),
13652            SemanticTransitionRefusal::WorkCounterOverflow {
13653                completed_draws: 50
13654            }
13655        );
13656        state.next_proposal += 1;
13657        assert!(refused_terminal(&state, rng, binding, binding.digest, None).is_err());
13658    }
13659
13660    #[test]
13661    fn refused_seal_cleanup_distinguishes_aliases_from_retired_private_roots() {
13662        let mut state = DeviceState::default();
13663        assert!(refused_root_cleanup(&state, 17, 2, 3).is_ok());
13664        state.semantic_receipts[3][33] = 1;
13665        state.semantic_receipts[3][39] = 17;
13666        state.semantic_receipts[3][1] = 2;
13667        state.semantic_receipts[3][34] = 2;
13668        state.semantic_receipts[3][35] = 3;
13669        assert!(refused_root_cleanup(&state, 17, 2, 3).is_err());
13670        state.retired_roots_mask = 1;
13671        assert!(refused_root_cleanup(&state, 17, 2, 3).is_ok());
13672        state.cleanup_receipts[1][39] = 17;
13673        assert!(
13674            refused_root_cleanup(&state, 17, 2, 3).is_err(),
13675            "base aliases are never retired"
13676        );
13677        state.semantic_receipts[3][1] = 1;
13678        state.semantic_receipts[3][34] = 7;
13679        state.cleanup_receipts[1][3] = 7;
13680        state.cleanup_receipts[1][4] = 4;
13681        assert!(refused_root_cleanup(&state, 17, 2, 3).is_ok());
13682        state.cleanup_receipts[1][4] = 3;
13683        assert!(refused_root_cleanup(&state, 17, 2, 3).is_err());
13684        state.cleanup_receipts[1][4] = 4;
13685        state.retired_roots_mask = 3;
13686        assert!(
13687            refused_root_cleanup(&state, 17, 2, 3).is_err(),
13688            "no seal exists in the other lane"
13689        );
13690    }
13691}
13692
13693/// Completed device outcome. A refusal carries no successor, selected-score
13694/// receipts, or derivative authority; it is not a successful observation.
13695#[derive(Clone, Debug, PartialEq)]
13696#[expect(
13697    clippy::large_enum_variant,
13698    reason = "published outcomes retain the original invocation owner without another allocation"
13699)]
13700pub enum SemanticTransitionOutcome {
13701    Published(SemanticTransitionObservation),
13702    Refused(SemanticTransitionRefusal),
13703}
13704
13705impl SemanticTransitionOutcome {
13706    /// Inspect the original result without relinquishing its invocation owner.
13707    /// A refusal preserves the same typed error as consuming the outcome.
13708    pub fn as_published(&self) -> Result<&SemanticTransitionObservation, SemanticTransitionError> {
13709        match self {
13710            Self::Published(observation) => Ok(observation),
13711            Self::Refused(refusal) => Err(refusal.into_error()),
13712        }
13713    }
13714
13715    pub fn into_published(self) -> Result<SemanticTransitionObservation, SemanticTransitionError> {
13716        match self {
13717            Self::Published(observation) => Ok(observation),
13718            Self::Refused(refusal) => Err(refusal.into_error()),
13719        }
13720    }
13721}
13722
13723/// Ordinary device refusal after authentic parent and cleanup reconciliation.
13724#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13725pub enum SemanticTransitionRefusal {
13726    InvalidFinalSupport {
13727        completed_draws: u64,
13728    },
13729    NonFinitePolicyInput {
13730        completed_draws: u64,
13731    },
13732    WorkCounterOverflow {
13733        completed_draws: u64,
13734    },
13735    InvalidTrainingView {
13736        status: u64,
13737    },
13738    RejectedModelUpdate {
13739        evidence: SemanticTrainingCanaryRefusalRecord,
13740    },
13741}
13742
13743impl SemanticTransitionRefusal {
13744    fn into_error(self) -> SemanticTransitionError {
13745        match self {
13746            Self::InvalidFinalSupport { completed_draws } => {
13747                SemanticTransitionError::InvalidFinalSupport { completed_draws }
13748            }
13749            Self::NonFinitePolicyInput { completed_draws } => {
13750                SemanticTransitionError::NonFinitePolicyInput { completed_draws }
13751            }
13752            Self::WorkCounterOverflow { completed_draws } => {
13753                SemanticTransitionError::WorkCounterOverflow { completed_draws }
13754            }
13755            Self::InvalidTrainingView { status } => {
13756                SemanticTransitionError::InvalidTrainingView { status }
13757            }
13758            Self::RejectedModelUpdate { evidence } => {
13759                SemanticTransitionError::RejectedModelUpdate {
13760                    evidence: Box::new(evidence),
13761                }
13762            }
13763        }
13764    }
13765}
13766
13767#[cfg(feature = "semantic-policy")]
13768fn decode_canary_refusal(
13769    record: SemanticTrainingCanaryRefusalRecord,
13770    results: &[SemanticTrainingCanaryResultRecord],
13771) -> Result<Option<SemanticTrainingCanaryRefusalRecord>, SemanticTransitionError> {
13772    if record.abi != 1 {
13773        return Err(SemanticTransitionError::ObservationMismatch);
13774    }
13775    if record.reason == 0 {
13776        let success = SemanticTrainingCanaryRefusalRecord {
13777            abi: 1,
13778            ..SemanticTrainingCanaryRefusalRecord::default()
13779        };
13780        return (record == success)
13781            .then_some(None)
13782            .ok_or(SemanticTransitionError::ObservationMismatch);
13783    }
13784    let reason = record
13785        .reason()
13786        .ok_or(SemanticTransitionError::ObservationMismatch)?;
13787    let original = results
13788        .iter()
13789        .find(|result| result.kind == record.kind)
13790        .ok_or(SemanticTransitionError::ObservationMismatch)?;
13791    if original.abi != 1
13792        || original.availability > 2
13793        || original.reason != record.reason
13794        || original.row_ordinal != record.row_ordinal
13795        || original.identity != record.identity
13796        || original.measurement_bits != record.measurement_bits
13797        || original.memory_used != record.memory_used
13798        || original.work_used != record.work_used
13799    {
13800        return Err(SemanticTransitionError::ObservationMismatch);
13801    }
13802    let lower = f64::from_bits(record.lower_bound_bits);
13803    let upper = f64::from_bits(record.upper_bound_bits);
13804    let measurement = f64::from_bits(record.measurement_bits);
13805    if !(1..=5).contains(&record.kind)
13806        || !lower.is_finite()
13807        || !upper.is_finite()
13808        || lower > upper
13809        || record.memory_limit == 0
13810        || record.work_limit == 0
13811        || (original.availability == 2
13812            && match reason {
13813                SemanticTrainingCanaryRefusalReason::NonFiniteMeasurement => {
13814                    measurement.is_finite()
13815                }
13816                SemanticTrainingCanaryRefusalReason::OutsideBounds => {
13817                    !measurement.is_finite() || (measurement >= lower && measurement <= upper)
13818                }
13819                SemanticTrainingCanaryRefusalReason::MemoryLimitExceeded => {
13820                    !measurement.is_finite()
13821                        || measurement < lower
13822                        || measurement > upper
13823                        || record.memory_used <= record.memory_limit
13824                }
13825                SemanticTrainingCanaryRefusalReason::WorkLimitExceeded => {
13826                    // The final work-limit pass can outrank an earlier retention
13827                    // or goal refusal, which skipped bounds and memory checks.
13828                    // Its original result therefore proves only this limit.
13829                    record.work_used <= record.work_limit
13830                }
13831                SemanticTrainingCanaryRefusalReason::IncompleteOperands
13832                | SemanticTrainingCanaryRefusalReason::ProtectedRetentionLost
13833                | SemanticTrainingCanaryRefusalReason::GoalWitnessInvalid
13834                | SemanticTrainingCanaryRefusalReason::WorkOverflow
13835                | SemanticTrainingCanaryRefusalReason::GenerationMismatch => false,
13836            })
13837    {
13838        return Err(SemanticTransitionError::ObservationMismatch);
13839    }
13840    Ok(Some(record))
13841}
13842
13843fn refused_terminal(
13844    state: &DeviceState,
13845    rng: SemanticRngBinding,
13846    catalogue: SemanticCatalogueBinding,
13847    binding_digest: Identity256,
13848    canary_refusal: Option<SemanticTrainingCanaryRefusalRecord>,
13849) -> Result<SemanticTransitionRefusal, SemanticTransitionError> {
13850    if state.model_generation != rng.model_generation
13851        || state.family_id != u32::from(rng.family_id)
13852        || state.stream_serial != rng.stream_serial
13853        || state.proposal != u64::from(rng.proposal)
13854        || state.next_proposal != state.proposal
13855        || state.blocks >= COMPONENT_COUNT as u64
13856        || state.catalogue_generation != catalogue.generation
13857        || state.catalogue_digest != catalogue.digest
13858        || state.binding_digest != binding_digest
13859        || state.importance_weight != 0.0
13860        || state.retired_roots_mask & !3 != 0
13861        || state.cleanup_receipts.iter().any(|receipt| receipt[0] != 0)
13862    {
13863        return Err(SemanticTransitionError::ObservationMismatch);
13864    }
13865    match state.status {
13866        2 => Ok(SemanticTransitionRefusal::InvalidFinalSupport {
13867            completed_draws: state.blocks,
13868        }),
13869        5 => Ok(SemanticTransitionRefusal::NonFinitePolicyInput {
13870            completed_draws: state.blocks,
13871        }),
13872        11 if state.execution_work.overflow == 1 => {
13873            Ok(SemanticTransitionRefusal::WorkCounterOverflow {
13874                completed_draws: state.blocks,
13875            })
13876        }
13877        12..=14 if state.execution_work.overflow == 0 && state.blocks == 0 => {
13878            Ok(SemanticTransitionRefusal::InvalidTrainingView {
13879                status: state.status - 11,
13880            })
13881        }
13882        15 if state.execution_work.overflow == 0 && state.blocks == 0 => {
13883            Ok(SemanticTransitionRefusal::RejectedModelUpdate {
13884                evidence: canary_refusal.ok_or(SemanticTransitionError::ObservationMismatch)?,
13885            })
13886        }
13887        _ => Err(SemanticTransitionError::ObservationMismatch),
13888    }
13889}
13890
13891fn refused_root_cleanup(
13892    state: &DeviceState,
13893    owner: u64,
13894    base_slot: u64,
13895    base_generation: u64,
13896) -> Result<(), SemanticTransitionError> {
13897    let mismatch = || SemanticTransitionError::ObservationMismatch;
13898    // This slot may describe either the inactive root retired by publication
13899    // admission or a later candidate discard. The completed kernel checks the
13900    // corresponding owner operation and changes status to failure on error.
13901    let cleanup = &state.cleanup_receipts[0];
13902    if cleanup.iter().any(|&word| word != 0) && (cleanup[0] != 0 || cleanup[39] != owner) {
13903        return Err(mismatch());
13904    }
13905    for lane in 0..2 {
13906        let sealed = &state.semantic_receipts[3 + lane * 3];
13907        let cleanup = &state.cleanup_receipts[1 + lane];
13908        let consumed = state.retired_roots_mask & (1 << lane) != 0;
13909        // Resident root-kind is 1; a cleared or failed seal owns no sealed root.
13910        if sealed[0] != 0 || sealed[33] != 1 {
13911            if consumed || cleanup.iter().any(|&word| word != 0) {
13912                return Err(mismatch());
13913            }
13914            continue;
13915        }
13916        if !consumed || sealed[39] != owner {
13917            return Err(mismatch());
13918        }
13919        match sealed[1] {
13920            // An unchanged seal only aliases the protected base, so there is
13921            // deliberately no retirement receipt for it.
13922            2 if sealed[34] == base_slot
13923                && sealed[35] == base_generation
13924                && cleanup.iter().all(|&word| word == 0) => {}
13925            1 if cleanup[0] == 0
13926                && cleanup[1] == 0
13927                && cleanup[39] == owner
13928                && cleanup[3] == sealed[34]
13929                && sealed[35].checked_add(1) == Some(cleanup[4]) => {}
13930            _ => return Err(mismatch()),
13931        }
13932    }
13933    Ok(())
13934}
13935
13936#[derive(Clone, Debug, PartialEq)]
13937pub struct SemanticTransitionObservation {
13938    pub components: Vec<SemanticTransitionReceipt>,
13939    pub root_handle: SemanticRootHandle,
13940    pub root: SemanticRootSnapshot,
13941    pub next_proposal: u64,
13942    pub lanes: [SemanticTransitionLane; 2],
13943    /// Full device-computed FP64 importance weight in original component order.
13944    /// The receipts retain the exact rational factors; this rounded reduction
13945    /// neither replaces them nor certifies the downstream parameter gradient.
13946    pub importance_weight: f64,
13947    /// Present only for the separately cold-bound finite evaluator.
13948    pub task_evaluation: Option<SemanticTaskEvaluation>,
13949}
13950
13951/// A task-local refusal is not a semantic infrastructure failure.
13952#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13953pub enum SemanticTaskRefusal {
13954    Scope,
13955    HardConstraint,
13956    FactCapacity,
13957    FuelExhausted,
13958}
13959
13960impl SemanticTaskRefusal {
13961    pub const fn canonical_kind(self) -> &'static str {
13962        match self {
13963            Self::Scope => "task-scope",
13964            Self::HardConstraint => "hard-constraint",
13965            Self::FactCapacity => "fact-capacity",
13966            Self::FuelExhausted => "fuel-exhausted",
13967        }
13968    }
13969}
13970
13971/// One native evaluation of the fixed base/learned roster. The selector runs
13972/// only on device; these are the resulting facts, not caller-supplied scores.
13973#[derive(Clone, Debug, PartialEq, Eq)]
13974pub struct SemanticTaskEvaluation {
13975    pub binding: Identity256,
13976    pub query_count: u64,
13977    pub winner: u64,
13978    pub return_value: i64,
13979    pub facts: [SemanticTaskFacts; 3],
13980}
13981
13982/// Device terminal and both ordered edit results. A refused lane has no root;
13983/// successful edit receipts preceding rollback are not published graph state.
13984#[derive(Clone, Debug, PartialEq, Eq)]
13985pub struct SemanticTransitionLane {
13986    /// No sealed root is produced for a task-local refusal. An owner refusal
13987    /// remains an actual owner error, distinct from an evaluator decision.
13988    pub root: Option<Result<(SemanticRootHandle, SemanticRootSnapshot), SemanticHypergraphError>>,
13989    pub task_refusal: Option<SemanticTaskRefusal>,
13990    /// Decoded binary rules attempted in the two edit slots, including a lane
13991    /// later rejected by a hard constraint. Graph support edits remain in `edits`.
13992    pub program_rules: [Option<crate::SemanticProgramRule>; 2],
13993    pub edits: [Result<Option<SemanticInsertOutcome>, SemanticHypergraphError>; 2],
13994    /// Actual owner work, retained even when the candidate is discarded.
13995    pub work: SemanticTransitionWork,
13996}
13997
13998/// Work performed by the two semantic edits of one learned candidate. These are
13999/// device counters, not estimates from the sampled actions or final truth alone.
14000#[repr(C)]
14001#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
14002pub struct SemanticTransitionWork {
14003    /// Calls to the modifying semantic owner, including a call that refuses.
14004    /// A NO_EDIT or a suppressed edit does not call that owner.
14005    pub edit_commands: u64,
14006    /// New reachable support attachments, or new materialized facts for an
14007    /// editable program, made before any candidate discard.
14008    pub added_supports: u64,
14009    /// Successful support edits that change a truth other than NEITHER, or
14010    /// changed query truths after program materialization.
14011    pub defined_truth_changes: u64,
14012}
14013
14014impl SemanticTransitionWork {
14015    #[cfg(any(test, feature = "semantic-policy"))]
14016    fn raw_structural_cost(self) -> u64 {
14017        self.edit_commands + self.added_supports + self.defined_truth_changes
14018    }
14019
14020    fn is_valid(self, editable_program: bool) -> bool {
14021        if self.edit_commands > 2 {
14022            return false;
14023        }
14024        if editable_program {
14025            self.added_supports <= crate::semantic_program::RESIDENT_PROGRAM_FACT_CAPACITY as u64
14026                && self.defined_truth_changes <= 3
14027                && (self.edit_commands != 0
14028                    || (self.added_supports == 0 && self.defined_truth_changes == 0))
14029        } else {
14030            self.added_supports <= self.edit_commands
14031                && self.defined_truth_changes <= self.added_supports
14032        }
14033    }
14034}
14035
14036/// Provider counters and explicit session stream waits. Compare snapshots around
14037/// launch only: cold binding/capture and terminal observation are outside it.
14038#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14039pub struct SemanticTransitionHostIoStats {
14040    pub htod_bytes: u64,
14041    pub dtoh_bytes: u64,
14042    pub htod_calls: u64,
14043    pub dtoh_calls: u64,
14044    pub launch_metadata_bytes: u64,
14045    pub launch_metadata_calls: u64,
14046    pub metadata_dtoh_calls: u64,
14047    pub observation_bytes: u64,
14048    pub observation_calls: u64,
14049    pub session_stream_waits: u64,
14050}
14051
14052#[derive(Clone, Debug, PartialEq, Eq)]
14053pub enum SemanticTransitionError {
14054    CatalogueMismatch,
14055    InvalidInput {
14056        detail: String,
14057    },
14058    InvalidFinalSupport {
14059        completed_draws: u64,
14060    },
14061    NonFinitePolicyInput {
14062        completed_draws: u64,
14063    },
14064    WorkCounterOverflow {
14065        completed_draws: u64,
14066    },
14067    InvalidPolicyGradient {
14068        status: u64,
14069    },
14070    InvalidTrainingView {
14071        status: u64,
14072    },
14073    RejectedModelUpdate {
14074        evidence: Box<SemanticTrainingCanaryRefusalRecord>,
14075    },
14076    InvalidTaskBank,
14077    InvalidTaskBase,
14078    TaskOwnerFailure,
14079    PublicationRefused {
14080        status: u64,
14081    },
14082    OverlappingInputs,
14083    OverlappingLaunch,
14084    UnconsumedPolicyTape,
14085    UnpublishedTask,
14086    NotBound,
14087    NotCaptured,
14088    NoPendingLaunch,
14089    GenerationExhausted,
14090    ObservationMismatch,
14091    Poisoned,
14092    Semantic(SemanticHypergraphError),
14093    Runtime {
14094        operation: &'static str,
14095        detail: String,
14096    },
14097}
14098
14099impl fmt::Display for SemanticTransitionError {
14100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14101        write!(f, "{self:?}")
14102    }
14103}
14104impl std::error::Error for SemanticTransitionError {}
14105
14106fn runtime_error(operation: &'static str, error: impl fmt::Display) -> SemanticTransitionError {
14107    SemanticTransitionError::Runtime {
14108        operation,
14109        detail: error.to_string(),
14110    }
14111}
14112
14113/// Pinned terminal bank, allocated before capture, never used for hot-loop metadata.
14114struct PinnedObservation {
14115    buffer: crate::device::PinnedHostBuffer,
14116}
14117
14118impl PinnedObservation {
14119    fn new(stream: Arc<CudaStream>) -> Result<Self, SemanticTransitionError> {
14120        Ok(Self {
14121            buffer: crate::device::PinnedHostBuffer::new(&stream, OBSERVATION_BYTES)
14122                .map_err(|error| runtime_error("pinned observation allocation", error))?,
14123        })
14124    }
14125
14126    fn enqueue_copy(&mut self, state: u64, receipts: u64, stream: &CudaStream) -> XlogResult<()> {
14127        // SAFETY: the recorder admits both fixed-size device ranges. The shared
14128        // pinned owner retains this whole batch, including a partially failed copy.
14129        unsafe {
14130            self.buffer.enqueue(stream, |ptr| {
14131                for (offset, source, len) in [
14132                    (0, state, size_of::<DeviceState>()),
14133                    (
14134                        size_of::<DeviceState>(),
14135                        receipts,
14136                        OBSERVATION_BYTES - size_of::<DeviceState>(),
14137                    ),
14138                ] {
14139                    // SAFETY: fixed-size ranges belong to this pinned bank and live device
14140                    // owners. Session waits before reading or freeing either allocation.
14141                    let code = {
14142                        sys::cuMemcpyDtoHAsync_v2(
14143                            ptr.add(offset).cast(),
14144                            source,
14145                            len,
14146                            stream.cu_stream(),
14147                        )
14148                    };
14149                    code.result()?;
14150                }
14151                Ok(())
14152            })
14153        }
14154        .map_err(|error| XlogError::Kernel(format!("semantic final observation copy: {error}")))
14155    }
14156
14157    /// Caller must have completed the stream wait after both copies.
14158    unsafe fn read(
14159        &mut self,
14160    ) -> Result<(DeviceState, Vec<SemanticTransitionReceipt>), SemanticTransitionError> {
14161        // SAFETY: both fixed-size copies initialized the complete byte bank.
14162        let bytes = unsafe { self.buffer.read_vec::<u8>(OBSERVATION_BYTES) }
14163            .map_err(|error| runtime_error("pinned observation read", error))?;
14164        // SAFETY: caller establishes completion; allocations and integral ABI sizes
14165        // are checked, and unaligned reads do not require additional host alignment.
14166        let state = unsafe { bytes.as_ptr().cast::<DeviceState>().read_unaligned() };
14167        let components = (0..COMPONENT_COUNT)
14168            .map(|i| unsafe {
14169                bytes
14170                    .as_ptr()
14171                    .add(size_of::<DeviceState>() + i * size_of::<SemanticTransitionReceipt>())
14172                    .cast::<SemanticTransitionReceipt>()
14173                    .read_unaligned()
14174            })
14175            .collect();
14176        Ok((state, components))
14177    }
14178}
14179
14180/// Single owner of one serial transition stream, graph, scratch, and receipt bank.
14181/// Retains the provider independently of the caller's handle.
14182pub struct SemanticTransitionSession {
14183    // Drop waits before destroying the exec, then retires its device storage.
14184    captured: Option<CapturedCudaGraph>,
14185    domain: ResidentExecutionDomain,
14186    stream: Arc<CudaStream>,
14187    graph: std::mem::ManuallyDrop<SemanticHypergraph>,
14188    root: SemanticRootHandle,
14189    base_snapshot: SemanticRootSnapshot,
14190    codebooks: ActionCodebooks,
14191    device_codebooks: TrackedCudaSlice<u64>,
14192    device_components: TrackedCudaSlice<SemanticComponent>,
14193    // Private observer/checker results never enter the proposal codebooks.
14194    task: Option<(TaskEvaluationBinding, TrackedCudaSlice<u64>)>,
14195    // A cold read can precede the final observed-source/authority import. The
14196    // later binding must reproduce this exact executed task content.
14197    cold_content: Option<(SemanticTaskContentIdentity, [crate::SemanticTruth; 3])>,
14198    initial_prefill: Option<InitialPrefillStage>,
14199    retained_initial_prefill: Option<RetainedInitialPrefillContent>,
14200    checkpoint_initial_prefill: Option<CheckpointInitialPrefill>,
14201    training_views: Option<Arc<SemanticTrainingViewArena>>,
14202    training_origins: Option<Arc<TrackedCudaSlice<SemanticTrainingViewOriginRecord>>>,
14203    task_epoch: u64,
14204    // Terminal observation does not publish a world. Keep the chosen roots and
14205    // raw banks immutable until the joint publisher consumes this pending tuple.
14206    task_observed: bool,
14207    publication: Option<Arc<PublicationStorage>>,
14208    learning_phases: Vec<SemanticLearningPhaseRecord>,
14209    publication_uploads: Vec<(usize, PublicationPayload)>,
14210    publication_issuer: Arc<()>,
14211    readers: BTreeMap<u64, PublishedReader>,
14212    steps: BTreeMap<u64, StepContentStorage>,
14213    prepared_segment: Option<PreparedSegmentState>,
14214    prepared_resources: Vec<Arc<dyn Send + Sync>>,
14215    next_reader: u64,
14216    continuation_base: Option<u64>,
14217    text_binding: Option<Arc<TextBindingStorage>>,
14218    admitted_transition: Option<(u64, u64, SemanticTransitionKind)>,
14219    release_events: Vec<cudarc::driver::CudaEvent>,
14220    logits: TrackedCudaSlice<f32>,
14221    support: TrackedCudaSlice<u8>,
14222    scratch: TrackedCudaSlice<u64>,
14223    receipts: TrackedCudaSlice<SemanticTransitionReceipt>,
14224    state: TrackedCudaSlice<DeviceState>,
14225    pinned: PinnedObservation,
14226    execute: CudaFunction,
14227    #[cfg(feature = "semantic-policy")]
14228    policy: Option<PolicyStorage>,
14229    #[cfg(feature = "semantic-policy")]
14230    pending_policy: Option<PendingPolicyStorage>,
14231    #[cfg(feature = "semantic-policy")]
14232    policy_tapes: Vec<PolicyTape>,
14233    rng: Option<SemanticRngBinding>,
14234    next_proposal: u64,
14235    pending: bool,
14236    poisoned: bool,
14237    stream_waits: u64,
14238    // All captured work and storage retire before their driver/allocation owner.
14239    provider: Arc<CudaKernelProvider>,
14240}
14241
14242/// Results retain each actual device invocation. An early admission refusal
14243/// owns no numerical invocation, selected receipts, or derivative authority.
14244/// Intermediate root records are historical receipts; a later step may retire
14245/// their slots. Acquire the canonical final reader for the current publication.
14246#[derive(Clone, Debug)]
14247#[expect(
14248    clippy::large_enum_variant,
14249    reason = "completed outcomes retain their original invocation and step owners"
14250)]
14251pub enum SemanticPreparedStepOutcome {
14252    Skipped {
14253        step: SemanticPreparedStep,
14254        status: u64,
14255    },
14256    Completed {
14257        step: SemanticPreparedStep,
14258        invocation: SemanticRngBinding,
14259        bank: u8,
14260        transition: SemanticTransitionKind,
14261        outcome: SemanticTransitionOutcome,
14262    },
14263}
14264
14265const _: () = assert!(
14266    size_of::<PreparedStepResult>()
14267        == size_of::<PublicationHeader>() + 32 + size_of::<AttemptReceipt>()
14268);
14269
14270fn prepared_step_allocation_bytes(
14271    input_bytes: usize,
14272    feedback_bytes: usize,
14273    policy_bytes: usize,
14274) -> Result<u64, SemanticTransitionError> {
14275    [
14276        size_of::<PublicationLease>(),
14277        size_of::<PreparedStepResult>(),
14278        input_bytes,
14279        feedback_bytes,
14280        policy_bytes,
14281    ]
14282    .into_iter()
14283    .try_fold(0usize, |sum, bytes| {
14284        sum.checked_add(bytes)
14285            .ok_or(SemanticTransitionError::GenerationExhausted)
14286    })
14287    .and_then(|bytes| {
14288        u64::try_from(bytes).map_err(|_| SemanticTransitionError::GenerationExhausted)
14289    })
14290}
14291
14292fn prepared_segment_allocation_bytes(
14293    step_bytes: u64,
14294    transition_bound: usize,
14295    training_origin_bytes: usize,
14296) -> Result<u64, SemanticTransitionError> {
14297    if transition_bound == 0 {
14298        return Err(publication_input_error(
14299            "a prepared segment requires a positive transition bound",
14300        ));
14301    }
14302    u64::try_from(transition_bound)
14303        .ok()
14304        .and_then(|bound| step_bytes.checked_mul(bound))
14305        .and_then(|bytes| {
14306            u64::try_from(training_origin_bytes)
14307                .ok()
14308                .and_then(|origin_bytes| bytes.checked_add(origin_bytes))
14309        })
14310        .ok_or(SemanticTransitionError::GenerationExhausted)
14311}
14312
14313/// Frozen bounds for the content, work, and external allocations currently
14314/// admitted during prepared-segment construction. Numerical-domain buffers
14315/// require their own native-derived extension before the full peak is claimed.
14316#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14317pub struct SemanticSegmentColdCapacity {
14318    pub tensor_content_capacity: usize,
14319    pub model_work_capacity: usize,
14320    pub segment_capacity_bytes: u64,
14321    pub other_external_cuda_bytes: u64,
14322}
14323
14324impl SemanticSegmentColdCapacity {
14325    fn external_floor(self) -> Result<u64, SemanticTransitionError> {
14326        if self.tensor_content_capacity == 0
14327            || self.model_work_capacity == 0
14328            || self.segment_capacity_bytes == 0
14329        {
14330            return Err(publication_input_error(
14331                "prepared segment requires positive frozen native capacities and external slab bytes",
14332            ));
14333        }
14334        self.segment_capacity_bytes
14335            .checked_add(self.other_external_cuda_bytes)
14336            .ok_or(SemanticTransitionError::GenerationExhausted)
14337    }
14338
14339    fn content_cells(self) -> Result<usize, SemanticTransitionError> {
14340        self.tensor_content_capacity
14341            .checked_mul(4)
14342            .ok_or(SemanticTransitionError::GenerationExhausted)
14343    }
14344
14345    fn content_bytes(self) -> Result<u64, SemanticTransitionError> {
14346        self.content_cells()?
14347            .checked_mul(size_of::<u64>())
14348            .and_then(|bytes| u64::try_from(bytes).ok())
14349            .ok_or(SemanticTransitionError::GenerationExhausted)
14350    }
14351
14352    fn model_work_bytes(self) -> Result<u64, SemanticTransitionError> {
14353        self.model_work_capacity
14354            .checked_mul(size_of::<ModelWorkEvent>() + 3 * size_of::<u64>())
14355            .and_then(|bytes| u64::try_from(bytes).ok())
14356            .ok_or(SemanticTransitionError::GenerationExhausted)
14357    }
14358
14359    fn late_native_bytes(self, steps: usize) -> Result<u64, SemanticTransitionError> {
14360        self.content_bytes()?
14361            .checked_add(self.model_work_bytes()?)
14362            .and_then(|bytes| bytes.checked_mul(u64::try_from(steps).ok()?))
14363            .ok_or(SemanticTransitionError::GenerationExhausted)
14364    }
14365}
14366
14367#[cfg(feature = "semantic-policy")]
14368fn policy_buffer_bytes(
14369    layout: &SemanticPolicyLayout,
14370    mask_cells: usize,
14371) -> Result<usize, SemanticTransitionError> {
14372    let differentiable_cells = [
14373        layout.parameter_cells,
14374        layout.score_cells(),
14375        layout.recurrent_cells(),
14376        32 * TEXT_CARDINALITY,
14377    ]
14378    .into_iter()
14379    .try_fold(0usize, |sum, cells| {
14380        sum.checked_add(cells)
14381            .ok_or(SemanticTransitionError::GenerationExhausted)
14382    })?;
14383    let primal_cells = differentiable_cells
14384        .checked_add(layout.retained_score_cells())
14385        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14386    let adjoint_cells = differentiable_cells
14387        .checked_add(COMPONENT_COUNT)
14388        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14389    let adjoint_cells = adjoint_cells
14390        .checked_mul(2)
14391        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14392    let numerical_cells = [
14393        // Original E/D plus explicitly assembled primal envelopes.
14394        (layout.parameter_cells, 9usize),
14395        (COMPONENT_COUNT, 9),
14396        (32 * TEXT_CARDINALITY, 4),
14397        (128, 3),
14398        (layout.score_cells(), 3),
14399        (layout.recurrent_cells(), 3),
14400    ]
14401    .into_iter()
14402    .try_fold(0usize, |total, (cells, width)| {
14403        cells
14404            .checked_mul(width)
14405            .and_then(|cells| total.checked_add(cells))
14406            .ok_or(SemanticTransitionError::GenerationExhausted)
14407    })?;
14408    let adjoint_numerical_cells = differentiable_cells
14409        .checked_add(COMPONENT_COUNT)
14410        .and_then(|cells| cells.checked_mul(8))
14411        .and_then(|cells| {
14412            layout
14413                .parameter_cells
14414                .checked_add(32 * TEXT_CARDINALITY)
14415                .and_then(|roots| roots.checked_add(COMPONENT_COUNT))
14416                // In addition to the internal coherent labels above, export
14417                // full E (two doubles) and actor/full D (eight doubles).
14418                .and_then(|roots| roots.checked_mul(10))
14419                .and_then(|roots| cells.checked_add(roots))
14420        })
14421        .and_then(|cells| cells.checked_add(8 * COMPONENT_COUNT))
14422        .and_then(|cells| cells.checked_mul(2))
14423        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14424    let numerical_cells = numerical_cells
14425        .checked_add(adjoint_numerical_cells)
14426        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14427    let uniform_cells = layout
14428        .parameter_cells
14429        .checked_add(COMPONENT_COUNT)
14430        .and_then(|cells| cells.checked_mul(2))
14431        // Every unknown mapped text row has the same category domain. Keep
14432        // one private row and the required 32-row region-major public output.
14433        .and_then(|cells| cells.checked_add(33 * TEXT_CARDINALITY))
14434        // Private coherent labels and distinct region-major export storage.
14435        .and_then(|cells| cells.checked_mul(8))
14436        .and_then(|cells| cells.checked_add(layout.recurrent_cells() * 12))
14437        .and_then(|cells| cells.checked_add(layout.score_cells() * 12))
14438        .and_then(|cells| cells.checked_add(128 * 4 + COMPONENT_COUNT * 8))
14439        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14440    let numerical_cells = numerical_cells
14441        .checked_add(uniform_cells)
14442        .ok_or(SemanticTransitionError::GenerationExhausted)?;
14443    primal_cells
14444        // Each differentiable primal bank has a dedicated adjoint bank. Only the
14445        // forward hidden vector is shared scratch. A second retained adjoint bank
14446        // is reserved for temporal Update capture; coefficients and status keep
14447        // their own types in both banks.
14448        .checked_add(adjoint_cells)
14449        .and_then(|cells| cells.checked_add(128))
14450        .and_then(|cells| cells.checked_add(COMPONENT_COUNT))
14451        .and_then(|cells| cells.checked_mul(size_of::<f32>()))
14452        .and_then(|bytes| bytes.checked_add(2 * COMPONENT_COUNT * size_of::<f64>()))
14453        .and_then(|bytes| bytes.checked_add(2 * size_of::<u64>()))
14454        .and_then(|bytes| {
14455            bytes.checked_add(12 * size_of::<u64>() + size_of::<PolicyUniformDescriptor>())
14456        })
14457        .and_then(|bytes| {
14458            numerical_cells
14459                .checked_mul(8)
14460                .and_then(|extra| bytes.checked_add(extra))
14461        })
14462        .and_then(|bytes| bytes.checked_add(COMPONENT_COUNT * size_of::<SemanticPolicyPwlCell>()))
14463        .and_then(|bytes| {
14464            bytes.checked_add(COMPONENT_COUNT * size_of::<SemanticPolicySelectedScoreVjp>())
14465        })
14466        .and_then(|bytes| {
14467            mask_cells
14468                .checked_mul(2)
14469                .and_then(|masks| bytes.checked_add(masks))
14470        })
14471        .ok_or(SemanticTransitionError::GenerationExhausted)
14472}
14473
14474fn validate_rebinding_ownership(
14475    prepared_segment: Option<&PreparedSegmentState>,
14476    unreconciled_acquisition: bool,
14477) -> Result<(), SemanticTransitionError> {
14478    if prepared_segment.is_some() {
14479        return Err(publication_input_error(
14480            "a prepared segment still owns its executable and native resources",
14481        ));
14482    }
14483    if unreconciled_acquisition {
14484        return Err(publication_input_error(
14485            "an unreconciled acquisition still owns its native step",
14486        ));
14487    }
14488    Ok(())
14489}
14490
14491fn validate_prepared_completion(
14492    lease: &PublicationLease,
14493    parent: &PublicationHeader,
14494    result: &PreparedStepResult,
14495    instance: Identity256,
14496) -> Result<SemanticTransitionKind, SemanticTransitionError> {
14497    if lease.abi != 1
14498        || lease.status != 0
14499        || lease.active != 0
14500        || lease.instance != instance
14501        || lease.bank > 1
14502        || lease.bank != lease.word & 1
14503        || lease.epoch != lease.word >> 1
14504        || parent.abi != 1
14505        || parent.instance != instance
14506        || parent.publication_word != lease.word
14507        || parent.sealed_epoch != lease.epoch
14508        || result.abi != 1
14509        || result.header.abi != 1
14510        || result.header.instance != instance
14511        || result.header.publication_word != result.word
14512        || result.header.sealed_epoch != result.word >> 1
14513        || result.advanced > 1
14514        || result.advanced != u64::from(result.word != lease.word && result.refusal == 0)
14515    {
14516        return Err(SemanticTransitionError::ObservationMismatch);
14517    }
14518    if result.word != lease.word {
14519        let epoch = lease
14520            .epoch
14521            .checked_add(1)
14522            .filter(|&epoch| epoch <= u64::MAX >> 1)
14523            .ok_or(SemanticTransitionError::ObservationMismatch)?;
14524        if result.word != (epoch << 1) | ((lease.word ^ 1) & 1)
14525            || result.header.base_word != lease.word
14526            || result.attempt.abi != 2
14527            || result.attempt.transition_kind != lease.transition_kind
14528            || result.attempt.instance != result.header.instance
14529            || result.attempt.base_word != lease.word
14530            || result.attempt.next_word != result.word
14531            || result.attempt.logical_digest != result.header.logical_digest
14532        {
14533            return Err(SemanticTransitionError::ObservationMismatch);
14534        }
14535    } else if result.attempt != AttemptReceipt::default() {
14536        return Err(SemanticTransitionError::ObservationMismatch);
14537    }
14538    match lease.transition_kind {
14539        1 => Ok(SemanticTransitionKind::Proposal),
14540        2 => Ok(SemanticTransitionKind::Recompute),
14541        3 => Ok(SemanticTransitionKind::Drain),
14542        4 => Ok(SemanticTransitionKind::Update),
14543        _ => Err(SemanticTransitionError::ObservationMismatch),
14544    }
14545}
14546
14547#[cfg(feature = "semantic-policy")]
14548impl SemanticTransitionSession {
14549    /// Submit this Session's complete graph once with the freshly validated
14550    /// canonical authority snapshot. The metadata upload precedes graph launch.
14551    pub fn launch_prepared_segment(
14552        &mut self,
14553        authority_decisions: Vec<u8>,
14554    ) -> Result<(), SemanticTransitionError> {
14555        self.ensure_quiescent()?;
14556        let storage = Arc::clone(
14557            self.publication
14558                .as_ref()
14559                .ok_or(SemanticTransitionError::NotBound)?,
14560        );
14561        let build = self
14562            .prepared_segment
14563            .as_ref()
14564            .ok_or(SemanticTransitionError::NotCaptured)?;
14565        if !build.finished
14566            || build.submitted
14567            || self.captured.is_none()
14568            || authority_decisions.is_empty()
14569        {
14570            return Err(publication_input_error(
14571                "prepared submission requires one unused graph and fresh canonical authority bytes",
14572            ));
14573        }
14574        for token in &build.tokens {
14575            let prepared = self
14576                .steps
14577                .get(token)
14578                .and_then(|step| step.prepared.as_ref())
14579                .ok_or(SemanticTransitionError::ObservationMismatch)?;
14580            if prepared.transition_recorded != PREPARED_TRANSITION_BANKS
14581                || prepared.branches.iter().any(|branch| {
14582                    branch.continuation.as_ref().is_none_or(|continuation| {
14583                        continuation.inputs.authority_bytes != authority_decisions.len() as u64
14584                    })
14585                })
14586            {
14587                return Err(publication_input_error(
14588                    "fresh authority snapshot differs from the captured continuation byte extent",
14589                ));
14590            }
14591        }
14592        let authority = storage
14593            .continuation_templates
14594            .iter()
14595            .find(|range| range.role == 39 && range.index == 0)
14596            .ok_or(SemanticTransitionError::ObservationMismatch)?;
14597        let slot = usize::try_from(authority.storage_slot)
14598            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
14599        let destination = storage
14600            .allocations
14601            .get(slot)
14602            .ok_or(SemanticTransitionError::ObservationMismatch)?;
14603        if authority.offset_bytes != 0 || authority_decisions.len() > destination.len() {
14604            return Err(publication_input_error(
14605                "fresh authority snapshot exceeds its original fixed allocation",
14606            ));
14607        }
14608        let recorder = self.prepared_segment_recorder()?;
14609        self.prepared_segment
14610            .as_mut()
14611            .expect("checked segment")
14612            .submit()?;
14613        self.publication_uploads = vec![(slot, PublicationPayload::Metadata(authority_decisions))];
14614        let result = (|| {
14615            let PublicationPayload::Metadata(bytes) = &self.publication_uploads[0].1 else {
14616                unreachable!("owned authority metadata")
14617            };
14618            let mut destination = storage.allocations[slot].view().slice(..bytes.len());
14619            self.provider
14620                .htod_launch_metadata_sync_copy_into(bytes, &mut destination)
14621                .map_err(|error| runtime_error("prepared fresh authority upload", error))?;
14622            let graph = self
14623                .captured
14624                .as_ref()
14625                .expect("checked original captured graph");
14626            enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
14627                graph.launch_in(enqueue)
14628            })
14629        })();
14630        if result.is_err() {
14631            self.poisoned = true;
14632            return result;
14633        }
14634        self.pending = true;
14635        Ok(())
14636    }
14637
14638    /// True only after the full ordered roster, work certificates, publication
14639    /// lineage and terminal reader release have been reconciled successfully.
14640    /// Stream completion alone does not establish a recoverable result.
14641    pub fn prepared_segment_completion_known(&self) -> bool {
14642        self.prepared_segment
14643            .as_ref()
14644            .is_some_and(|build| build.completed)
14645    }
14646
14647    pub fn complete_prepared_segment(
14648        &mut self,
14649    ) -> Result<Vec<SemanticPreparedStepOutcome>, SemanticTransitionError> {
14650        if self.is_poisoned() {
14651            return Err(SemanticTransitionError::Poisoned);
14652        }
14653        if !self.pending
14654            || !self
14655                .prepared_segment
14656                .as_ref()
14657                .is_some_and(|build| build.submitted && !build.completed)
14658        {
14659            return Err(SemanticTransitionError::NoPendingLaunch);
14660        }
14661        let result = self.complete_prepared_segment_inner();
14662        if result.is_err() {
14663            self.poisoned = true;
14664        } else {
14665            self.pending = false;
14666            self.publication_uploads.clear();
14667            self.continuation_base = None;
14668            self.admitted_transition = None;
14669            self.text_binding = None;
14670        }
14671        result
14672    }
14673
14674    fn complete_prepared_segment_inner(
14675        &mut self,
14676    ) -> Result<Vec<SemanticPreparedStepOutcome>, SemanticTransitionError> {
14677        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
14678            .map_err(|error| runtime_error("prepared completion stream admission", error))?;
14679        wait_on_stream(
14680            &self.stream,
14681            &mut self.poisoned,
14682            &mut self.stream_waits,
14683            "prepared graph terminal wait",
14684            CudaStream::synchronize,
14685        )?;
14686        let handles = self
14687            .prepared_segment
14688            .as_ref()
14689            .expect("submitted segment")
14690            .handles()?;
14691        let storage = Arc::clone(
14692            self.publication
14693                .as_ref()
14694                .ok_or(SemanticTransitionError::NotBound)?,
14695        );
14696        let mut outcomes = Vec::new();
14697        outcomes
14698            .try_reserve_exact(handles.len())
14699            .map_err(|error| runtime_error("prepared outcome reservation", error))?;
14700        let mut previous = None;
14701        for step in handles {
14702            let prepared = self.steps[&step.token]
14703                .prepared
14704                .as_ref()
14705                .ok_or(SemanticTransitionError::ObservationMismatch)?;
14706            let reader = prepared.reader.view();
14707            let result_view = prepared.result.view();
14708            let lease = self.publication_read(reader)?[0];
14709            let result = self.publication_read(result_view)?[0];
14710            if result.abi == 0 {
14711                if lease.active != 0
14712                    || lease.abi != 0
14713                    || lease.transition_kind != 0
14714                    || !matches!(lease.status, 1..=5 | 7)
14715                {
14716                    return Err(SemanticTransitionError::ObservationMismatch);
14717                }
14718                #[cfg(feature = "semantic-policy")]
14719                let token = step.token;
14720                let outcome = SemanticPreparedStepOutcome::Skipped {
14721                    step,
14722                    status: lease.status,
14723                };
14724                #[cfg(feature = "semantic-policy")]
14725                {
14726                    self.steps
14727                        .get_mut(&token)
14728                        .expect("retained original step")
14729                        .prepared
14730                        .as_mut()
14731                        .expect("retained original prepared owner")
14732                        .observed_outcome = Some(outcome.clone());
14733                }
14734                outcomes.push(outcome);
14735                continue;
14736            }
14737            let inputs = Arc::clone(
14738                self.steps[&step.token]
14739                    .inputs
14740                    .as_ref()
14741                    .ok_or(SemanticTransitionError::ObservationMismatch)?,
14742            );
14743            let parent = self.publication_read(inputs.header.view())?[0];
14744            if previous.is_some_and(|header| header != parent) {
14745                return Err(SemanticTransitionError::ObservationMismatch);
14746            }
14747            let transition =
14748                validate_prepared_completion(&lease, &parent, &result, storage.instance)?;
14749            let bank = u8::try_from(lease.bank)
14750                .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
14751            let (state_view, receipts, update_refusal_view) = {
14752                let prepared = self.steps[&step.token]
14753                    .prepared
14754                    .as_ref()
14755                    .expect("original prepared owner");
14756                let branch = prepared
14757                    .branches
14758                    .get(usize::from(bank))
14759                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
14760                (
14761                    branch.state.view(),
14762                    branch
14763                        .receipts
14764                        .as_ref()
14765                        .ok_or(SemanticTransitionError::ObservationMismatch)?
14766                        .view(),
14767                    branch
14768                        .model_update
14769                        .as_ref()
14770                        .map(|update| (update.refusal.view(), update.canary_results.view())),
14771                )
14772            };
14773            let canary_refusal = match (transition, update_refusal_view) {
14774                (SemanticTransitionKind::Update, Some((view, results))) => {
14775                    let results = self.publication_read(results)?;
14776                    decode_canary_refusal(self.publication_read(view)?[0], &results)?
14777                }
14778                (SemanticTransitionKind::Update, None) | (_, Some(_)) => {
14779                    return Err(SemanticTransitionError::ObservationMismatch);
14780                }
14781                (_, None) => None,
14782            };
14783            let state = self.publication_read(state_view)?[0];
14784            if transition != SemanticTransitionKind::Drain {
14785                let work = self.steps[&step.token]
14786                    .prepared
14787                    .as_ref()
14788                    .expect("original prepared owner")
14789                    .model_work
14790                    .as_ref()
14791                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
14792                if !state
14793                    .execution_work
14794                    .validate_model(&work.recording, state.status == 11)
14795                {
14796                    return Err(SemanticTransitionError::ObservationMismatch);
14797                }
14798            }
14799            let components = if transition == SemanticTransitionKind::Proposal {
14800                self.publication_read(receipts)?
14801            } else {
14802                Vec::new()
14803            };
14804            let invocation = parent.rng_binding()?;
14805            let outcome = self.reconcile_prepared_transition(
14806                &parent,
14807                &result,
14808                state,
14809                components,
14810                invocation,
14811                PreparedTransitionEvidence {
14812                    transition,
14813                    canary_refusal,
14814                },
14815            )?;
14816            previous = Some(result.header);
14817            #[cfg(feature = "semantic-policy")]
14818            if transition == SemanticTransitionKind::Proposal {
14819                self.take_prepared_policy_tape(
14820                    &step,
14821                    usize::from(bank),
14822                    invocation,
14823                    match &outcome {
14824                        SemanticTransitionOutcome::Refused(refusal) => Some(*refusal),
14825                        _ => None,
14826                    },
14827                )?;
14828            }
14829            self.steps
14830                .get_mut(&step.token)
14831                .expect("retained original step")
14832                .prepared
14833                .as_mut()
14834                .expect("retained original prepared owner")
14835                .observed = true;
14836            #[cfg(feature = "semantic-policy")]
14837            if transition == SemanticTransitionKind::Update
14838                && matches!(&outcome, SemanticTransitionOutcome::Published(_))
14839            {
14840                self.steps
14841                    .get_mut(&step.token)
14842                    .expect("retained original step")
14843                    .prepared
14844                    .as_mut()
14845                    .expect("retained original prepared owner")
14846                    .group_update_published = true;
14847            }
14848            #[cfg(feature = "semantic-policy")]
14849            let token = step.token;
14850            let outcome = SemanticPreparedStepOutcome::Completed {
14851                step,
14852                invocation,
14853                bank,
14854                transition,
14855                outcome,
14856            };
14857            #[cfg(feature = "semantic-policy")]
14858            {
14859                let prepared = self
14860                    .steps
14861                    .get_mut(&token)
14862                    .expect("retained original step")
14863                    .prepared
14864                    .as_mut()
14865                    .expect("retained original prepared owner");
14866                prepared.observed_parent = Some(parent);
14867                prepared.observed_result = Some(result);
14868                prepared.observed_outcome = Some(outcome.clone());
14869            }
14870            outcomes.push(outcome);
14871        }
14872        let control = self.publication_read(storage.control.view())?[0];
14873        if control.abi != 1
14874            || control.instance != storage.instance
14875            || control.reader_gate != 0
14876            || previous.is_some_and(|header| control.word != header.publication_word)
14877        {
14878            return Err(SemanticTransitionError::ObservationMismatch);
14879        }
14880        self.prepared_segment
14881            .as_mut()
14882            .expect("submitted segment")
14883            .completed = true;
14884        Ok(outcomes)
14885    }
14886
14887    fn reconcile_prepared_transition(
14888        &mut self,
14889        parent: &PublicationHeader,
14890        result: &PreparedStepResult,
14891        state: DeviceState,
14892        components: Vec<SemanticTransitionReceipt>,
14893        invocation: SemanticRngBinding,
14894        evidence: PreparedTransitionEvidence,
14895    ) -> Result<SemanticTransitionOutcome, SemanticTransitionError> {
14896        let PreparedTransitionEvidence {
14897            transition,
14898            canary_refusal,
14899        } = evidence;
14900        if result.refusal != 0 || state.status == 10 {
14901            return Err(SemanticTransitionError::PublicationRefused {
14902                status: result.refusal,
14903            });
14904        }
14905        if matches!(state.status, 2 | 5 | 11 | 12..=15) {
14906            let canary_refusal = if state.status == 15 {
14907                Some(canary_refusal.ok_or(SemanticTransitionError::ObservationMismatch)?)
14908            } else {
14909                None
14910            };
14911            let refusal = refused_terminal(
14912                &state,
14913                invocation,
14914                SemanticActionCatalogue::current().binding(),
14915                self.binding().digest,
14916                canary_refusal,
14917            )?;
14918            if result.word != parent.publication_word || result.header != *parent {
14919                return Err(SemanticTransitionError::ObservationMismatch);
14920            }
14921            let (root, snapshot) = self.observe_publication_root(&state, parent, 0)?;
14922            refused_root_cleanup(
14923                &state,
14924                self.graph.transition_arena()[1],
14925                u64::from(root.slot()),
14926                root.generation(),
14927            )?;
14928            self.root = root;
14929            self.base_snapshot = snapshot;
14930            self.next_proposal = parent.proposal;
14931            return Ok(SemanticTransitionOutcome::Refused(refusal));
14932        }
14933        match state.status {
14934            7 => return Err(SemanticTransitionError::InvalidTaskBank),
14935            8 => return Err(SemanticTransitionError::InvalidTaskBase),
14936            9 => return Err(SemanticTransitionError::TaskOwnerFailure),
14937            _ => {}
14938        }
14939        let next = parent
14940            .proposal
14941            .checked_add(u64::from(transition == SemanticTransitionKind::Proposal))
14942            .ok_or(SemanticTransitionError::GenerationExhausted)?;
14943        if state.status != 0
14944            || result.word == parent.publication_word
14945            || result.header.proposal != next
14946        {
14947            return Err(SemanticTransitionError::ObservationMismatch);
14948        }
14949        let winner = if transition == SemanticTransitionKind::Proposal {
14950            state.task_evaluation.winner
14951        } else {
14952            0
14953        };
14954        let index = match winner {
14955            0 => 0,
14956            1 => 3,
14957            2 => 6,
14958            _ => return Err(SemanticTransitionError::ObservationMismatch),
14959        };
14960        if winner > 0 && state.retired_roots_mask & (1 << (winner - 1)) != 0 {
14961            return Err(SemanticTransitionError::ObservationMismatch);
14962        }
14963        let root = self.observe_publication_root(&state, &result.header, index)?;
14964        self.finish_observed_transition(
14965            state,
14966            components,
14967            invocation,
14968            Some((result.header, root, transition)),
14969            true,
14970        )
14971    }
14972}
14973
14974#[cfg(test)]
14975mod prepared_completion_tests {
14976    use super::*;
14977
14978    #[test]
14979    fn prepared_allocation_plan_counts_original_banks_before_expanding_bound() {
14980        let schema = SemanticFeedbackSchema::new([&[1u8; 64], &[2u8; 64], &[3u8; 64]]).unwrap();
14981        let feedback = FeedbackAllocationPlan::new(&schema, 2, 3).unwrap();
14982        let expected_feedback = 2 * schema.feature_width * size_of::<f32>()
14983            + 2 * 9
14984            + (2 * 42 + 2 + 3 + 3 * SEMANTIC_FEEDBACK_SUPPORT_FIELDS.len()) * size_of::<u64>()
14985            + 6 * 4 * size_of::<u64>();
14986        assert_eq!(feedback.bytes, expected_feedback);
14987        let input_bytes = PreparedStepInputs::allocation_bytes(&[]).unwrap();
14988        assert_eq!(
14989            input_bytes,
14990            size_of::<PublicationHeader>() + 32 * size_of::<SourceSlot>() + u64::BITS as usize
14991        );
14992        let plans = [
14993            StepInputPlan {
14994                role: 1,
14995                index: 0,
14996                layout: SemanticTensorLayout::default(),
14997                banks: [
14998                    StepInputBankPlan {
14999                        storage_slot: 0,
15000                        span: 0..1024,
15001                    },
15002                    StepInputBankPlan {
15003                        storage_slot: 0,
15004                        span: 0..1024,
15005                    },
15006                ],
15007            },
15008            StepInputPlan {
15009                role: 2,
15010                index: 0,
15011                layout: SemanticTensorLayout::default(),
15012                banks: [
15013                    StepInputBankPlan {
15014                        storage_slot: 1,
15015                        span: 0..32,
15016                    },
15017                    StepInputBankPlan {
15018                        storage_slot: 2,
15019                        span: 0..32,
15020                    },
15021                ],
15022            },
15023        ];
15024        assert_eq!(
15025            PreparedStepInputs::allocation_bytes(&plans).unwrap(),
15026            input_bytes
15027                + 2 * (size_of::<PublicationRange>() + 2 * size_of::<PublicationStepInput>())
15028                + 32
15029        );
15030        assert!(PreparedStepInputs::allocation_bytes(&[StepInputPlan {
15031            banks: [
15032                StepInputBankPlan {
15033                    storage_slot: 1,
15034                    span: 0..usize::MAX,
15035                },
15036                StepInputBankPlan {
15037                    storage_slot: 2,
15038                    span: 0..usize::MAX,
15039                },
15040            ],
15041            ..plans[1].clone()
15042        }])
15043        .is_err());
15044        let step_bytes = prepared_step_allocation_bytes(input_bytes, feedback.bytes, 0).unwrap();
15045        assert_eq!(
15046            step_bytes,
15047            (input_bytes
15048                + feedback.bytes
15049                + size_of::<PublicationLease>()
15050                + size_of::<PreparedStepResult>()) as u64
15051        );
15052        assert_eq!(
15053            prepared_segment_allocation_bytes(step_bytes, 3, 0).unwrap(),
15054            3 * step_bytes
15055        );
15056        assert!(prepared_segment_allocation_bytes(step_bytes, 0, 0).is_err());
15057        assert!(prepared_segment_allocation_bytes(step_bytes, usize::MAX, 0).is_err());
15058    }
15059
15060    #[test]
15061    fn prepared_scope_blocks_ordinary_rebinding_until_retirement() {
15062        let issuer = Arc::new(());
15063        let mut build = PreparedSegmentState::new(
15064            Arc::clone(&issuer),
15065            vec![1],
15066            std::iter::once(SemanticTransitionKind::Proposal),
15067            SemanticSegmentColdCapacity {
15068                tensor_content_capacity: 1,
15069                model_work_capacity: 1,
15070                segment_capacity_bytes: 1,
15071                other_external_cuda_bytes: 0,
15072            },
15073        )
15074        .unwrap();
15075        assert!(validate_rebinding_ownership(None, false).is_ok());
15076        assert!(validate_rebinding_ownership(None, true).is_err());
15077        assert!(validate_rebinding_ownership(Some(&build), false).is_err());
15078        let step = build.handles().unwrap().remove(0);
15079        build.enter(&step, &issuer).unwrap();
15080        build.leave(&step, &issuer).unwrap();
15081        build.finish().unwrap();
15082        build.submit().unwrap();
15083        build.completed = true;
15084        assert!(validate_rebinding_ownership(Some(&build), false).is_err());
15085    }
15086
15087    #[test]
15088    fn prepared_submission_is_once_only_after_complete_construction() {
15089        let issuer = Arc::new(());
15090        let mut build = PreparedSegmentState::new(
15091            Arc::clone(&issuer),
15092            vec![1],
15093            std::iter::once(SemanticTransitionKind::Proposal),
15094            SemanticSegmentColdCapacity {
15095                tensor_content_capacity: 1,
15096                model_work_capacity: 1,
15097                segment_capacity_bytes: 1,
15098                other_external_cuda_bytes: 0,
15099            },
15100        )
15101        .unwrap();
15102        assert!(build.submit().is_err());
15103        let step = build.handles().unwrap().remove(0);
15104        build.enter(&step, &issuer).unwrap();
15105        build.leave(&step, &issuer).unwrap();
15106        build.finish().unwrap();
15107        build.submit().unwrap();
15108        assert!(build.submit().is_err());
15109        build.completed = true;
15110        assert!(build.submit().is_err());
15111    }
15112
15113    #[test]
15114    fn completion_uses_original_parent_and_requires_device_release() {
15115        let parent = PublicationHeader {
15116            abi: 1,
15117            publication_word: 2,
15118            // Proposal publication and model-weight banks advance separately.
15119            neural_bank: 1,
15120            sealed_epoch: 1,
15121            proposal: 37,
15122            model_generation: 9,
15123            family_id: 3,
15124            stream_serial: 91,
15125            ..PublicationHeader::default()
15126        };
15127        let mut lease = PublicationLease {
15128            abi: 1,
15129            word: 2,
15130            epoch: 1,
15131            transition_kind: 1,
15132            ..PublicationLease::default()
15133        };
15134        let mut result = PreparedStepResult {
15135            abi: 1,
15136            word: 5,
15137            advanced: 1,
15138            header: PublicationHeader {
15139                abi: 1,
15140                base_word: 2,
15141                publication_word: 5,
15142                sealed_epoch: 2,
15143                proposal: 38,
15144                ..parent
15145            },
15146            attempt: AttemptReceipt {
15147                abi: 2,
15148                transition_kind: 1,
15149                instance: parent.instance,
15150                base_word: 2,
15151                next_word: 5,
15152                logical_digest: parent.logical_digest,
15153                ..AttemptReceipt::default()
15154            },
15155            ..PreparedStepResult::default()
15156        };
15157        assert_eq!(
15158            validate_prepared_completion(&lease, &parent, &result, parent.instance).unwrap(),
15159            SemanticTransitionKind::Proposal
15160        );
15161        assert_eq!(parent.rng_binding().unwrap().proposal, 37);
15162        lease.active = 1;
15163        assert!(validate_prepared_completion(&lease, &parent, &result, parent.instance).is_err());
15164        lease.active = 0;
15165        result.word = 8;
15166        assert!(validate_prepared_completion(&lease, &parent, &result, parent.instance).is_err());
15167        result.word = 5;
15168        lease.transition_kind = 0;
15169        assert!(validate_prepared_completion(&lease, &parent, &result, parent.instance).is_err());
15170    }
15171}
15172
15173struct UnreleasedPublicationOwners {
15174    _graph: SemanticHypergraph,
15175    _publication: Arc<PublicationStorage>,
15176    _training_views: Option<Arc<SemanticTrainingViewArena>>,
15177    _training_origins: Option<Arc<TrackedCudaSlice<SemanticTrainingViewOriginRecord>>>,
15178    _readers: BTreeMap<u64, PublishedReader>,
15179    _steps: BTreeMap<u64, StepContentStorage>,
15180    _initial_prefill_content: Option<RetainedInitialPrefillContent>,
15181    _prepared_resources: Vec<Arc<dyn Send + Sync>>,
15182    _prepared_segment: Option<PreparedSegmentState>,
15183    _text_binding: Option<Arc<TextBindingStorage>>,
15184    #[cfg(feature = "semantic-policy")]
15185    _policy: Option<PolicyStorage>,
15186    #[cfg(feature = "semantic-policy")]
15187    _pending_policy: Option<PendingPolicyStorage>,
15188    #[cfg(feature = "semantic-policy")]
15189    _policy_tapes: Vec<PolicyTape>,
15190    _events: Vec<cudarc::driver::CudaEvent>,
15191    _uploads: Vec<(usize, PublicationPayload)>,
15192    _stream: Arc<CudaStream>,
15193}
15194
15195thread_local! {
15196    // Driver/function/semantic owners are constructing-thread confined. A
15197    // violated explicit-release contract must retain these actual owners even
15198    // when that thread exits; no unsafe Send or foreign-thread destructor runs.
15199    static UNRELEASED_PUBLICATIONS: std::cell::RefCell<Vec<std::mem::ManuallyDrop<UnreleasedPublicationOwners>>> = const { std::cell::RefCell::new(Vec::new()) };
15200}
15201
15202impl Drop for SemanticTransitionSession {
15203    fn drop(&mut self) {
15204        // Captured work retires before either the semantic owner or its banks.
15205        drop(self.captured.take());
15206        if !self.readers.is_empty()
15207            || !self.steps.is_empty()
15208            || self
15209                .prepared_segment
15210                .as_ref()
15211                .is_some_and(|build| (build.capturing || build.submitted) && !build.completed)
15212        {
15213            if let Some(publication) = self.publication.take() {
15214                // SAFETY: graph is taken exactly once here and its normal
15215                // destructor is disabled by ManuallyDrop in Session storage.
15216                let graph = unsafe { std::mem::ManuallyDrop::take(&mut self.graph) };
15217                let owners = UnreleasedPublicationOwners {
15218                    _graph: graph,
15219                    _publication: publication,
15220                    _training_views: self.training_views.take(),
15221                    _training_origins: self.training_origins.take(),
15222                    _readers: std::mem::take(&mut self.readers),
15223                    _events: std::mem::take(&mut self.release_events),
15224                    _steps: std::mem::take(&mut self.steps),
15225                    _initial_prefill_content: self.retained_initial_prefill.take(),
15226                    _text_binding: self.text_binding.take(),
15227                    _prepared_resources: std::mem::take(&mut self.prepared_resources),
15228                    _prepared_segment: self.prepared_segment.take(),
15229                    #[cfg(feature = "semantic-policy")]
15230                    _policy: self.policy.take(),
15231                    #[cfg(feature = "semantic-policy")]
15232                    _pending_policy: self.pending_policy.take(),
15233                    #[cfg(feature = "semantic-policy")]
15234                    _policy_tapes: std::mem::take(&mut self.policy_tapes),
15235                    _uploads: std::mem::take(&mut self.publication_uploads),
15236                    _stream: Arc::clone(&self.stream),
15237                };
15238                eprintln!("semantic publication owners retained: Session dropped with unreleased readers or retained steps");
15239                let owners = std::mem::ManuallyDrop::new(owners);
15240                let _ = UNRELEASED_PUBLICATIONS
15241                    .try_with(|quarantine| quarantine.borrow_mut().push(owners));
15242                return;
15243            }
15244        }
15245        // SAFETY: no active reader can reach the graph, and the captured exec
15246        // retired above. This is the graph's unique normal destructor call.
15247        unsafe { std::mem::ManuallyDrop::drop(&mut self.graph) };
15248    }
15249}
15250
15251impl SemanticTransitionSession {
15252    /// Retain the actual allocation owner and serial stream for a private successor.
15253    /// Source and successor allocations remain charged to this same provider's
15254    /// resource stack; constructing a successor does not grant a fresh budget
15255    /// or consume another permanent stream-pool slot.
15256    pub fn checkpoint_allocation_domain(
15257        &self,
15258    ) -> Result<(Arc<CudaKernelProvider>, ResidentExecutionDomain), SemanticTransitionError> {
15259        self.ensure_quiescent()?;
15260        Ok((Arc::clone(&self.provider), self.domain.clone()))
15261    }
15262
15263    /// Decode and validate one complete native material before allocating a new
15264    /// CUDA owner, returning only the original immutable admission needed to
15265    /// construct that fresh owner. This is the same state codec consumed by
15266    /// `restore_state_material`, not an independently serialized graph.
15267    pub fn state_material_admission(
15268        bytes: &[u8],
15269    ) -> Result<SemanticAdmissionRecords, SemanticTransitionError> {
15270        PublicationMaterial::decode(bytes)?
15271            .graph
15272            .admission_records()
15273            .map_err(SemanticTransitionError::Semantic)
15274    }
15275
15276    /// Fixed compact checkpoint v2 extent, also reserved by the cold exporter.
15277    pub const CHECKPOINT_REFERENT_BYTES: usize = b"XLOG-CHECKPOINT-REFERENT\0".len()
15278        + 4
15279        + 32
15280        + 8
15281        + 104
15282        + 32
15283        + 8
15284        + 32
15285        + 32
15286        + 8
15287        + 3 * 32
15288        + 5 * 32
15289        + 1;
15290
15291    /// Decode the original sealed material once and project its selected publication.
15292    /// This performs no CUDA allocation and does not create a runnable owner.
15293    pub fn state_material_projection(
15294        bytes: &[u8],
15295    ) -> Result<SemanticCheckpointNativeProjection, SemanticTransitionError> {
15296        let material = PublicationMaterial::decode(bytes)?;
15297        let header = material.bank.header;
15298        Ok(SemanticCheckpointNativeProjection {
15299            publication: SemanticPublishedIdentity {
15300                instance: header.instance,
15301                word: header.publication_word,
15302                logical_digest: header.logical_digest,
15303                state_digest: header.state_digest,
15304            },
15305            semantic_root: header.semantic_digest,
15306            model_generation: header.model_generation,
15307        })
15308    }
15309
15310    /// Inspect original source and cache operands through the sole full-state
15311    /// decoder, without a CUDA owner or a new historical execution claim.
15312    pub fn state_material_input_projection(
15313        bytes: &[u8],
15314    ) -> Result<SemanticPublicationInputProjection, SemanticTransitionError> {
15315        let material = PublicationMaterial::decode(bytes)?;
15316        let header = material.bank.header;
15317        let range = |role| {
15318            material
15319                .ranges
15320                .iter()
15321                .find(|item| (item.range.role, item.range.index) == (role, 0))
15322                .ok_or(SemanticTransitionError::ObservationMismatch)
15323        };
15324        let prefix_material = range(1)?;
15325        let provenance_material = range(2)?;
15326        if prefix_material.range.logical_begin != 0
15327            || prefix_material.range.logical_end != header.prefix_extent
15328            || header
15329                .prefix_extent
15330                .checked_mul(size_of::<SemanticTextSlot>() as u64)
15331                != Some(prefix_material.bytes.len() as u64)
15332            || !provenance_material
15333                .bytes
15334                .len()
15335                .is_multiple_of(size_of::<TokenProvenance>())
15336            || header.prefix_extent > material.contract.prefix_capacity
15337            || header.ring_head >= 32
15338        {
15339            return Err(publication_input_error(
15340                "publication text material has inconsistent extents",
15341            ));
15342        }
15343        // SAFETY: fixed, padding-free, all-bit-valid integral ABI records. The
15344        // codec has checked each sealed record's bytes and the exact row sizes.
15345        let prefix = prefix_material
15346            .bytes
15347            .as_chunks::<{ size_of::<SemanticTextSlot>() }>()
15348            .0
15349            .iter()
15350            .map(|bytes| unsafe { bytes.as_ptr().cast::<SemanticTextSlot>().read_unaligned() })
15351            .collect::<Vec<_>>();
15352        let records = provenance_material
15353            .bytes
15354            .as_chunks::<{ size_of::<TokenProvenance>() }>()
15355            .0
15356            .iter()
15357            .map(|bytes| unsafe { bytes.as_ptr().cast::<TokenProvenance>().read_unaligned() })
15358            .collect::<Vec<_>>();
15359        for (position, slot) in prefix.iter().enumerate() {
15360            if slot.logical_position != position as u64
15361                || slot.kind != 1
15362                || slot.valid != 1
15363                || slot.committed != 1
15364                || slot.recomputed != 1
15365            {
15366                return Err(publication_input_error(
15367                    "publication prefix is not the exact committed ordered prefix",
15368                ));
15369            }
15370        }
15371        for slot in prefix.iter().chain(&material.bank.source) {
15372            if slot.kind != 1 {
15373                if slot.provenance != 0 || slot.provenance_record != 0 {
15374                    return Err(publication_input_error(
15375                        "unfilled source carries token provenance",
15376                    ));
15377                }
15378                continue;
15379            }
15380            let record = usize::try_from(slot.provenance_record)
15381                .ok()
15382                .and_then(|index| records.get(index))
15383                .ok_or(SemanticTransitionError::ObservationMismatch)?;
15384            if !matches!(slot.provenance, 1 | 2)
15385                || record.logical_position != slot.logical_position
15386                || record.token != slot.token
15387                || record.origin_logical_digest == Identity256::default()
15388                || record.authority_closure_digest == Identity256::default()
15389                || record.record_digest == Identity256::default()
15390                || (slot.provenance == 1)
15391                    != (record.action_receipt_digest == Identity256::default())
15392            {
15393                return Err(publication_input_error(
15394                    "publication token differs from its original source or generated origin",
15395                ));
15396            }
15397        }
15398        let prefix_identity = Identity256::from_bytes(
15399            range(3)?
15400                .bytes
15401                .as_slice()
15402                .try_into()
15403                .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
15404        );
15405        let cache = material
15406            .ranges
15407            .iter()
15408            .filter(|item| matches!(item.range.role, 4..=13))
15409            .map(|item| {
15410                item.cache_projection(
15411                    *material
15412                        .layouts
15413                        .get(&(item.range.role, item.range.index))
15414                        .ok_or(SemanticTransitionError::ObservationMismatch)?,
15415                )
15416            })
15417            .collect::<Result<Vec<_>, _>>()?;
15418        let token_provenance = records
15419            .into_iter()
15420            .map(|record| SemanticTokenProvenance {
15421                source_slot: record.source_slot,
15422                logical_position: record.logical_position,
15423                token: record.token,
15424                base_word: record.base_word,
15425                proposal: record.proposal,
15426                ordinal: record.ordinal,
15427                action_receipt_digest: record.action_receipt_digest,
15428                authority_generation: record.authority_generation,
15429                origin_logical_digest: record.origin_logical_digest,
15430                authority_closure_digest: record.authority_closure_digest,
15431                record_digest: record.record_digest,
15432            })
15433            .collect();
15434        Ok(SemanticPublicationInputProjection {
15435            publication: SemanticPublishedIdentity {
15436                instance: header.instance,
15437                word: header.publication_word,
15438                logical_digest: header.logical_digest,
15439                state_digest: header.state_digest,
15440            },
15441            semantic_root: header.semantic_digest,
15442            model_generation: header.model_generation,
15443            model_geometry_digest: header.model_geometry_digest,
15444            model_numerical_digest: header.model_numerical_digest,
15445            neural_generation: header.neural_generation,
15446            cache_generation: header.cache_generation,
15447            prefix_extent: header.prefix_extent,
15448            ring_head: header.ring_head,
15449            prefix_identity,
15450            prefix,
15451            source: material.bank.source,
15452            token_provenance,
15453            cache,
15454        })
15455    }
15456
15457    /// Allocate every native step owner before the first capture begins.
15458    /// Freeze requested modes and reserve the complete segment before creating
15459    /// per-step storage. Device admission alone selects terminal drain.
15460    pub fn prepare_segment_steps(
15461        &mut self,
15462        transitions: impl ExactSizeIterator<Item = SemanticTransitionKind> + Clone,
15463        cold_capacity: SemanticSegmentColdCapacity,
15464    ) -> Result<Vec<SemanticPreparedStep>, SemanticTransitionError> {
15465        self.ensure_rebindable()?;
15466        let external_floor = cold_capacity.external_floor()?;
15467        let transitions = transitions.collect::<Vec<_>>();
15468        if transitions.is_empty() || transitions.contains(&SemanticTransitionKind::Drain) {
15469            return Err(publication_input_error(
15470                "a prepared segment requires frozen proposal, recompute, or update steps",
15471            ));
15472        }
15473        let update_count = transitions
15474            .iter()
15475            .filter(|kind| **kind == SemanticTransitionKind::Update)
15476            .count();
15477        let training_view = if update_count == 0 {
15478            None
15479        } else {
15480            Some(Arc::clone(self.training_views.as_ref().ok_or_else(
15481                || {
15482                    publication_input_error(
15483                        "prepared updates require the native training-view arena",
15484                    )
15485                },
15486            )?))
15487        };
15488        if self.prepared_segment.is_some()
15489            || !self.readers.is_empty()
15490            || self.captured.is_some()
15491            || self.admitted_transition.is_some()
15492            || self.text_binding.is_some()
15493        {
15494            return Err(publication_input_error("segment construction requires an idle Session with no acquired reader or prior executable"));
15495        }
15496        let storage = Arc::clone(
15497            self.publication
15498                .as_ref()
15499                .ok_or(SemanticTransitionError::NotBound)?,
15500        );
15501        let transition_bound = transitions.len();
15502        let replay_bytes = PreparedReplayCustody::allocation_bytes(
15503            &storage,
15504            self.graph.transition_arena_view().len(),
15505        )?
15506        .checked_mul(transition_bound as u64)
15507        .ok_or(SemanticTransitionError::GenerationExhausted)?;
15508        let bound = u64::try_from(transition_bound)
15509            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
15510        let end = self
15511            .next_reader
15512            .checked_add(bound)
15513            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15514        let schema = SemanticFeedbackSchema::new(self.feedback_statement_bytes()?)?;
15515        let descriptor = self.descriptor();
15516        let input_plans = PreparedStepInputs::plan(&storage)?;
15517        let feedback_plan = FeedbackAllocationPlan::new(
15518            &schema,
15519            storage.contract_value.feedback_capacity,
15520            descriptor.arena[4],
15521        )?;
15522        let block_bytes = storage
15523            .physical_parameter_roster
15524            .as_ref()
15525            .map_or(Some(0usize), |roster| {
15526                roster.len().checked_mul(6 * size_of::<f64>())
15527            })
15528            .and_then(|bytes| bytes.checked_mul(2))
15529            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15530        #[cfg(not(feature = "semantic-policy"))]
15531        let policy_bytes = block_bytes;
15532        #[cfg(feature = "semantic-policy")]
15533        let policy_bytes = policy_buffer_bytes(&self.policy_layout()?, self.codebooks.input_cells)?
15534            .checked_add(self.codebooks.input_cells)
15535            .and_then(|n| n.checked_add(COMPONENT_COUNT * size_of::<SemanticTransitionReceipt>()))
15536            .and_then(|n| n.checked_add(size_of::<DeviceState>()))
15537            .and_then(|n| n.checked_mul(2))
15538            .and_then(|n| n.checked_add(block_bytes))
15539            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15540        let step_bytes = prepared_step_allocation_bytes(
15541            PreparedStepInputs::allocation_bytes(&input_plans)?,
15542            feedback_plan.bytes,
15543            policy_bytes,
15544        )?;
15545        let training_origin_bytes = if self.training_views.is_some() {
15546            transition_bound
15547                .checked_mul(size_of::<SemanticTrainingViewOriginRecord>())
15548                .ok_or(SemanticTransitionError::GenerationExhausted)?
15549        } else {
15550            0
15551        };
15552        let training_view_bytes = training_view.as_ref().map_or(Ok(0usize), |arena| {
15553            arena
15554                .selection_bytes()?
15555                .checked_mul(update_count)
15556                .ok_or(SemanticTransitionError::GenerationExhausted)
15557        })?;
15558        let model_forward_seal_count = storage.bank_templates[0]
15559            .iter()
15560            .filter(|range| matches!(range.role, 18..=25))
15561            .count();
15562        let model_update_bank_metadata_bytes = model_forward_seal_count
15563            .checked_mul(size_of::<ModelForwardSealInput>())
15564            .and_then(|bytes| {
15565                bytes.checked_add(
15566                    1 + 5 * size_of::<SemanticTrainingCanaryResultRecord>()
15567                        + size_of::<SemanticTrainingCanaryRefusalRecord>()
15568                        + 2 * size_of::<ModelForwardReceipt>(),
15569                )
15570            })
15571            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15572        let update_binding_bytes = update_count
15573            .checked_mul(2)
15574            .and_then(|count| count.checked_mul(storage.model_slots.len()))
15575            .and_then(|count| count.checked_mul(size_of::<ModelUpdateBinding>()))
15576            .and_then(|bytes| {
15577                update_count
15578                    .checked_mul(2)
15579                    .and_then(|count| count.checked_mul(model_update_bank_metadata_bytes))
15580                    .and_then(|metadata| bytes.checked_add(metadata))
15581            })
15582            .and_then(|bytes| {
15583                update_count
15584                    .checked_mul(transition_bound)
15585                    .and_then(|count| count.checked_mul(size_of::<ModelUpdateEvidenceSource>()))
15586                    .and_then(|evidence| bytes.checked_add(evidence))
15587            })
15588            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15589        let update_binding_bytes = u64::try_from(update_binding_bytes)
15590            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
15591        let base_bytes =
15592            prepared_segment_allocation_bytes(step_bytes, transition_bound, training_origin_bytes)?
15593                .checked_add(
15594                    u64::try_from(training_view_bytes)
15595                        .map_err(|_| SemanticTransitionError::GenerationExhausted)?,
15596                )
15597                .and_then(|bytes| bytes.checked_add(update_binding_bytes))
15598                .and_then(|bytes| bytes.checked_add(replay_bytes))
15599                .ok_or(SemanticTransitionError::GenerationExhausted)?;
15600        // Each model-bearing prepared branch binds the complete roster once. Its
15601        // ranges, contract snapshot, and roster are native cold allocations,
15602        // even though the live producer addresses arrive after this claim.
15603        let publication_allocation_bytes = storage
15604            .allocations
15605            .iter()
15606            .map(TrackedCudaSlice::len)
15607            .collect::<Vec<_>>();
15608        let model_content_bytes = storage
15609            .bank_templates
15610            .iter()
15611            .try_fold(0u64, |total, directory| {
15612                if !directory.iter().any(|range| range.role == 18) {
15613                    return Ok(total);
15614                }
15615                let ranges = directory
15616                    .iter()
15617                    .enumerate()
15618                    .filter_map(|(index, range)| matches!(range.role, 18..=20).then_some(index))
15619                    .collect::<Vec<_>>();
15620                let plan =
15621                    model_content_copy_plan(directory, &ranges, &publication_allocation_bytes)?;
15622                let bytes = plan
15623                    .directory_offsets
15624                    .len()
15625                    .checked_mul(size_of::<PublicationRange>())
15626                    .and_then(|bytes| bytes.checked_add(plan.contract_span.len()))
15627                    .and_then(|bytes| {
15628                        ranges
15629                            .len()
15630                            .checked_mul(2 * size_of::<u64>())
15631                            .and_then(|roster| bytes.checked_add(roster))
15632                    })
15633                    .and_then(|bytes| u64::try_from(bytes).ok())
15634                    .ok_or(SemanticTransitionError::GenerationExhausted)?;
15635                total
15636                    .checked_add(bytes)
15637                    .ok_or(SemanticTransitionError::GenerationExhausted)
15638            })?
15639            .checked_mul(bound)
15640            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15641        let late_native_bytes = cold_capacity.late_native_bytes(transition_bound)?;
15642        let bytes = base_bytes
15643            .checked_add(model_content_bytes)
15644            .and_then(|bytes| bytes.checked_add(late_native_bytes))
15645            .and_then(|bytes| bytes.checked_add(external_floor))
15646            .ok_or(SemanticTransitionError::GenerationExhausted)?;
15647        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
15648            .map_err(|error| runtime_error("segment preparation stream admission", error))?;
15649        let mut free_bytes = 0usize;
15650        let mut total_bytes = 0usize;
15651        // SAFETY: the stream admission binds this Session's CUDA context and
15652        // excludes managed capture while the driver writes both host scalars.
15653        unsafe { sys::cuMemGetInfo_v2(&mut free_bytes, &mut total_bytes) }
15654            .result()
15655            .map_err(|error| runtime_error("prepared segment physical memory snapshot", error))?;
15656        if u128::from(bytes) > free_bytes as u128 {
15657            return Err(runtime_error(
15658                "prepared segment physical memory admission",
15659                format!("declared cold claim {bytes} bytes exceeds {free_bytes} free CUDA bytes"),
15660            ));
15661        }
15662        // Claim the declared local and runtime budgets before any T-sized host
15663        // collection or native allocation. Every fixed bank consumes this claim.
15664        let mut reservation = self
15665            .provider
15666            .memory()
15667            .reserve_bytes(bytes)
15668            .map_err(|error| runtime_error("prepared segment reservation", error))?;
15669        let training_origins = if training_origin_bytes == 0 {
15670            None
15671        } else {
15672            let origins = reservation
15673                .alloc::<SemanticTrainingViewOriginRecord>(transition_bound)
15674                .map_err(|error| runtime_error("training origin roster allocation", error))?;
15675            upload_publication(
15676                &self.provider,
15677                &vec![SemanticTrainingViewOriginRecord::default(); transition_bound],
15678                &origins,
15679            )?;
15680            Some(Arc::new(origins))
15681        };
15682        let mut tokens = Vec::new();
15683        tokens
15684            .try_reserve_exact(transition_bound)
15685            .map_err(|error| runtime_error("prepared token reservation", error))?;
15686        tokens.extend((self.next_reader..end).map(|token| token + 1));
15687        let build = PreparedSegmentState::new(
15688            Arc::clone(&self.publication_issuer),
15689            tokens,
15690            transitions.iter().copied(),
15691            cold_capacity,
15692        )?;
15693        let handles = build.handles()?;
15694        let kernel = |name| {
15695            self.provider
15696                .device()
15697                .inner()
15698                .get_func("xlog_semantic_transition", name)
15699                .ok_or_else(|| runtime_error("kernel lookup", format!("{name} unavailable")))
15700        };
15701        let admit = kernel("semantic_publication_step_admit")?;
15702        let kind_gate = kernel("semantic_publication_step_kind_gate")?;
15703        let kind_bank_gate = kernel("semantic_publication_step_kind_bank_gate")?;
15704        let active_gate = kernel("semantic_publication_step_active_gate")?;
15705        let drain_prepare = kernel("semantic_publication_prepare_drain")?;
15706        let release = kernel("semantic_publication_step_release")?;
15707        let witness = kernel("semantic_tensor_content_witness")?;
15708        let content_guard = kernel("semantic_publication_content_guard")?;
15709        let result_kernel = kernel("semantic_publication_step_result")?;
15710        let model_update_admissibility_copy =
15711            kernel("semantic_publication_prepare_model_update_admissibility")?;
15712        let model_update_forward_receipt =
15713            kernel("semantic_publication_record_model_forward_receipts")?;
15714        let model_update_copy = kernel("semantic_publication_apply_model_update")?;
15715        self.prepared_segment = Some(build);
15716        self.next_reader = end;
15717        let result = (|| {
15718            for (ordinal, (handle, kind)) in handles.iter().zip(&transitions).enumerate() {
15719                let reader = reservation
15720                    .alloc(1)
15721                    .map_err(|error| runtime_error("prepared reader allocation", error))?;
15722                let result = reservation
15723                    .alloc(1)
15724                    .map_err(|error| runtime_error("prepared result allocation", error))?;
15725                let (update_evidence, update_evidence_owners) = if *kind
15726                    == SemanticTransitionKind::Update
15727                {
15728                    #[cfg(feature = "semantic-policy")]
15729                    let mut values = vec![ModelUpdateEvidenceSource::default(); transition_bound];
15730                    #[cfg(not(feature = "semantic-policy"))]
15731                    let values = vec![ModelUpdateEvidenceSource::default(); transition_bound];
15732                    #[cfg(feature = "semantic-policy")]
15733                    let mut owners = Vec::new();
15734                    #[cfg(not(feature = "semantic-policy"))]
15735                    let owners = Vec::new();
15736                    #[cfg(feature = "semantic-policy")]
15737                    for source_ordinal in 0..ordinal {
15738                        if transitions[source_ordinal] != SemanticTransitionKind::Proposal {
15739                            continue;
15740                        }
15741                        let source = &self.steps[&handles[source_ordinal].token];
15742                        let prepared = source
15743                            .prepared
15744                            .as_ref()
15745                            .ok_or(SemanticTransitionError::ObservationMismatch)?;
15746                        let inputs = source
15747                            .inputs
15748                            .as_ref()
15749                            .ok_or(SemanticTransitionError::ObservationMismatch)?;
15750                        let origin = prepared
15751                            .training_origin
15752                            .clone()
15753                            .ok_or(SemanticTransitionError::ObservationMismatch)?;
15754                        let owner = ModelUpdateEvidenceOwner {
15755                            lease: prepared.reader.view(),
15756                            parent_header: inputs.header.view(),
15757                            result: prepared.result.view(),
15758                            origin,
15759                            states: [
15760                                prepared.branches[0].state.view(),
15761                                prepared.branches[1].state.view(),
15762                            ],
15763                        };
15764                        values[source_ordinal] = ModelUpdateEvidenceSource {
15765                            lease: *owner.lease.device_ptr(),
15766                            parent_header: *owner.parent_header.device_ptr(),
15767                            result: *owner.result.device_ptr(),
15768                            origin: *owner.origin.device_ptr(),
15769                            states: [*owner.states[0].device_ptr(), *owner.states[1].device_ptr()],
15770                        };
15771                        owners.push(owner);
15772                    }
15773                    let evidence = reservation
15774                        .alloc::<ModelUpdateEvidenceSource>(transition_bound)
15775                        .map_err(|error| {
15776                            runtime_error("model update evidence allocation", error)
15777                        })?;
15778                    upload_publication(&self.provider, &values, &evidence)?;
15779                    (Some(Arc::new(evidence)), Some(Arc::new(owners)))
15780                } else {
15781                    (None, None)
15782                };
15783                let mut allocate_model_update = || {
15784                    if *kind != SemanticTransitionKind::Update {
15785                        return Ok(None);
15786                    }
15787                    let bindings = reservation
15788                        .alloc::<ModelUpdateBinding>(storage.model_slots.len())
15789                        .map_err(|error| runtime_error("model update binding allocation", error))?;
15790                    upload_publication(
15791                        &self.provider,
15792                        &vec![ModelUpdateBinding::default(); storage.model_slots.len()],
15793                        &bindings,
15794                    )?;
15795                    let forward_seals = reservation
15796                        .alloc::<ModelForwardSealInput>(model_forward_seal_count)
15797                        .map_err(|error| runtime_error("model forward seal allocation", error))?;
15798                    upload_publication(
15799                        &self.provider,
15800                        &vec![ModelForwardSealInput::default(); model_forward_seal_count],
15801                        &forward_seals,
15802                    )?;
15803                    let forward_receipts =
15804                        reservation
15805                            .alloc::<ModelForwardReceipt>(2)
15806                            .map_err(|error| {
15807                                runtime_error("model forward receipt allocation", error)
15808                            })?;
15809                    upload_publication(
15810                        &self.provider,
15811                        &[ModelForwardReceipt::default(); 2],
15812                        &forward_receipts,
15813                    )?;
15814                    let admissibility = reservation.alloc::<u8>(1).map_err(|error| {
15815                        runtime_error("model update admissibility allocation", error)
15816                    })?;
15817                    upload_publication(&self.provider, &[0u8], &admissibility)?;
15818                    let canary_results = reservation
15819                        .alloc::<SemanticTrainingCanaryResultRecord>(5)
15820                        .map_err(|error| {
15821                            runtime_error("model update canary result allocation", error)
15822                        })?;
15823                    upload_publication(
15824                        &self.provider,
15825                        &[SemanticTrainingCanaryResultRecord::default(); 5],
15826                        &canary_results,
15827                    )?;
15828                    let refusal = reservation
15829                        .alloc::<SemanticTrainingCanaryRefusalRecord>(1)
15830                        .map_err(|error| runtime_error("model update refusal allocation", error))?;
15831                    upload_publication(
15832                        &self.provider,
15833                        &[SemanticTrainingCanaryRefusalRecord::default()],
15834                        &refusal,
15835                    )?;
15836                    Ok(Some(PreparedModelUpdate {
15837                        bindings,
15838                        evidence: Arc::clone(
15839                            update_evidence
15840                                .as_ref()
15841                                .ok_or(SemanticTransitionError::ObservationMismatch)?,
15842                        ),
15843                        evidence_owners: Arc::clone(
15844                            update_evidence_owners
15845                                .as_ref()
15846                                .ok_or(SemanticTransitionError::ObservationMismatch)?,
15847                        ),
15848                        forward_seals,
15849                        forward_receipts,
15850                        admissibility,
15851                        canary_results,
15852                        refusal,
15853                        output: None,
15854                        forward_recorded: 0,
15855                        admissibility_copy: model_update_admissibility_copy.clone(),
15856                        forward_receipt: model_update_forward_receipt.clone(),
15857                        copy: model_update_copy.clone(),
15858                    }))
15859                };
15860                let model_updates: [Option<PreparedModelUpdate>; 2] =
15861                    [allocate_model_update()?, allocate_model_update()?];
15862                let inputs = Arc::new(PreparedStepInputs::allocate_reserved(
15863                    &self.provider,
15864                    Arc::clone(&storage),
15865                    reader.view(),
15866                    input_plans.clone(),
15867                    &mut reservation,
15868                )?);
15869                let feedback = FeedbackBuffers::allocate_reserved(
15870                    &self.provider,
15871                    schema.clone(),
15872                    feedback_plan,
15873                    &mut reservation,
15874                )?;
15875                let mut allocate_block_slot = || -> Result<_, SemanticTransitionError> {
15876                    storage
15877                        .physical_parameter_roster
15878                        .as_ref()
15879                        .map(|roster| {
15880                            let cells = roster
15881                                .len()
15882                                .checked_mul(6)
15883                                .ok_or(SemanticTransitionError::GenerationExhausted)?;
15884                            reservation
15885                                .alloc::<f64>(cells)
15886                                .map(Arc::new)
15887                                .map_err(|error| {
15888                                    runtime_error("prepared block bound allocation", error)
15889                                })
15890                        })
15891                        .transpose()
15892                };
15893                let [blocks_zero, blocks_one] = [allocate_block_slot()?, allocate_block_slot()?];
15894                #[cfg(feature = "semantic-policy")]
15895                let [branch_zero, branch_one] = [
15896                    self.prepare_step_policy_storage(&mut reservation)?,
15897                    self.prepare_step_policy_storage(&mut reservation)?,
15898                ];
15899                let [model_update_zero, model_update_one] = model_updates;
15900                #[cfg(feature = "semantic-policy")]
15901                let (policy_buffers_zero, support_zero, receipts_zero, state_zero) = branch_zero;
15902                #[cfg(feature = "semantic-policy")]
15903                let (policy_buffers_one, support_one, receipts_one, state_one) = branch_one;
15904                let branches = [
15905                    PreparedBranchStorage {
15906                        model_update: model_update_zero,
15907                        continuation: None,
15908                        numerical_block_snapshot: blocks_zero,
15909                        #[cfg(feature = "semantic-policy")]
15910                        policy_buffers: Some(policy_buffers_zero),
15911                        #[cfg(feature = "semantic-policy")]
15912                        policy: None,
15913                        #[cfg(feature = "semantic-policy")]
15914                        support: Some(support_zero),
15915                        #[cfg(feature = "semantic-policy")]
15916                        receipts: Some(receipts_zero),
15917                        #[cfg(feature = "semantic-policy")]
15918                        state: state_zero,
15919                        #[cfg(feature = "semantic-policy")]
15920                        policy_sources: Vec::new(),
15921                        #[cfg(feature = "semantic-policy")]
15922                        policy_witness: None,
15923                    },
15924                    PreparedBranchStorage {
15925                        model_update: model_update_one,
15926                        continuation: None,
15927                        numerical_block_snapshot: blocks_one,
15928                        #[cfg(feature = "semantic-policy")]
15929                        policy_buffers: Some(policy_buffers_one),
15930                        #[cfg(feature = "semantic-policy")]
15931                        policy: None,
15932                        #[cfg(feature = "semantic-policy")]
15933                        support: Some(support_one),
15934                        #[cfg(feature = "semantic-policy")]
15935                        receipts: Some(receipts_one),
15936                        #[cfg(feature = "semantic-policy")]
15937                        state: state_one,
15938                        #[cfg(feature = "semantic-policy")]
15939                        policy_sources: Vec::new(),
15940                        #[cfg(feature = "semantic-policy")]
15941                        policy_witness: None,
15942                    },
15943                ];
15944                let mut step = StepContentStorage::new();
15945                step.inputs = Some(Arc::clone(&inputs));
15946                step.feedback.push(feedback);
15947                step.prepared = Some(PreparedStepStorage {
15948                    reader,
15949                    // Every executed step's completed binding keeps its own
15950                    // acquired inputs after later transitions reuse either bank.
15951                    replay_custody: Some(PreparedReplayCustody::allocate(
15952                        &self.provider,
15953                        &storage,
15954                        &inputs,
15955                        self.graph.transition_arena_view().len(),
15956                        &mut reservation,
15957                        &self.learning_phases,
15958                    )?),
15959                    branches,
15960                    digests: None,
15961                    next_digest: 0,
15962                    model_work: None,
15963                    admit: admit.clone(),
15964                    kind_gate: kind_gate.clone(),
15965                    kind_bank_gate: kind_bank_gate.clone(),
15966                    active_gate: active_gate.clone(),
15967                    drain_prepare: drain_prepare.clone(),
15968                    release: release.clone(),
15969                    witness: witness.clone(),
15970                    content_guard: content_guard.clone(),
15971                    inputs_recorded: false,
15972                    model_content_recorded: 0,
15973                    transition_recorded: 0,
15974                    drain_recorded: false,
15975                    observed: false,
15976                    #[cfg(feature = "semantic-policy")]
15977                    observed_outcome: None,
15978                    #[cfg(feature = "semantic-policy")]
15979                    observed_parent: None,
15980                    #[cfg(feature = "semantic-policy")]
15981                    observed_result: None,
15982                    result,
15983                    training_origin: training_origins
15984                        .as_ref()
15985                        .and_then(|origins| origins.view().try_slice(ordinal..ordinal + 1)),
15986                    training_view: if *kind == SemanticTransitionKind::Update {
15987                        Some(
15988                            training_view
15989                                .as_ref()
15990                                .expect("validated update training-view owner")
15991                                .allocate_selection_reserved(
15992                                    &mut reservation,
15993                                    training_origins.clone(),
15994                                )?,
15995                        )
15996                    } else {
15997                        None
15998                    },
15999                    #[cfg(feature = "semantic-policy")]
16000                    group_vjp_members: [BTreeSet::new(), BTreeSet::new()],
16001                    #[cfg(feature = "semantic-policy")]
16002                    group_edit_members: [BTreeSet::new(), BTreeSet::new()],
16003                    #[cfg(feature = "semantic-policy")]
16004                    group_imported_vjp_members: [BTreeSet::new(), BTreeSet::new()],
16005                    #[cfg(feature = "semantic-policy")]
16006                    group_gradient_members: [BTreeSet::new(), BTreeSet::new()],
16007                    #[cfg(feature = "semantic-policy")]
16008                    group_critic_recorded: 0,
16009                    #[cfg(feature = "semantic-policy")]
16010                    group_update_published: false,
16011                    result_kernel: result_kernel.clone(),
16012                });
16013                self.steps.insert(handle.token, step);
16014                let prepared = self.steps[&handle.token]
16015                    .prepared
16016                    .as_ref()
16017                    .expect("installed fixed step");
16018                // Only immutable catalogue identity is initialized on the host;
16019                // actual invocation coordinates come from device admission.
16020                #[cfg(feature = "semantic-policy")]
16021                for branch in &prepared.branches {
16022                    upload_publication(
16023                        &self.provider,
16024                        &[DeviceState {
16025                            catalogue_generation: self.binding().generation,
16026                            catalogue_digest: Identity256::from_bytes(CATALOGUE_DIGEST),
16027                            binding_digest: self.binding().digest,
16028                            ..DeviceState::default()
16029                        }],
16030                        &branch.state,
16031                    )?;
16032                }
16033                upload_publication(
16034                    &self.provider,
16035                    &[PublicationLease::default()],
16036                    &prepared.reader,
16037                )?;
16038                upload_publication(
16039                    &self.provider,
16040                    &[PreparedStepResult::default()],
16041                    &prepared.result,
16042                )?;
16043                inputs.initialize(&self.provider)?;
16044            }
16045            if reservation.remaining_bytes() != bytes - base_bytes {
16046                return Err(SemanticTransitionError::ObservationMismatch);
16047            }
16048            self.training_origins = training_origins;
16049            Ok(handles)
16050        })();
16051        match result {
16052            Ok(handles) => {
16053                self.prepared_segment
16054                    .as_mut()
16055                    .expect("installed prepared segment")
16056                    .cold_reservation = Some(reservation);
16057                Ok(handles)
16058            }
16059            Err(error) => {
16060                self.poisoned = true;
16061                Err(error)
16062            }
16063        }
16064    }
16065
16066    fn checked_prepared_step(
16067        &self,
16068        step: &SemanticPreparedStep,
16069        recording: bool,
16070    ) -> Result<&StepContentStorage, SemanticTransitionError> {
16071        self.ensure_quiescent()?;
16072        let build = self
16073            .prepared_segment
16074            .as_ref()
16075            .ok_or_else(|| publication_input_error("Session has no prepared segment"))?;
16076        if recording {
16077            build.check(step, &self.publication_issuer, true)?;
16078        } else {
16079            build.check_retained(step, &self.publication_issuer)?;
16080        }
16081        self.steps
16082            .get(&step.token)
16083            .filter(|owner| owner.prepared.is_some() && owner.identity.is_none())
16084            .ok_or_else(|| {
16085                publication_input_error("prepared step has no original native storage owner")
16086            })
16087    }
16088
16089    /// Original nominal schedule mode, available only before construction ends.
16090    /// It does not predict the effective mode selected by device admission.
16091    pub fn prepared_transition_kind(
16092        &self,
16093        step: &SemanticPreparedStep,
16094    ) -> Result<SemanticTransitionKind, SemanticTransitionError> {
16095        self.checked_prepared_step(step, false)?;
16096        let build = self
16097            .prepared_segment
16098            .as_ref()
16099            .expect("checked prepared scope");
16100        build.check(step, &self.publication_issuer, false)?;
16101        build.requested_kind(step, &self.publication_issuer)
16102    }
16103
16104    /// Cold exports retain the original schedule after construction finishes.
16105    /// This authenticates known completion without reopening graph recording.
16106    #[cfg(feature = "semantic-policy")]
16107    fn completed_prepared_transition_kind(
16108        &self,
16109        step: &SemanticPreparedStep,
16110    ) -> Result<SemanticTransitionKind, SemanticTransitionError> {
16111        let owner = self.checked_prepared_step(step, false)?;
16112        let build = self
16113            .prepared_segment
16114            .as_ref()
16115            .expect("checked prepared scope");
16116        if !build.completed
16117            || !owner
16118                .prepared
16119                .as_ref()
16120                .expect("checked prepared owner")
16121                .observed
16122        {
16123            return Err(publication_input_error(
16124                "completed schedule observation requires this step's known execution",
16125            ));
16126        }
16127        build.requested_kind(step, &self.publication_issuer)
16128    }
16129
16130    fn check_prepared_cold(
16131        &self,
16132        step: &SemanticPreparedStep,
16133    ) -> Result<(), SemanticTransitionError> {
16134        self.checked_prepared_step(step, false)?;
16135        if self
16136            .prepared_segment
16137            .as_ref()
16138            .expect("checked build")
16139            .capturing
16140        {
16141            return Err(publication_input_error(
16142                "fixed resources must be prepared before capture begins",
16143            ));
16144        }
16145        Ok(())
16146    }
16147
16148    pub fn prepared_stream(
16149        &self,
16150        step: &SemanticPreparedStep,
16151    ) -> Result<Arc<CudaStream>, SemanticTransitionError> {
16152        self.checked_prepared_step(step, false)?;
16153        Ok(Arc::clone(&self.stream))
16154    }
16155
16156    /// Reserve private digest storage for original tensors born while recording.
16157    /// The producer derives this bound from its retained allocation capacity.
16158    pub fn reserve_tensor_content(
16159        &mut self,
16160        step: &SemanticPreparedStep,
16161        tensor_capacity: usize,
16162    ) -> Result<(), SemanticTransitionError> {
16163        self.check_prepared_cold(step)?;
16164        if tensor_capacity == 0 {
16165            return Err(publication_input_error(
16166                "content reservation requires a positive original tensor capacity",
16167            ));
16168        }
16169        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
16170            .map_err(|error| runtime_error("content reservation stream admission", error))?;
16171        if self.steps[&step.token]
16172            .prepared
16173            .as_ref()
16174            .expect("prepared owner")
16175            .digests
16176            .is_some()
16177        {
16178            return Err(publication_input_error(
16179                "original content capacity is reserved once per fixed step",
16180            ));
16181        }
16182        let build = self.prepared_segment.as_mut().expect("checked build");
16183        if tensor_capacity != build.cold_capacity.tensor_content_capacity {
16184            return Err(publication_input_error(
16185                "content capacity differs from the frozen segment claim",
16186            ));
16187        }
16188        let cells = build.cold_capacity.content_cells()?;
16189        let bytes = build.cold_capacity.content_bytes()?;
16190        let floor = build.cold_capacity.external_floor()?;
16191        let reservation = build
16192            .cold_reservation
16193            .as_mut()
16194            .ok_or(SemanticTransitionError::ObservationMismatch)?;
16195        if reservation
16196            .remaining_bytes()
16197            .checked_sub(bytes)
16198            .is_none_or(|remaining| remaining < floor)
16199        {
16200            return Err(SemanticTransitionError::ObservationMismatch);
16201        }
16202        let digest = Arc::new(
16203            reservation
16204                .alloc::<u64>(cells)
16205                .map_err(|error| runtime_error("original content allocation", error))?,
16206        );
16207        self.steps
16208            .get_mut(&step.token)
16209            .expect("checked fixed step")
16210            .prepared
16211            .as_mut()
16212            .expect("checked prepared owner")
16213            .digests = Some(digest);
16214        Ok(())
16215    }
16216
16217    /// Reserve and allocate the original producer's event roster before capture.
16218    /// This does not execute the model or upload any recording-time event data.
16219    pub fn reserve_model_work(
16220        &mut self,
16221        step: &SemanticPreparedStep,
16222        event_capacity: usize,
16223    ) -> Result<(), SemanticTransitionError> {
16224        self.check_prepared_cold(step)?;
16225        if self.steps[&step.token]
16226            .prepared
16227            .as_ref()
16228            .expect("prepared owner")
16229            .model_work
16230            .is_some()
16231        {
16232            return Err(publication_input_error(
16233                "original model work capacity is reserved once per step",
16234            ));
16235        }
16236        let build = self.prepared_segment.as_ref().expect("checked build");
16237        if event_capacity != build.cold_capacity.model_work_capacity {
16238            return Err(publication_input_error(
16239                "model work capacity differs from the frozen segment claim",
16240            ));
16241        }
16242        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
16243            .map_err(|error| runtime_error("model work reservation stream admission", error))?;
16244        let bytes = build.cold_capacity.model_work_bytes()?;
16245        let floor = build.cold_capacity.external_floor()?;
16246        let work = {
16247            let reservation = self
16248                .prepared_segment
16249                .as_mut()
16250                .expect("checked build")
16251                .cold_reservation
16252                .as_mut()
16253                .ok_or(SemanticTransitionError::ObservationMismatch)?;
16254            if reservation
16255                .remaining_bytes()
16256                .checked_sub(bytes)
16257                .is_none_or(|remaining| remaining < floor)
16258            {
16259                return Err(SemanticTransitionError::ObservationMismatch);
16260            }
16261            PreparedModelWork::allocate(&self.provider, reservation, event_capacity)?
16262        };
16263        // Initialize the complete exported scratch allocation cold. Each real
16264        // producer occurrence additionally records its own reset before use.
16265        work.reset_slots(&self.domain, &mut self.poisoned, 0, event_capacity)?;
16266        self.steps
16267            .get_mut(&step.token)
16268            .expect("checked original step")
16269            .prepared
16270            .as_mut()
16271            .expect("prepared owner")
16272            .model_work = Some(work);
16273        Ok(())
16274    }
16275
16276    /// Export the original work scratch as U64[capacity,3] before capture.
16277    /// Each row is [actual_units, sticky_overflow, producer_writes]. It is not a
16278    /// canonical receipt or a writable alias of the immutable work descriptors.
16279    pub fn model_work_buffer(
16280        &mut self,
16281        step: &SemanticPreparedStep,
16282        consumer_stream: u64,
16283    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16284        self.check_prepared_cold(step)?;
16285        if consumer_stream != self.stream.cu_stream() as u64 {
16286            return Err(publication_input_error(
16287                "model work producers must use the original native recording stream",
16288            ));
16289        }
16290        let work = self.steps[&step.token]
16291            .prepared
16292            .as_ref()
16293            .expect("prepared owner")
16294            .model_work
16295            .as_ref()
16296            .ok_or_else(|| publication_input_error("model work requires its cold reservation"))?;
16297        let capacity = i64::try_from(work.actual.len() / 3)
16298            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
16299        // SAFETY: the entire padding-free U64 scratch bank was initialized by
16300        // the cold reset; the exported view retains its actual allocation owner.
16301        let view = unsafe { work.actual.view().cast::<u8>() }
16302            .ok_or(SemanticTransitionError::ObservationMismatch)?;
16303        self.export_prepared_view(
16304            step,
16305            view,
16306            vec![capacity, 3],
16307            vec![3, 1],
16308            (1, 64),
16309            consumer_stream,
16310        )
16311    }
16312
16313    /// Reserve an occurrence in the current original recording and enqueue its
16314    /// reset immediately before the producer. A composite operator records one
16315    /// occurrence per actual unit category, rather than charging a dense mask.
16316    pub fn record_model_device_work(
16317        &mut self,
16318        step: &SemanticPreparedStep,
16319        kind: ModelWorkKind,
16320        upper_dimensions: &[u64],
16321    ) -> Result<usize, SemanticTransitionError> {
16322        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
16323        let result = (|| {
16324            let work = self
16325                .steps
16326                .get_mut(&step.token)
16327                .expect("checked original step")
16328                .prepared
16329                .as_mut()
16330                .expect("prepared owner")
16331                .model_work
16332                .as_mut()
16333                .ok_or_else(|| {
16334                    publication_input_error("model work requires its cold reservation")
16335                })?;
16336            let slot = work.next_slot().map_err(publication_input_error)?;
16337            if slot >= work.actual.len() / 3 {
16338                return Err(publication_input_error(
16339                    "model work exceeds its cold event capacity",
16340                ));
16341            }
16342            let actual = work
16343                .actual
16344                .device_ptr_value()
16345                .checked_add((slot * 3 * size_of::<u64>()) as u64)
16346                .ok_or(SemanticTransitionError::GenerationExhausted)?;
16347            let event = ModelWorkEvent::device_operation(kind, upper_dimensions, actual)
16348                .map_err(publication_input_error)?;
16349            let recorded = work.record_event(event).map_err(publication_input_error)?;
16350            debug_assert_eq!(recorded, slot);
16351            work.reset_slots(&self.domain, &mut self.poisoned, slot, 1)?;
16352            Ok(slot)
16353        })();
16354        if result.is_err() {
16355            self.poisoned = true;
16356        }
16357        result
16358    }
16359
16360    /// Append an actual operator occurrence during the original first recording.
16361    /// Geometry is expressed in the agreed unit (coordinates, summands or bytes),
16362    /// not FLOPs, elapsed time, or a caller-computed aggregate cost.
16363    pub fn record_model_work(
16364        &mut self,
16365        step: &SemanticPreparedStep,
16366        kind: ModelWorkKind,
16367        dimensions: &[u64],
16368    ) -> Result<(), SemanticTransitionError> {
16369        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
16370        let result = (|| {
16371            let event =
16372                ModelWorkEvent::operation(kind, dimensions).map_err(publication_input_error)?;
16373            let work = self
16374                .steps
16375                .get_mut(&step.token)
16376                .expect("checked original step")
16377                .prepared
16378                .as_mut()
16379                .expect("prepared owner")
16380                .model_work
16381                .as_mut()
16382                .ok_or_else(|| {
16383                    publication_input_error("model work requires its original cold reservation")
16384                })?;
16385            work.record_event(event)
16386                .map(|_| ())
16387                .map_err(publication_input_error)
16388        })();
16389        if result.is_err() {
16390            self.poisoned = true;
16391        }
16392        result
16393    }
16394
16395    /// Record at the original model-call site, within its active bank capture.
16396    /// A marker executes only in the selected graph, not once per cold capture.
16397    pub fn record_model_invocation(
16398        &mut self,
16399        step: &SemanticPreparedStep,
16400    ) -> Result<(), SemanticTransitionError> {
16401        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
16402        let result = self
16403            .steps
16404            .get_mut(&step.token)
16405            .expect("checked original step")
16406            .prepared
16407            .as_mut()
16408            .expect("prepared owner")
16409            .model_work
16410            .as_mut()
16411            .ok_or_else(|| {
16412                publication_input_error(
16413                    "model invocation requires its original cold work reservation",
16414                )
16415            })?
16416            .record_invocation(&self.domain, &mut self.poisoned);
16417        if result.is_err() {
16418            self.poisoned = true;
16419        }
16420        result
16421    }
16422
16423    /// Charge each original saved clone from its retained native tensor layout.
16424    /// A repeated storage still costs another copy when a new witness records
16425    /// another save occurrence. Reusing the same occurrence is rejected.
16426    pub fn record_saved_tensor_work(
16427        &mut self,
16428        step: &SemanticPreparedStep,
16429        witness: &SemanticTensorContentWitness,
16430    ) -> Result<(), SemanticTransitionError> {
16431        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
16432        let result = (|| {
16433            let owner = self
16434                .steps
16435                .get_mut(&step.token)
16436                .expect("checked original step");
16437            if !Arc::ptr_eq(&witness.issuer, &self.publication_issuer)
16438                || witness.reader_token != step.token
16439                || !Arc::ptr_eq(&witness._witness, &owner.content_witnesses)
16440            {
16441                return Err(publication_input_error(
16442                    "saved work requires this original step and tensor witness",
16443                ));
16444            }
16445            let content = owner.content.get(witness.index).ok_or_else(|| {
16446                publication_input_error("saved work has no retained original tensor occurrence")
16447            })?;
16448            let work = owner
16449                .prepared
16450                .as_mut()
16451                .expect("prepared owner")
16452                .model_work
16453                .as_mut()
16454                .ok_or_else(|| {
16455                    publication_input_error("saved work requires its original cold reservation")
16456                })?;
16457            for (index, tensor) in content.tensors.iter().enumerate() {
16458                let layout = &tensor.layout;
16459                let dimensions = layout
16460                    .dimensions
16461                    .get(..layout.rank as usize)
16462                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
16463                let event = ModelWorkEvent::saved(
16464                    witness.index as u64,
16465                    index as u64,
16466                    dimensions,
16467                    layout.element_bytes,
16468                )
16469                .map_err(publication_input_error)?;
16470                work.record_event(event).map_err(publication_input_error)?;
16471            }
16472            Ok(())
16473        })();
16474        if result.is_err() {
16475            self.poisoned = true;
16476        }
16477        result
16478    }
16479
16480    fn export_prepared_view(
16481        &mut self,
16482        step: &SemanticPreparedStep,
16483        view: DeviceMemoryView<u8>,
16484        shape: Vec<i64>,
16485        strides: Vec<i64>,
16486        dtype: (u8, u8),
16487        consumer_stream: u64,
16488    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16489        self.check_prepared_cold(step)?;
16490        let guard = Arc::clone(&self.steps[&step.token].aliases);
16491        self.steps
16492            .get_mut(&step.token)
16493            .expect("checked fixed step")
16494            .consumer_streams
16495            .insert(consumer_stream);
16496        self.export_owned_view(view, shape, strides, dtype, guard, consumer_stream)
16497    }
16498
16499    pub fn prepared_source(
16500        &mut self,
16501        step: &SemanticPreparedStep,
16502        consumer_stream: u64,
16503    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16504        self.check_prepared_cold(step)?;
16505        let (_, shape, strides) = PublicationBankField::Source.layout();
16506        let view = self.steps[&step.token]
16507            .inputs
16508            .as_ref()
16509            .expect("fixed input owner")
16510            .field_view(PublicationBankField::Source)?;
16511        self.export_prepared_view(step, view, shape, strides, (1, 64), consumer_stream)
16512    }
16513
16514    pub fn prepared_prefix(
16515        &mut self,
16516        step: &SemanticPreparedStep,
16517        bank: usize,
16518        consumer_stream: u64,
16519    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16520        self.prepared_tensor(
16521            step,
16522            SemanticStateRole::PrefixSource,
16523            0,
16524            bank,
16525            consumer_stream,
16526        )
16527    }
16528
16529    pub fn prepared_record(
16530        &mut self,
16531        step: &SemanticPreparedStep,
16532        role: SemanticStateRole,
16533        index: u64,
16534        consumer_stream: u64,
16535    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16536        self.check_prepared_cold(step)?;
16537        if is_tensor_role(role as u64) {
16538            return Err(publication_input_error(
16539                "tensor roles require their original model layout",
16540            ));
16541        }
16542        if role == SemanticStateRole::PrefixSource {
16543            return Err(publication_input_error(
16544                "prepared prefixes require the fixed typed capacity and original device extent",
16545            ));
16546        }
16547        let storage = self.publication.as_ref().expect("prepared publication");
16548        let key = (role as u64, index);
16549        let inputs = self.steps[&step.token]
16550            .inputs
16551            .as_ref()
16552            .expect("fixed inputs");
16553        let view = if let Some(view) = inputs.views[0].get(&key) {
16554            view.clone()
16555        } else {
16556            let original = storage.bank_templates[0]
16557                .iter()
16558                .find(|range| (range.role, range.index) == key)
16559                .ok_or_else(|| {
16560                    publication_input_error("record has no original fixed declaration")
16561                })?;
16562            let other = storage.bank_templates[1]
16563                .iter()
16564                .find(|range| (range.role, range.index) == key)
16565                .ok_or(SemanticTransitionError::ObservationMismatch)?;
16566            if publication_mutable_role(role as u64)
16567                || original.storage_slot != other.storage_slot
16568                || original.offset_bytes != other.offset_bytes
16569                || original.length_bytes != other.length_bytes
16570            {
16571                return Err(publication_input_error(
16572                    "bank-varying records require a private prepared input producer",
16573                ));
16574            }
16575            let begin = original.offset_bytes as usize;
16576            let end = begin
16577                .checked_add(original.length_bytes as usize)
16578                .ok_or(SemanticTransitionError::ObservationMismatch)?;
16579            storage.allocations[original.storage_slot as usize]
16580                .view()
16581                .slice(begin..end)
16582        };
16583        let bytes =
16584            i64::try_from(view.len()).map_err(|_| SemanticTransitionError::ObservationMismatch)?;
16585        self.export_prepared_view(step, view, vec![bytes], vec![1], (1, 8), consumer_stream)
16586    }
16587
16588    pub fn prepared_range_keys(
16589        &self,
16590        step: &SemanticPreparedStep,
16591    ) -> Result<Vec<(SemanticStateRole, u64)>, SemanticTransitionError> {
16592        self.checked_prepared_step(step, false)?;
16593        self.publication
16594            .as_ref()
16595            .expect("prepared publication")
16596            .bank_templates[0]
16597            .iter()
16598            .map(|range| {
16599                SemanticStateRole::from_code(range.role)
16600                    .map(|role| (role, range.index))
16601                    .ok_or(SemanticTransitionError::ObservationMismatch)
16602            })
16603            .collect()
16604    }
16605
16606    /// Export the fixed original capacity; live extents remain device inputs.
16607    pub fn prepared_tensor(
16608        &mut self,
16609        step: &SemanticPreparedStep,
16610        role: SemanticStateRole,
16611        index: u64,
16612        bank: usize,
16613        consumer_stream: u64,
16614    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16615        let (view, layout) = self.prepared_tensor_view(step, role, index, bank)?;
16616        let shape = layout.dimensions[..layout.rank as usize]
16617            .iter()
16618            .map(|&value| {
16619                i64::try_from(value).map_err(|_| SemanticTransitionError::ObservationMismatch)
16620            })
16621            .collect::<Result<Vec<_>, _>>()?;
16622        let strides = layout.strides_bytes[..layout.rank as usize]
16623            .iter()
16624            .map(|&value| {
16625                i64::try_from(value / layout.element_bytes)
16626                    .map_err(|_| SemanticTransitionError::ObservationMismatch)
16627            })
16628            .collect::<Result<Vec<_>, _>>()?;
16629        let dtype = match layout.scalar_type {
16630            1 => (1, 8),
16631            2 => (1, 32),
16632            3 => (1, 64),
16633            4 => (2, 16),
16634            5 => (4, 16),
16635            6 => (2, 32),
16636            7 => (0, 64),
16637            8 => (6, 8),
16638            9 => (2, 64),
16639            _ => return Err(SemanticTransitionError::ObservationMismatch),
16640        };
16641        self.export_prepared_view(step, view, shape, strides, dtype, consumer_stream)
16642    }
16643
16644    /// Export one fixed device port produced by this Update step's native
16645    /// selection. Its status word remains device-resident and gates consumers.
16646    pub fn prepared_training_view_port(
16647        &mut self,
16648        step: &SemanticPreparedStep,
16649        port: SemanticTrainingViewPort,
16650        consumer_stream: u64,
16651    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16652        self.check_prepared_cold(step)?;
16653        if self.prepared_transition_kind(step)? != SemanticTransitionKind::Update {
16654            return Err(publication_input_error(
16655                "native selected training views belong only to prepared updates",
16656            ));
16657        }
16658        let (view, shape, strides, dtype) = self.steps[&step.token]
16659            .prepared
16660            .as_ref()
16661            .expect("prepared owner")
16662            .training_view
16663            .as_ref()
16664            .ok_or(SemanticTransitionError::NotBound)?
16665            .port(port)?;
16666        self.export_prepared_view(step, view, shape, strides, dtype, consumer_stream)
16667    }
16668
16669    /// Actual allocation origin and complete backing bytes of the fixed view
16670    /// exported by `prepared_tensor`. The byte export retains the original step
16671    /// grant and stream ordering. Live extents and version counters are separate.
16672    pub fn prepared_tensor_allocation(
16673        &mut self,
16674        step: &SemanticPreparedStep,
16675        role: SemanticStateRole,
16676        index: u64,
16677        bank: usize,
16678        consumer_stream: u64,
16679    ) -> Result<(DeviceAllocationProvenance, DlpackManagedTensor), SemanticTransitionError> {
16680        dlpack_consumer_stream(consumer_stream)?;
16681        let (view, _) = self.prepared_tensor_view(step, role, index, bank)?;
16682        let provenance = view.allocation_provenance().ok_or_else(|| {
16683            publication_input_error("prepared tensor has no complete native allocation owner")
16684        })?;
16685        let allocation = view
16686            .allocation_view()
16687            .ok_or(SemanticTransitionError::ObservationMismatch)?;
16688        let bytes = i64::try_from(allocation.len())
16689            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
16690        let tensor = self.export_prepared_view(
16691            step,
16692            allocation,
16693            vec![bytes],
16694            vec![1],
16695            (1, 8),
16696            consumer_stream,
16697        )?;
16698        Ok((provenance, tensor))
16699    }
16700
16701    fn prepared_tensor_view(
16702        &mut self,
16703        step: &SemanticPreparedStep,
16704        role: SemanticStateRole,
16705        index: u64,
16706        bank: usize,
16707    ) -> Result<(DeviceMemoryView<u8>, SemanticTensorLayout), SemanticTransitionError> {
16708        self.check_prepared_cold(step)?;
16709        if bank > 1 {
16710            return Err(publication_input_error(
16711                "prepared tensor bank must be zero or one",
16712            ));
16713        }
16714        let retained = self
16715            .prepared_segment
16716            .as_ref()
16717            .expect("checked prepared scope")
16718            .finished;
16719        if retained {
16720            let actual_bank = self.prepared_completed_parent_bank(step.token)?;
16721            if actual_bank != bank {
16722                return Err(publication_input_error(
16723                    "completed tensor requires the original executed branch bank",
16724                ));
16725            }
16726        }
16727        let inputs = self.steps[&step.token]
16728            .inputs
16729            .as_ref()
16730            .expect("fixed input owner");
16731        let plan = inputs
16732            .plans
16733            .iter()
16734            .find(|plan| (plan.role, plan.index) == (role as u64, index))
16735            .ok_or_else(|| {
16736                publication_input_error("prepared tensor has no fixed original input owner")
16737            })?;
16738        let custody = self.steps[&step.token]
16739            .prepared
16740            .as_ref()
16741            .expect("checked prepared owner")
16742            .replay_custody
16743            .as_ref();
16744        let view = if let Some(custody) =
16745            custody.filter(|_| retained && matches!(role as u64, 1 | 4 | 5 | 18..=25))
16746        {
16747            custody.input_view(role as u64, index)?.0
16748        } else {
16749            inputs.views[bank][&(role as u64, index)].clone()
16750        };
16751        Ok((view, plan.layout))
16752    }
16753
16754    pub fn prepared_terminal(
16755        &mut self,
16756        step: &SemanticPreparedStep,
16757        consumer_stream: u64,
16758    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16759        self.prepared_bank_field(step, PublicationBankField::Terminal, consumer_stream)
16760    }
16761
16762    pub fn prepared_prefix_extent(
16763        &mut self,
16764        step: &SemanticPreparedStep,
16765        consumer_stream: u64,
16766    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16767        self.prepared_bank_field(step, PublicationBankField::PrefixExtent, consumer_stream)
16768    }
16769
16770    pub fn prepared_ring_head(
16771        &mut self,
16772        step: &SemanticPreparedStep,
16773        consumer_stream: u64,
16774    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16775        self.prepared_bank_field(step, PublicationBankField::RingHead, consumer_stream)
16776    }
16777
16778    fn prepared_bank_field(
16779        &mut self,
16780        step: &SemanticPreparedStep,
16781        field: PublicationBankField,
16782        consumer_stream: u64,
16783    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
16784        self.check_prepared_cold(step)?;
16785        let inputs = self.steps[&step.token]
16786            .inputs
16787            .as_ref()
16788            .expect("prepared input owner");
16789        let (_, shape, strides) = field.layout();
16790        self.export_prepared_view(
16791            step,
16792            inputs.field_view(field)?,
16793            shape,
16794            strides,
16795            (1, 64),
16796            consumer_stream,
16797        )
16798    }
16799
16800    /// Immutable admitted model geometry; no future publication values occur.
16801    pub fn prepared_model_geometry(
16802        &self,
16803        step: &SemanticPreparedStep,
16804    ) -> Result<(Identity256, Identity256, u64, u64, u64, u64), SemanticTransitionError> {
16805        self.checked_prepared_step(step, false)?;
16806        let contract = self
16807            .publication
16808            .as_ref()
16809            .expect("prepared publication")
16810            .contract_value;
16811        Ok((
16812            contract.topology_identity,
16813            contract.table_identity,
16814            contract.model_generation,
16815            contract.prefix_capacity,
16816            contract.feedback_capacity,
16817            contract.max_position,
16818        ))
16819    }
16820
16821    /// Authenticate the retained model inputs of an actually completed step.
16822    /// This cold observation joins every original consumer before checking the
16823    /// private input seals and reading that step's actual acquisition/result.
16824    /// It never acquires a current bank or constructs a historical live reader.
16825    ///
16826    /// Returns (predecessor, successor-or-None, model generation, model geometry
16827    /// digest, model numerical digest). A numerical refusal has no successor;
16828    /// skipped steps and unknown completion have no observable input binding.
16829    /// Model record 44 and complete model backing allocations are the existing
16830    /// prepared record/tensor exports, retained until original step retirement.
16831    /// Recheck this binding after serializing those read-only exports. This is
16832    /// not complete semantic replay material or authority for another forward.
16833    pub fn prepared_model_binding(
16834        &mut self,
16835        step: &SemanticPreparedStep,
16836        consumer_streams: &[u64],
16837    ) -> Result<
16838        (
16839            SemanticPublishedIdentity,
16840            Option<SemanticPublishedIdentity>,
16841            u64,
16842            Identity256,
16843            Identity256,
16844        ),
16845        SemanticTransitionError,
16846    > {
16847        let owner = self.checked_prepared_step(step, false)?;
16848        let prepared = owner.prepared.as_ref().expect("checked prepared owner");
16849        if !self
16850            .prepared_segment
16851            .as_ref()
16852            .expect("checked prepared scope")
16853            .completed
16854            || !prepared.observed
16855        {
16856            return Err(publication_input_error(
16857                "model input observation requires this step's known completed execution",
16858            ));
16859        }
16860        let inputs = Arc::clone(
16861            owner
16862                .inputs
16863                .as_ref()
16864                .ok_or(SemanticTransitionError::ObservationMismatch)?,
16865        );
16866        let reader = prepared.reader.view();
16867        let result = prepared.result.view();
16868        let _ordinary =
16869            crate::cuda_graph::reserve_uncaptured_stream(&self.stream).map_err(|error| {
16870                runtime_error("completed model observation stream admission", error)
16871            })?;
16872        self.complete_step_consumers_by_token(step.token, consumer_streams)?;
16873        let custody = self.steps[&step.token]
16874            .prepared
16875            .as_ref()
16876            .expect("checked prepared owner")
16877            .replay_custody
16878            .as_ref();
16879        inputs.verify_completed(&self.domain, &mut self.poisoned, custody)?;
16880        let parent = self.publication_read(inputs.header.view())?[0];
16881        let reader = self.publication_read(reader)?[0];
16882        let result = self.publication_read(result)?[0];
16883        if validate_prepared_completion(&reader, &parent, &result, inputs.storage.instance).is_err()
16884            || (result.advanced == 0 && result.header != parent)
16885        {
16886            self.poisoned = true;
16887            return Err(SemanticTransitionError::ObservationMismatch);
16888        }
16889        let identity = |header: PublicationHeader| SemanticPublishedIdentity {
16890            instance: header.instance,
16891            word: header.publication_word,
16892            logical_digest: header.logical_digest,
16893            state_digest: header.state_digest,
16894        };
16895        Ok((
16896            identity(parent),
16897            (result.advanced == 1).then(|| identity(result.header)),
16898            parent.model_generation,
16899            parent.model_geometry_digest,
16900            parent.model_numerical_digest,
16901        ))
16902    }
16903
16904    /// Joined execution quantities for this original step, including known
16905    /// skips and refusals. These exclude cold preparation and are not a whole
16906    /// resource-unit or physical memory certificate. Overflow is not a value.
16907    #[cfg(feature = "semantic-policy")]
16908    pub fn prepared_execution_measurements(
16909        &mut self,
16910        step: &SemanticPreparedStep,
16911    ) -> Result<SemanticCompletedExecutionObservation, SemanticTransitionError> {
16912        let original = self.checked_prepared_step(step, false)?;
16913        if !self
16914            .prepared_segment
16915            .as_ref()
16916            .expect("checked prepared scope")
16917            .completed
16918        {
16919            return Err(publication_input_error(
16920                "execution measurements require the original segment's known completion",
16921            ));
16922        }
16923        let prepared = original.prepared.as_ref().expect("checked original step");
16924        let requested_transition = self
16925            .prepared_segment
16926            .as_ref()
16927            .expect("checked prepared scope")
16928            .requested_kind(step, &self.publication_issuer)?;
16929        let original_outcome = prepared
16930            .observed_outcome
16931            .as_ref()
16932            .ok_or(SemanticTransitionError::ObservationMismatch)?
16933            .clone();
16934        let original_parent = prepared.observed_parent;
16935        let original_result = prepared.observed_result;
16936        let reader = prepared.reader.view();
16937        let result = prepared.result.view();
16938        let mut streams = original.consumer_streams.clone();
16939        if let Some(reader) = self.readers.get(&step.token) {
16940            streams.extend(reader.consumer_streams.iter().copied());
16941        }
16942        let observation = (|| {
16943            self.complete_step_consumers_by_token(
16944                step.token,
16945                &streams.into_iter().collect::<Vec<_>>(),
16946            )?;
16947            let lease = self.publication_read(reader)?[0];
16948            let result = self.publication_read(result)?[0];
16949            let prepared = self.steps[&step.token]
16950                .prepared
16951                .as_ref()
16952                .expect("retained original step");
16953            let work = prepared
16954                .model_work
16955                .as_ref()
16956                .ok_or(SemanticTransitionError::ObservationMismatch)?;
16957            let actual = work.actual.view();
16958            let actual = self.publication_read(actual)?;
16959            if result.abi == 0 {
16960                if lease.active != 0
16961                    || lease.abi != 0
16962                    || lease.transition_kind != 0
16963                    || !matches!(lease.status, 1..=5 | 7)
16964                    || original_parent.is_some()
16965                    || original_result.is_some()
16966                    || !matches!(&original_outcome,
16967                        SemanticPreparedStepOutcome::Skipped { step: issued, status }
16968                            if issued.same_handle(step) && *status == lease.status)
16969                {
16970                    return Err(SemanticTransitionError::ObservationMismatch);
16971                }
16972                self.steps[&step.token]
16973                    .prepared
16974                    .as_ref()
16975                    .expect("retained original step")
16976                    .model_work
16977                    .as_ref()
16978                    .expect("original work checked above")
16979                    .completed_model_calls(&actual, false)?;
16980                return Ok(SemanticCompletedExecutionObservation {
16981                    original: step.clone(),
16982                    requested_transition,
16983                    outcome: original_outcome,
16984                    predecessor: None,
16985                    successor: None,
16986                    model_binding: None,
16987                    quantities: [0; 4],
16988                });
16989            }
16990            let parent = self.steps[&step.token]
16991                .inputs
16992                .as_ref()
16993                .ok_or(SemanticTransitionError::ObservationMismatch)?
16994                .header
16995                .view();
16996            let parent = self.publication_read(parent)?[0];
16997            let transition =
16998                validate_prepared_completion(&lease, &parent, &result, parent.instance)?;
16999            if original_parent != Some(parent)
17000                || original_result != Some(result)
17001                || !matches!(&original_outcome,
17002                    SemanticPreparedStepOutcome::Completed {
17003                        step: issued, bank, transition: issued_transition, ..
17004                    } if issued.same_handle(step)
17005                        && u64::from(*bank) == lease.bank
17006                        && *issued_transition == transition)
17007            {
17008                return Err(SemanticTransitionError::ObservationMismatch);
17009            }
17010            let prepared = self.steps[&step.token]
17011                .prepared
17012                .as_ref()
17013                .expect("retained original step");
17014            if !prepared.observed {
17015                return Err(SemanticTransitionError::ObservationMismatch);
17016            }
17017            let state = prepared
17018                .branches
17019                .get(
17020                    usize::try_from(lease.bank)
17021                        .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
17022                )
17023                .ok_or(SemanticTransitionError::ObservationMismatch)?
17024                .state
17025                .view();
17026            let state = self.publication_read(state)?[0];
17027            let work = state.execution_work;
17028            if work.overflow != 0
17029                || work.model_once.checked_add(work.native_attempt) != Some(work.raw)
17030                || (transition != SemanticTransitionKind::Drain
17031                    && !work.validate_model(
17032                        &self.steps[&step.token]
17033                            .prepared
17034                            .as_ref()
17035                            .expect("retained original step")
17036                            .model_work
17037                            .as_ref()
17038                            .expect("original work checked above")
17039                            .recording,
17040                        false,
17041                    ))
17042            {
17043                return Err(SemanticTransitionError::ObservationMismatch);
17044            }
17045            let calls = self.steps[&step.token]
17046                .prepared
17047                .as_ref()
17048                .expect("retained original step")
17049                .model_work
17050                .as_ref()
17051                .expect("original work checked above")
17052                .completed_model_calls(&actual, transition != SemanticTransitionKind::Drain)?;
17053            let identity = |header: PublicationHeader| SemanticPublishedIdentity {
17054                instance: header.instance,
17055                word: header.publication_word,
17056                logical_digest: header.logical_digest,
17057                state_digest: header.state_digest,
17058            };
17059            Ok(SemanticCompletedExecutionObservation {
17060                original: step.clone(),
17061                requested_transition,
17062                outcome: original_outcome,
17063                predecessor: Some(identity(parent)),
17064                successor: (result.advanced == 1).then(|| identity(result.header)),
17065                model_binding: Some((
17066                    parent.model_generation,
17067                    parent.model_geometry_digest,
17068                    parent.model_numerical_digest,
17069                )),
17070                quantities: [work.raw, work.model_once, work.native_attempt, calls],
17071            })
17072        })();
17073        if observation.is_err() {
17074            self.poisoned = true;
17075        }
17076        observation
17077    }
17078
17079    /// Read the original five Update checks and original forward receipts after
17080    /// terminal completion. All returned data is host-owned; no reader is acquired
17081    /// and no forward, metric, or candidate generation is reconstructed.
17082    #[cfg(feature = "semantic-policy")]
17083    pub fn prepared_update_measurements(
17084        &mut self,
17085        step: &SemanticPreparedStep,
17086    ) -> Result<Option<SemanticUpdateMeasurements>, SemanticTransitionError> {
17087        let original = self.checked_prepared_step(step, false)?;
17088        let mut streams = original.consumer_streams.clone();
17089        if let Some(reader) = self.readers.get(&step.token) {
17090            streams.extend(reader.consumer_streams.iter().copied());
17091        }
17092        let streams = streams.into_iter().collect::<Vec<_>>();
17093        let binding = self.prepared_model_binding(step, &streams)?;
17094        let observation = (|| {
17095            let prepared = self.steps[&step.token]
17096                .prepared
17097                .as_ref()
17098                .expect("checked owner");
17099            let lease_view = prepared.reader.view();
17100            let result_view = prepared.result.view();
17101            let parent_view = self.steps[&step.token]
17102                .inputs
17103                .as_ref()
17104                .ok_or(SemanticTransitionError::ObservationMismatch)?
17105                .header
17106                .view();
17107            let parent = self.publication_read(parent_view)?[0];
17108            let lease = self.publication_read(lease_view)?[0];
17109            let result = self.publication_read(result_view)?[0];
17110            let transition =
17111                validate_prepared_completion(&lease, &parent, &result, parent.instance)?;
17112            if transition != SemanticTransitionKind::Update {
17113                return Ok(None);
17114            }
17115            let bank = usize::try_from(lease.bank)
17116                .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
17117            let (
17118                selection,
17119                canaries,
17120                rows,
17121                protected,
17122                results,
17123                receipts,
17124                refusal,
17125                state,
17126                logits,
17127                work_count,
17128            ) = {
17129                let prepared = self.steps[&step.token]
17130                    .prepared
17131                    .as_ref()
17132                    .expect("checked owner");
17133                let view = prepared
17134                    .training_view
17135                    .as_ref()
17136                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17137                let branch = prepared
17138                    .branches
17139                    .get(bank)
17140                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17141                let update = branch
17142                    .model_update
17143                    .as_ref()
17144                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17145                let output = update
17146                    .output
17147                    .as_ref()
17148                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17149                let work = prepared
17150                    .model_work
17151                    .as_ref()
17152                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17153                (
17154                    view.selection(),
17155                    view.canaries(),
17156                    view.roster_rows(),
17157                    view.protected_members(),
17158                    update.canary_results.view(),
17159                    update.forward_receipts.view(),
17160                    update.refusal.view(),
17161                    branch.state.view(),
17162                    [
17163                        (output.baseline_logits.data, output.baseline_logits.layout),
17164                        (output.candidate_logits.data, output.candidate_logits.layout),
17165                    ],
17166                    work.recording.events().len() as u64,
17167                )
17168            };
17169            let selection = self.publication_read(selection)?[0];
17170            let canaries = self.publication_read(canaries)?;
17171            let rows = self.publication_read(rows)?;
17172            let protected = self.publication_read(protected)?;
17173            let results = self.publication_read(results)?;
17174            let receipts = self.publication_read(receipts)?;
17175            let refusal = decode_canary_refusal(self.publication_read(refusal)?[0], &results)?;
17176            let state = self.publication_read(state)?[0];
17177            if canaries.len() != 5
17178                || results.len() != 5
17179                || receipts.len() != 2
17180                || selection.status > 3
17181                || selection.row_count != rows.len() as u64
17182            {
17183                return Err(SemanticTransitionError::ObservationMismatch);
17184            }
17185            let mut observations = Vec::with_capacity(5);
17186            for (index, (frozen, measured)) in canaries.into_iter().zip(&results).enumerate() {
17187                let row = rows
17188                    .get(
17189                        usize::try_from(frozen.row_ordinal)
17190                            .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
17191                    )
17192                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17193                let lower = f64::from_bits(frozen.lower_bound_bits);
17194                let upper = f64::from_bits(frozen.upper_bound_bits);
17195                let value = f64::from_bits(measured.measurement_bits);
17196                let complete = measured.availability == 2;
17197                let reason_valid = match measured.reason {
17198                    0 => {
17199                        complete
17200                            && value.is_finite()
17201                            && value >= lower
17202                            && value <= upper
17203                            && measured.memory_used <= frozen.memory_limit
17204                            && measured.work_used <= frozen.work_limit
17205                    }
17206                    1 => measured.availability == 1 || (complete && !value.is_finite()),
17207                    2 => complete && value.is_finite() && (value < lower || value > upper),
17208                    3 => complete && measured.memory_used > frozen.memory_limit,
17209                    4 => measured.work_used > frozen.work_limit,
17210                    5 => !complete,
17211                    6 => complete && frozen.kind == 2,
17212                    7 => {
17213                        (measured.availability == 1 && matches!(frozen.kind, 1 | 4))
17214                            || (complete && frozen.kind == 4)
17215                    }
17216                    8 => true,
17217                    9 => measured.availability == 0,
17218                    _ => false,
17219                };
17220                if frozen.evaluator_abi != 3
17221                    || frozen.kind != index as u64 + 1
17222                    || frozen.task_identity
17223                        != identity_words(
17224                            *self
17225                                .publication
17226                                .as_ref()
17227                                .expect("checked publication")
17228                                .contract_value
17229                                .task_identity
17230                                .as_bytes(),
17231                        )
17232                    || row.ordinal != frozen.row_ordinal
17233                    || row.identity != frozen.row_identity
17234                    || row.content_identity != frozen.row_content_identity
17235                    || measured.abi != 1
17236                    || measured.kind != frozen.kind
17237                    || measured.row_ordinal != frozen.row_ordinal
17238                    || measured.identity != frozen.identity
17239                    || measured.availability > 2
17240                    || !reason_valid
17241                    || !lower.is_finite()
17242                    || !upper.is_finite()
17243                    || lower > upper
17244                    || frozen.memory_limit == 0
17245                    || frozen.work_limit == 0
17246                    || measured.memory_used != results[0].memory_used
17247                    || measured.work_used != results[0].work_used
17248                {
17249                    return Err(SemanticTransitionError::ObservationMismatch);
17250                }
17251                let begin = usize::try_from(frozen.protected_member_offset)
17252                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
17253                let count = usize::try_from(frozen.protected_member_count)
17254                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
17255                let end = begin
17256                    .checked_add(count)
17257                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
17258                let positions = protected
17259                    .get(begin..end)
17260                    .ok_or(SemanticTransitionError::ObservationMismatch)?
17261                    .to_vec();
17262                observations.push(SemanticUpdateCanaryMeasurement {
17263                    frozen,
17264                    protected_positions: positions,
17265                    availability: measured.availability,
17266                    reason: measured.reason,
17267                    measurement_bits: complete.then_some(measured.measurement_bits),
17268                    memory_used: measured.memory_used,
17269                    work_used: measured.work_used,
17270                });
17271            }
17272            let winning = results
17273                .iter()
17274                .filter(|check| check.reason != 0)
17275                .min_by_key(|check| (check.reason, check.kind));
17276            if winning.map(|check| (check.reason, check.kind))
17277                != refusal.map(|record| (record.reason, record.kind))
17278                || refusal.is_some_and(|record| {
17279                    let frozen = &observations[(record.kind - 1) as usize].frozen;
17280                    record.selection_identity != selection.identity
17281                        || record.lower_bound_bits != frozen.lower_bound_bits
17282                        || record.upper_bound_bits != frozen.upper_bound_bits
17283                        || record.memory_limit != frozen.memory_limit
17284                        || record.work_limit != frozen.work_limit
17285                })
17286                || (result.advanced == 1
17287                    && (state.status != 0
17288                        || refusal.is_some()
17289                        || observations.iter().any(|check| check.availability != 2)))
17290            {
17291                return Err(SemanticTransitionError::ObservationMismatch);
17292            }
17293            let mut forwards = Vec::with_capacity(2);
17294            for (role, receipt) in receipts.iter().enumerate() {
17295                if receipt.availability > 2 {
17296                    return Err(SemanticTransitionError::ObservationMismatch);
17297                }
17298                let bytes = receipt.canonical_bytes();
17299                let material = if receipt.availability == 2 {
17300                    let (address, layout) = logits[role];
17301                    let digest: [u8; 32] = Sha256::digest(&bytes[..bytes.len() - 32]).into();
17302                    if receipt.abi != 1
17303                        || receipt.role != role as u64
17304                        || receipt.work_sequence == 0
17305                        || receipt.work_sequence > work_count
17306                        || receipt.logits != address
17307                        || receipt.scalar_type != layout.scalar_type
17308                        || [receipt.row_count, receipt.capacity, receipt.vocabulary]
17309                            != layout.dimensions[..3]
17310                        || receipt.strides_bytes != layout.strides_bytes[..3]
17311                        || receipt.model_geometry_digest != binding.3
17312                        || receipt.identity != Identity256::from_bytes(digest)
17313                        || receipt.model_numerical_digest == Identity256::default()
17314                        || (role == 0
17315                            && (receipt.generation != binding.2
17316                                || receipt.model_numerical_digest != binding.4))
17317                        || (role == 1
17318                            && result.advanced == 1
17319                            && (receipt.generation != result.header.model_generation
17320                                || receipt.model_numerical_digest
17321                                    != result.header.model_numerical_digest))
17322                    {
17323                        return Err(SemanticTransitionError::ObservationMismatch);
17324                    }
17325                    Some(SemanticUpdateForwardReceiptMaterial {
17326                        role: receipt.role,
17327                        generation: receipt.generation,
17328                        work_sequence: receipt.work_sequence,
17329                        scalar_type: receipt.scalar_type,
17330                        dimensions: [receipt.row_count, receipt.capacity, receipt.vocabulary],
17331                        strides_bytes: receipt.strides_bytes,
17332                        model_geometry_digest: receipt.model_geometry_digest,
17333                        model_numerical_digest: receipt.model_numerical_digest,
17334                        logits_digest: receipt.logits_digest,
17335                        identity: receipt.identity,
17336                        canonical_bytes: bytes,
17337                    })
17338                } else {
17339                    // An unexecuted one-shot receipt is the original zero allocation.
17340                    // A started but incomplete producer cannot masquerade as a sealed receipt.
17341                    let mut absent = *receipt;
17342                    absent.availability = 0;
17343                    if absent.canonical_bytes().iter().any(|&byte| byte != 0)
17344                        || result.advanced == 1
17345                    {
17346                        return Err(SemanticTransitionError::ObservationMismatch);
17347                    }
17348                    None
17349                };
17350                forwards.push(SemanticUpdateForwardReceipt {
17351                    availability: receipt.availability,
17352                    material,
17353                });
17354            }
17355            if receipts.iter().all(|receipt| receipt.availability == 2)
17356                && (receipts[0].work_sequence >= receipts[1].work_sequence
17357                    || receipts[0].identity == receipts[1].identity)
17358            {
17359                return Err(SemanticTransitionError::ObservationMismatch);
17360            }
17361            Ok(Some(SemanticUpdateMeasurements {
17362                predecessor: binding.0,
17363                successor: binding.1,
17364                bank: bank as u8,
17365                model_generation: binding.2,
17366                model_geometry_digest: binding.3,
17367                model_numerical_digest: binding.4,
17368                transition_status: state.status,
17369                selection,
17370                canaries: observations,
17371                forward_receipts: forwards
17372                    .try_into()
17373                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
17374                canary_refusal: refusal,
17375            }))
17376        })();
17377        if observation.is_err() {
17378            self.poisoned = true;
17379        }
17380        let observation = observation?;
17381        if self.prepared_model_binding(step, &streams)? != binding {
17382            self.poisoned = true;
17383            return Err(SemanticTransitionError::ObservationMismatch);
17384        }
17385        Ok(observation)
17386    }
17387
17388    pub fn prepared_feedback(
17389        &mut self,
17390        step: &SemanticPreparedStep,
17391        consumer_stream: u64,
17392    ) -> Result<(SemanticFeedbackSchema, [DlpackManagedTensor; 6]), SemanticTransitionError> {
17393        self.check_prepared_cold(step)?;
17394        let feedback = &self.steps[&step.token].feedback[0];
17395        let schema = feedback.schema.clone();
17396        let layouts = feedback
17397            .content
17398            .tensors
17399            .iter()
17400            .map(|tensor| {
17401                (
17402                    tensor.source.as_ref().expect("feedback owner").clone(),
17403                    tensor.layout,
17404                )
17405            })
17406            .collect::<Vec<_>>();
17407        let mut outputs = Vec::with_capacity(6);
17408        for (view, layout) in layouts {
17409            let shape = layout.dimensions[..layout.rank as usize]
17410                .iter()
17411                .map(|&value| value as i64)
17412                .collect();
17413            let strides = layout.strides_bytes[..layout.rank as usize]
17414                .iter()
17415                .map(|&value| (value / layout.element_bytes) as i64)
17416                .collect();
17417            let dtype = match layout.scalar_type {
17418                3 => (1, 64),
17419                6 => (2, 32),
17420                8 => (6, 8),
17421                _ => return Err(SemanticTransitionError::ObservationMismatch),
17422            };
17423            outputs.push(self.export_prepared_view(
17424                step,
17425                view,
17426                shape,
17427                strides,
17428                dtype,
17429                consumer_stream,
17430            )?);
17431        }
17432        Ok((
17433            schema,
17434            outputs
17435                .try_into()
17436                .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
17437        ))
17438    }
17439
17440    /// Cold readback of each original raw feedback, statement and provenance
17441    /// record, after known completion and before this prepared step retires.
17442    /// The original input guard brackets readback; neither a current-bank
17443    /// reader nor a fresh encoder/semantic query is constructed. These bytes
17444    /// are inputs to the canonical carrier, not an execution or replay grant.
17445    pub fn prepared_feedback_records(
17446        &mut self,
17447        step: &SemanticPreparedStep,
17448        consumer_streams: &[u64],
17449    ) -> Result<
17450        (
17451            SemanticPublishedIdentity,
17452            Option<SemanticPublishedIdentity>,
17453            Vec<SemanticFeedbackRecordMaterial>,
17454        ),
17455        SemanticTransitionError,
17456    > {
17457        let binding = self.prepared_model_binding(step, consumer_streams)?;
17458        let inputs = Arc::clone(
17459            self.checked_prepared_step(step, false)?
17460                .inputs
17461                .as_ref()
17462                .ok_or(SemanticTransitionError::ObservationMismatch)?,
17463        );
17464        let ranges = self.publication_read(inputs.ranges.view())?;
17465        let mut records = Vec::new();
17466        for range in ranges
17467            .into_iter()
17468            .filter(|range| matches!(range.role, 15..=17))
17469        {
17470            let original = inputs
17471                .storage
17472                .allocations
17473                .get(
17474                    usize::try_from(range.storage_slot)
17475                        .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
17476                )
17477                .ok_or(SemanticTransitionError::ObservationMismatch)?;
17478            let capacity = usize::try_from(range.offset_bytes)
17479                .ok()
17480                .and_then(|begin| original.len().checked_sub(begin))
17481                .ok_or(SemanticTransitionError::ObservationMismatch)?;
17482            let view = inputs
17483                .views
17484                .first()
17485                .expect("two publication input banks")
17486                .get(&(range.role, range.index))
17487                .ok_or(SemanticTransitionError::ObservationMismatch)?;
17488            let bytes = self.publication_read(view.clone())?;
17489            match (PublicationMaterialRange {
17490                range,
17491                capacity,
17492                bytes,
17493            })
17494            .into_feedback_record()
17495            {
17496                Ok(record) => records.push(record),
17497                Err(error) => {
17498                    self.poisoned = true;
17499                    return Err(error);
17500                }
17501            }
17502        }
17503        if self.prepared_model_binding(step, consumer_streams)? != binding {
17504            self.poisoned = true;
17505            return Err(SemanticTransitionError::ObservationMismatch);
17506        }
17507        Ok((binding.0, binding.1, records))
17508    }
17509
17510    /// Serialize the completed step's original native RNG and executed-work
17511    /// witnesses while its retained input/result owners are still reachable.
17512    #[cfg(feature = "semantic-policy")]
17513    fn prepared_completed_step_witnesses(
17514        &mut self,
17515        step: &SemanticPreparedStep,
17516        consumer_streams: &[u64],
17517    ) -> Result<SemanticCompletedStepWitnessMaterial, SemanticTransitionError> {
17518        let binding = self.prepared_model_binding(step, consumer_streams)?;
17519        let transition = match self.completed_prepared_transition_kind(step)? {
17520            SemanticTransitionKind::Proposal => 1,
17521            SemanticTransitionKind::Recompute => 2,
17522            SemanticTransitionKind::Update => 3,
17523            SemanticTransitionKind::Drain => 4,
17524        };
17525        let (header_view, result_view, actual_view, events) = {
17526            let owner = self.checked_prepared_step(step, false)?;
17527            let inputs = owner
17528                .inputs
17529                .as_ref()
17530                .ok_or(SemanticTransitionError::ObservationMismatch)?;
17531            let prepared = owner.prepared.as_ref().expect("checked prepared owner");
17532            let work = prepared
17533                .model_work
17534                .as_ref()
17535                .ok_or(SemanticTransitionError::ObservationMismatch)?;
17536            (
17537                inputs.header.view(),
17538                prepared.result.view(),
17539                work.actual.view(),
17540                work.recording.events().to_vec(),
17541            )
17542        };
17543        let header = self.publication_read(header_view)?[0];
17544        let result = self.publication_read(result_view)?[0];
17545        let actual = self.publication_read(actual_view)?;
17546        if actual.len() < events.len().saturating_mul(3) {
17547            self.poisoned = true;
17548            return Err(SemanticTransitionError::ObservationMismatch);
17549        }
17550
17551        let mut owner_binding = Vec::new();
17552        owner_binding.extend_from_slice(b"xlog.completed-step-witness-owner.v1\0");
17553        encode_publication_identity(&mut owner_binding, binding.0);
17554        material_u64(&mut owner_binding, u64::from(binding.1.is_some()));
17555        if let Some(successor) = binding.1 {
17556            encode_publication_identity(&mut owner_binding, successor);
17557        }
17558        material_u64(&mut owner_binding, step.token);
17559        material_u64(&mut owner_binding, transition);
17560        let mut owner_hash = Sha256::new();
17561        owner_hash.update(&owner_binding);
17562        let identity = Identity256::from_bytes(owner_hash.finalize().into());
17563
17564        let mut bytes = Vec::new();
17565        bytes.extend_from_slice(b"XLOG-COMPLETED-STEP-WITNESSES\0");
17566        material_u64(&mut bytes, 1);
17567        material_u64(&mut bytes, transition);
17568        encode_publication_identity(&mut bytes, binding.0);
17569        material_u64(&mut bytes, u64::from(binding.1.is_some()));
17570        if let Some(successor) = binding.1 {
17571            encode_publication_identity(&mut bytes, successor);
17572        }
17573        material_u64(&mut bytes, header.model_generation);
17574        material_u64(&mut bytes, header.stream_serial);
17575        material_u64(&mut bytes, header.family_id);
17576        material_u64(&mut bytes, header.proposal);
17577        material_u64(&mut bytes, header.training_cursor);
17578        for value in header.training_rng {
17579            material_u64(&mut bytes, value);
17580        }
17581        material_u64(&mut bytes, result.refusal);
17582        material_u64(&mut bytes, result.advanced);
17583        bytes.extend_from_slice(binding.3.as_bytes());
17584        bytes.extend_from_slice(binding.4.as_bytes());
17585        material_u64(&mut bytes, events.len() as u64);
17586        for (index, event) in events.iter().enumerate() {
17587            material_u64(&mut bytes, event.kind);
17588            material_u64(&mut bytes, event.witness);
17589            material_u64(&mut bytes, event.tensor);
17590            material_u64(&mut bytes, event.rank);
17591            for dimension in event.dimensions {
17592                material_u64(&mut bytes, dimension);
17593            }
17594            for value in &actual[index * 3..index * 3 + 3] {
17595                material_u64(&mut bytes, *value);
17596            }
17597        }
17598        if self.prepared_model_binding(step, consumer_streams)? != binding {
17599            self.poisoned = true;
17600            return Err(SemanticTransitionError::ObservationMismatch);
17601        }
17602        Ok(SemanticCompletedStepWitnessMaterial { identity, bytes })
17603    }
17604
17605    /// Serialize the selected Proposal branch's original device state and all
17606    /// 136 exact component receipts after known completion. The step-owned
17607    /// buffers, not a current publication or Python reconstruction, are read.
17608    #[cfg(feature = "semantic-policy")]
17609    fn prepared_completed_action_witnesses(
17610        &mut self,
17611        step: &SemanticPreparedStep,
17612        consumer_streams: &[u64],
17613    ) -> Result<SemanticCompletedStepWitnessMaterial, SemanticTransitionError> {
17614        let binding = self.prepared_model_binding(step, consumer_streams)?;
17615        if self.completed_prepared_transition_kind(step)? != SemanticTransitionKind::Proposal {
17616            return Err(publication_input_error(
17617                "completed action witnesses require an original Proposal",
17618            ));
17619        }
17620        let result_view = self
17621            .checked_prepared_step(step, false)?
17622            .prepared
17623            .as_ref()
17624            .expect("checked prepared owner")
17625            .result
17626            .view();
17627        let result = self.publication_read(result_view)?[0];
17628        let tape_index = self.completed_prepared_policy_tape(step)?;
17629        let bank = self.policy_tapes[tape_index]
17630            .prepared_bank
17631            .ok_or(SemanticTransitionError::ObservationMismatch)?;
17632        let (state_view, receipt_view) = {
17633            let prepared = self
17634                .checked_prepared_step(step, false)?
17635                .prepared
17636                .as_ref()
17637                .expect("checked prepared owner");
17638            let branch = &prepared.branches[bank];
17639            (
17640                branch.state.view(),
17641                self.policy_tapes[tape_index].receipts.view(),
17642            )
17643        };
17644        let state = self.publication_read(state_view)?[0];
17645        let receipts = self.publication_read(receipt_view)?;
17646        if result.refusal != 0
17647            || result.advanced != 1
17648            || state.status != 0
17649            || state.blocks != COMPONENT_COUNT as u64
17650            || receipts.len() != COMPONENT_COUNT
17651            || state.proposal.checked_add(1) != Some(state.next_proposal)
17652            || state.next_proposal != result.header.proposal
17653            || receipts
17654                .iter()
17655                .any(|receipt| receipt.proposal != state.proposal)
17656        {
17657            self.poisoned = true;
17658            return Err(SemanticTransitionError::ObservationMismatch);
17659        }
17660
17661        let mut owner_binding = Vec::new();
17662        owner_binding.extend_from_slice(b"xlog.completed-action-witness-owner.v1\0");
17663        encode_publication_identity(&mut owner_binding, binding.0);
17664        encode_publication_identity(
17665            &mut owner_binding,
17666            binding
17667                .1
17668                .ok_or(SemanticTransitionError::ObservationMismatch)?,
17669        );
17670        material_u64(&mut owner_binding, step.token);
17671        material_u64(&mut owner_binding, state.proposal);
17672        let mut owner_hash = Sha256::new();
17673        owner_hash.update(&owner_binding);
17674        let identity = Identity256::from_bytes(owner_hash.finalize().into());
17675
17676        let mut bytes = Vec::new();
17677        bytes.extend_from_slice(b"XLOG-COMPLETED-ACTION-WITNESSES\0");
17678        material_u64(&mut bytes, 1);
17679        encode_publication_identity(&mut bytes, binding.0);
17680        encode_publication_identity(
17681            &mut bytes,
17682            binding
17683                .1
17684                .ok_or(SemanticTransitionError::ObservationMismatch)?,
17685        );
17686        material_u64(&mut bytes, bank as u64);
17687        material_u64(&mut bytes, size_of::<DeviceState>() as u64);
17688        bytes.extend(publication_abi_bytes(&[state]));
17689        material_u64(&mut bytes, receipts.len() as u64);
17690        bytes.extend(publication_abi_bytes(&receipts));
17691        if self.prepared_model_binding(step, consumer_streams)? != binding {
17692            self.poisoned = true;
17693            return Err(SemanticTransitionError::ObservationMismatch);
17694        }
17695        Ok(SemanticCompletedStepWitnessMaterial { identity, bytes })
17696    }
17697
17698    #[cfg(feature = "semantic-policy")]
17699    fn original_initial_prefill_content(
17700        &mut self,
17701        predecessor: SemanticPublishedIdentity,
17702        semantic_root: Identity256,
17703        prefix_extent: u64,
17704        model_generation: u64,
17705        task_identity: Identity256,
17706        task_content: SemanticTaskContentIdentity,
17707    ) -> Result<Option<Vec<u8>>, SemanticTransitionError> {
17708        let Some(retained) = self.retained_initial_prefill.as_ref() else {
17709            return Ok(None);
17710        };
17711        if retained.record.predecessor != predecessor {
17712            return Ok(None);
17713        }
17714        let record = retained.record.clone();
17715        if record.semantic_root != semantic_root
17716            || record.model_generation != model_generation
17717            || record.task_identity != task_identity
17718            || record.task_content != task_content
17719            || record.task_epoch != self.task_epoch
17720            || record.task_identity != retained.task_identity
17721            || record.task_epoch != retained.task_epoch
17722            || record.model_generation != retained.model_generation
17723            || record.tokens.is_empty()
17724            || record.tokens.len() as u64 != prefix_extent
17725            || record.mapping.len() != record.tokens.len()
17726            || record.mapping.iter().enumerate().any(|(position, row)| {
17727                row.source.is_empty() || row.logical_position != position as u64
17728            })
17729        {
17730            self.poisoned = true;
17731            return Err(SemanticTransitionError::ObservationMismatch);
17732        }
17733        let model_seals = initial_prefill_seal_sources(&retained.model)?;
17734        let output_seals = initial_prefill_seal_sources(&retained.output)?;
17735        if model_seals.is_empty()
17736            || output_seals.is_empty()
17737            || model_seals
17738                .iter()
17739                .any(|(role, _, _, _)| !matches!(role, 0 | 18..=25))
17740            || output_seals
17741                .iter()
17742                .any(|(role, _, _, _)| !matches!(role, 4..=13))
17743        {
17744            self.poisoned = true;
17745            return Err(SemanticTransitionError::ObservationMismatch);
17746        }
17747        let mut bytes = Vec::new();
17748        bytes.extend_from_slice(record.semantic_root.as_bytes());
17749        material_u64(&mut bytes, record.model_generation);
17750        bytes.extend_from_slice(record.task_identity.as_bytes());
17751        material_u64(&mut bytes, record.task_epoch);
17752        for identity in [
17753            record.task_content.query,
17754            record.task_content.theory_program,
17755            record.task_content.result,
17756        ] {
17757            bytes.extend_from_slice(identity.as_bytes());
17758        }
17759        material_u64(&mut bytes, record.tokens.len() as u64);
17760        for token in &record.tokens {
17761            material_u64(&mut bytes, *token);
17762        }
17763        material_u64(&mut bytes, record.mapping.len() as u64);
17764        for row in &record.mapping {
17765            material_u64(&mut bytes, row.source.len() as u64);
17766            bytes.extend_from_slice(row.source.as_bytes());
17767            material_u64(&mut bytes, row.offset);
17768            material_u64(&mut bytes, row.logical_position);
17769        }
17770        for seals in [model_seals, output_seals] {
17771            material_u64(&mut bytes, seals.len() as u64);
17772            for (role, index, cells, offset) in seals {
17773                let digest = self.publication_read(cells.view())?;
17774                if offset.checked_add(4).is_none_or(|end| end > digest.len()) {
17775                    self.poisoned = true;
17776                    return Err(SemanticTransitionError::ObservationMismatch);
17777                }
17778                material_u64(&mut bytes, role);
17779                material_u64(&mut bytes, index);
17780                for word in &digest[offset..offset + 4] {
17781                    material_u64(&mut bytes, *word);
17782                }
17783            }
17784        }
17785        Ok(Some(bytes))
17786    }
17787
17788    #[cfg(feature = "semantic-policy")]
17789    #[expect(
17790        clippy::too_many_arguments,
17791        reason = "the original prefill and actual recovered predecessor have independent owners"
17792    )]
17793    fn completed_initial_prefill_material(
17794        &mut self,
17795        predecessor: SemanticPublishedIdentity,
17796        recovered_instance: Identity256,
17797        semantic_root: Identity256,
17798        prefix_extent: u64,
17799        model_generation: u64,
17800        task_identity: Identity256,
17801        task_content: SemanticTaskContentIdentity,
17802        owner: Identity256,
17803    ) -> Result<Option<SemanticCompletedStepWitnessMaterial>, SemanticTransitionError> {
17804        let live_content = self.original_initial_prefill_content(
17805            predecessor,
17806            semantic_root,
17807            prefix_extent,
17808            model_generation,
17809            task_identity,
17810            task_content,
17811        )?;
17812        let (original, content, recovery_referent) =
17813            if let Some(saved) = &self.checkpoint_initial_prefill {
17814                if saved.original != predecessor {
17815                    if saved.original.instance == predecessor.instance
17816                        || predecessor.word != 0
17817                        || recovered_instance != saved.original.instance
17818                        || predecessor.logical_digest != saved.original.logical_digest
17819                        || predecessor.state_digest != saved.original.state_digest
17820                        || live_content.is_some()
17821                    {
17822                        self.poisoned = true;
17823                        return Err(SemanticTransitionError::ObservationMismatch);
17824                    }
17825                    let referent = saved
17826                        .recovery_referent
17827                        .as_ref()
17828                        .ok_or(SemanticTransitionError::ObservationMismatch)?;
17829                    (
17830                        saved.original,
17831                        saved.content.as_slice(),
17832                        Some(referent.as_slice()),
17833                    )
17834                } else {
17835                    if live_content.as_deref() != Some(saved.content.as_slice()) {
17836                        self.poisoned = true;
17837                        return Err(SemanticTransitionError::ObservationMismatch);
17838                    }
17839                    (saved.original, saved.content.as_slice(), None)
17840                }
17841            } else {
17842                let Some(content) = live_content.as_deref() else {
17843                    return Ok(None);
17844                };
17845                (predecessor, content, None)
17846            };
17847        let mut bytes = Vec::new();
17848        bytes.extend_from_slice(b"XLOG-INITIAL-PREFILL\0");
17849        material_u64(&mut bytes, 2);
17850        encode_publication_identity(&mut bytes, original);
17851        encode_publication_identity(&mut bytes, predecessor);
17852        if let Some(referent) = recovery_referent {
17853            bytes.push(2);
17854            material_u64(
17855                &mut bytes,
17856                u64::try_from(referent.len())
17857                    .map_err(|_| publication_input_error("checkpoint referent exceeds u64"))?,
17858            );
17859            bytes.extend_from_slice(referent);
17860        } else {
17861            bytes.push(1);
17862        }
17863        bytes.extend_from_slice(content);
17864        Ok(Some(completed_action_child_material(
17865            owner,
17866            b"initial-prefill",
17867            0,
17868            &bytes,
17869        )))
17870    }
17871
17872    /// Reserve the complete cold export before any execution chooses a bank or
17873    /// action. Only frozen extents and captured launch metadata are inspected;
17874    /// no tensor value, publication header, or future result is read.
17875    #[cfg(feature = "semantic-policy")]
17876    pub fn prepared_completed_material_capacity(
17877        &self,
17878        step: &SemanticPreparedStep,
17879    ) -> Result<SemanticCompletedMaterialCapacity, SemanticTransitionError> {
17880        let owner = self.checked_prepared_step(step, false)?;
17881        let build = self
17882            .prepared_segment
17883            .as_ref()
17884            .expect("checked prepared scope");
17885        if !build.finished || build.capturing || build.active || build.submitted || build.completed
17886        {
17887            return Err(publication_input_error(
17888                "completed material capacity requires finished capture before the first submit",
17889            ));
17890        }
17891        if build.requested_kind(step, &self.publication_issuer)? != SemanticTransitionKind::Proposal
17892        {
17893            return Err(publication_input_error(
17894                "completed material capacity requires an original Proposal",
17895            ));
17896        }
17897        let prepared = owner.prepared.as_ref().expect("checked prepared owner");
17898        let inputs = owner
17899            .inputs
17900            .as_ref()
17901            .ok_or(SemanticTransitionError::ObservationMismatch)?;
17902        let work = prepared
17903            .model_work
17904            .as_ref()
17905            .ok_or(SemanticTransitionError::ObservationMismatch)?;
17906        let launches = self
17907            .captured
17908            .as_ref()
17909            .ok_or(SemanticTransitionError::ObservationMismatch)?
17910            .captured_launch_bindings();
17911        if launches.is_empty()
17912            || launches
17913                .iter()
17914                .any(|launch| launch.artifact_sha256.is_none())
17915        {
17916            return Err(SemanticTransitionError::ObservationMismatch);
17917        }
17918        let task = &self
17919            .task
17920            .as_ref()
17921            .ok_or(SemanticTransitionError::ObservationMismatch)?
17922            .0;
17923        let mut capacity = SemanticCompletedMaterialCapacity::default();
17924        let publication_identity_bytes = 3 * 32 + size_of::<u64>();
17925        // These are the serialized fields, not the narrower private device ABI.
17926        let component_receipt_bytes = (2 + 9 + 2 + 4 + 4 + 4 + 4 * 3 + 2) * 8 + 2 * 32;
17927        let semantic_receipt_bytes = 42 * size_of::<u64>();
17928        let action_bytes = completed_material_extent(&[
17929            b"XLOG-COMPLETED-ACTION-WITNESSES\0".len(),
17930            4 * 8,
17931            2 * publication_identity_bytes,
17932            size_of::<DeviceState>(),
17933            repeated_material_extent(COMPONENT_COUNT, size_of::<SemanticTransitionReceipt>())?,
17934        ])?;
17935        capacity.add(action_bytes)?;
17936        if let Some(saved) = &self.checkpoint_initial_prefill {
17937            let referent = saved.recovery_referent.as_ref().map_or(0, Vec::len);
17938            capacity.child(
17939                b"initial-prefill",
17940                completed_material_extent(&[
17941                    b"XLOG-INITIAL-PREFILL\0".len(),
17942                    8,
17943                    2 * publication_identity_bytes,
17944                    1,
17945                    8,
17946                    referent,
17947                    saved.content.len(),
17948                ])?,
17949            )?;
17950        } else if let Some(retained) = &self.retained_initial_prefill {
17951            let record = &retained.record;
17952            let mut content = completed_material_extent(&[
17953                2 * 32,
17954                2 * 8,
17955                3 * 32,
17956                2 * 8,
17957                repeated_material_extent(record.tokens.len(), 8)?,
17958                2 * 8,
17959                repeated_material_extent(
17960                    initial_prefill_seal_sources(&retained.model)?.len(),
17961                    6 * 8,
17962                )?,
17963                repeated_material_extent(
17964                    initial_prefill_seal_sources(&retained.output)?.len(),
17965                    6 * 8,
17966                )?,
17967            ])?;
17968            for row in &record.mapping {
17969                content = completed_material_extent(&[content, 3 * 8, row.source.len()])?;
17970            }
17971            capacity.child(
17972                b"initial-prefill",
17973                completed_material_extent(&[
17974                    b"XLOG-INITIAL-PREFILL\0".len(),
17975                    8,
17976                    2 * publication_identity_bytes,
17977                    1,
17978                    content,
17979                ])?,
17980            )?;
17981        }
17982        capacity.add(
17983            self.graph
17984                .transition_root_material_capacity()
17985                .map_err(SemanticTransitionError::Semantic)?,
17986        )?;
17987        capacity.add(
17988            self.graph
17989                .admission()
17990                .ok_or(SemanticTransitionError::ObservationMismatch)?
17991                .schema_bytes()
17992                .len(),
17993        )?;
17994        capacity.add(SemanticActionCatalogue::current().canonical_bytes().len())?;
17995        capacity.add(repeated_material_extent(self.codebooks.words.len(), 8)?)?;
17996        capacity.add(completed_material_extent(&[
17997            b"xlog.semantic-action-roster.v1\0".len(),
17998            32 + 8,
17999            repeated_material_extent(self.codebooks.components.len(), 7 * 8)?,
18000        ])?)?;
18001        capacity.add(size_of::<SemanticActionBatchReceipt>())?;
18002        capacity.add(task.completed_result_material().bytes.len())?;
18003        for _ in 0..2 {
18004            capacity.child(b"action-rng", 4 * 8)?;
18005            capacity.child(b"logical-state", publication_identity_bytes)?;
18006            capacity.child(b"lane-admission", semantic_receipt_bytes)?;
18007            for _ in 0..2 {
18008                capacity.child(b"hard-decode-receipt", semantic_receipt_bytes)?;
18009            }
18010        }
18011        capacity.child(b"slot-zero-admission", semantic_receipt_bytes)?;
18012        for component in &self.codebooks.components {
18013            let mask = completed_material_extent(&[8, component.cardinality as usize])?;
18014            capacity.child(b"final-mask", mask)?;
18015            capacity.child(b"active-set", mask)?;
18016            capacity.child(b"component-receipt", component_receipt_bytes)?;
18017            capacity.child(b"pwl-cell", size_of::<SemanticPolicyPwlCell>())?;
18018            capacity.child(b"vjp", size_of::<SemanticPolicySelectedScoreVjp>())?;
18019        }
18020        // Every edit slot may emit both a delta and its refusal/acceptance
18021        // evidence. NULL, winner selection, and digest aliases cannot shrink
18022        // the reservation before execution.
18023        let editable_program = task.spec().program.editable_program().is_some();
18024        let (delta_kind, evidence_kind, delta_bytes, evidence_prefix) = if editable_program {
18025            (
18026                b"theory-rule-delta".as_slice(),
18027                b"theory-rule-delta-evidence".as_slice(),
18028                b"XLOG-DECODED-RULE-INSERTION\0".len() + 8 + 2 * 32 + (18 + 10) * 4,
18029                2 * 32 + 3 * 8,
18030            )
18031        } else {
18032            (
18033                b"theory-delta".as_slice(),
18034                b"theory-delta-evidence".as_slice(),
18035                b"XLOG-DECODED-SUPPORT-INSERTION\0".len() + 8 + 3 * 32 + (18 + 1 + 10) * 4,
18036                32 + 3 * 8 + (1 + 10) * 4,
18037            )
18038        };
18039        for _ in 0..4 {
18040            capacity.child(delta_kind, delta_bytes)?;
18041            capacity.child(
18042                evidence_kind,
18043                completed_material_extent(&[
18044                    evidence_prefix,
18045                    2 * semantic_receipt_bytes,
18046                    18 * component_receipt_bytes,
18047                ])?,
18048            )?;
18049        }
18050        let mut ground = completed_material_extent(&[
18051            b"XLOG-COMPLETED-TASK-GROUND\0".len(),
18052            17 * 8,
18053            10 * 32,
18054            publication_identity_bytes,
18055            3 * size_of::<SemanticTaskFacts>(),
18056        ])?;
18057        for level in task.priority_levels() {
18058            ground = completed_material_extent(&[
18059                ground,
18060                8,
18061                repeated_material_extent(level.goals.len(), 3 * 8)?,
18062            ])?;
18063        }
18064        capacity.child(b"task-ground", ground)?;
18065        capacity.child(
18066            b"task-scoring-law",
18067            task.spec()
18068                .scoring
18069                .completed_law_bytes(task.identity(), editable_program)?
18070                .len(),
18071        )?;
18072        capacity.child(
18073            b"edit-solution",
18074            b"XLOG-COMPLETED-EDIT-SOLUTION\0".len() + 8 + 64 + 32 + 6 * 8 + 3 * 64 + 68 * 5 * 64,
18075        )?;
18076        capacity.attempt_receipt_bytes = capacity.child(b"attempt-receipt", 4 * 8 + 10 * 32)?;
18077        if let Some(roster) = &inputs.storage.physical_parameter_roster {
18078            let mut names = 0;
18079            for name in roster {
18080                names = completed_material_extent(&[names, name.len()])?;
18081            }
18082            let mut original_records = 0;
18083            for bank in 0..2 {
18084                let model = inputs.views[bank]
18085                    .get(&(44, 0))
18086                    .ok_or(SemanticTransitionError::ObservationMismatch)?
18087                    .len();
18088                let profile = inputs.storage.bank_templates[bank]
18089                    .iter()
18090                    .find(|range| range.role == 43 && range.index == 0)
18091                    .and_then(|range| usize::try_from(range.length_bytes).ok())
18092                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
18093                original_records =
18094                    original_records.max(completed_material_extent(&[model, profile])?);
18095            }
18096            capacity.child(
18097                b"estimator-bound",
18098                completed_material_extent(&[
18099                    b"XLOG-ESTIMATOR-BOUND\0".len(),
18100                    4 * 8,
18101                    publication_identity_bytes,
18102                    8,
18103                    3 * 32,
18104                    2 * 64,
18105                    2 * 32,
18106                    6 * 8,
18107                    3 * 8,
18108                    original_records,
18109                    repeated_material_extent(roster.len(), 7 * 8)?,
18110                    names,
18111                ])?,
18112            )?;
18113        }
18114        let mut graph = b"XLOG-CAPTURED-CUDA-LAUNCH-BINDINGS\0".len() + 2 * 8;
18115        for launch in launches {
18116            graph = completed_material_extent(&[
18117                graph,
18118                13 * 8 + 32,
18119                launch.module_name.len(),
18120                launch.artifact_name.len(),
18121                launch.function_name.len(),
18122            ])?;
18123        }
18124        let work_bytes = completed_material_extent(&[
18125            b"XLOG-COMPLETED-STEP-WITNESSES\0".len(),
18126            15 * 8,
18127            2 * publication_identity_bytes,
18128            2 * 32,
18129            repeated_material_extent(work.recording.events().len(), (4 + 8 + 3) * 8)?,
18130        ])?;
18131        let numerical = completed_material_extent(&[
18132            b"XLOG-COMPLETED-NUMERICAL-REALIZATION\0".len(),
18133            4 * 8,
18134            graph,
18135            work_bytes,
18136            action_bytes,
18137        ])?;
18138        let mut logits = 0;
18139        for branch in &prepared.branches {
18140            let policy = branch
18141                .policy
18142                .as_ref()
18143                .ok_or(SemanticTransitionError::ObservationMismatch)?;
18144            let field_count = repeated_material_extent(policy.layout.fields.len(), 4)?;
18145            let mut scores = 0;
18146            for field in &policy.layout.fields {
18147                scores = completed_material_extent(&[scores, field.cardinality])?;
18148            }
18149            logits = logits.max(completed_material_extent(&[
18150                b"XLOG-COMPLETED-EDIT-LOGITS\0".len(),
18151                2 * 8,
18152                repeated_material_extent(field_count, 5 * 8)?,
18153                repeated_material_extent(scores, 4 * 4)?,
18154            ])?);
18155        }
18156        let random = b"XLOG-COMPLETED-RANDOM-STATE\0".len() + 11 * 8 + COMPONENT_COUNT * 12 * 8;
18157        capacity.carrier_bytes = [numerical, logits, random];
18158        for bytes in capacity.carrier_bytes {
18159            capacity.add(bytes)?;
18160        }
18161        for plan in inputs
18162            .plans
18163            .iter()
18164            .filter(|plan| matches!(plan.role, 15..=17))
18165        {
18166            let mut bytes = 0;
18167            for bank in &plan.banks {
18168                bytes = bytes.max(
18169                    bank.span
18170                        .end
18171                        .checked_sub(bank.span.start)
18172                        .ok_or(SemanticTransitionError::ObservationMismatch)?,
18173                );
18174            }
18175            capacity.add(bytes)?;
18176        }
18177        let mut evidence = REPLAY_EVIDENCE_MAGIC.len() + 2 * 4 + 32 + publication_identity_bytes;
18178        for role in REPLAY_EVIDENCE_ROLES {
18179            let mut bytes = 0;
18180            for bank in &inputs.storage.bank_templates {
18181                let range = bank
18182                    .iter()
18183                    .find(|range| range.role == role && range.index == 0)
18184                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
18185                let slot = usize::try_from(range.storage_slot)
18186                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
18187                let offset = usize::try_from(range.offset_bytes)
18188                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
18189                let allocation = inputs
18190                    .storage
18191                    .allocations
18192                    .get(slot)
18193                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
18194                bytes = bytes.max(
18195                    allocation
18196                        .len()
18197                        .checked_sub(offset)
18198                        .ok_or(SemanticTransitionError::ObservationMismatch)?,
18199                );
18200            }
18201            evidence = completed_material_extent(&[
18202                evidence,
18203                2 * 4 + size_of::<PublicationRange>() + 8,
18204                bytes,
18205            ])?;
18206        }
18207        capacity.publication_evidence_bytes = evidence;
18208        let custody = prepared
18209            .replay_custody
18210            .as_ref()
18211            .ok_or(SemanticTransitionError::ObservationMismatch)?;
18212        let (parent, provenance) = custody.material_capacity(
18213            &inputs.storage,
18214            self.graph
18215                .transition_root_material_capacity()
18216                .map_err(SemanticTransitionError::Semantic)?,
18217        )?;
18218        capacity.add(parent)?;
18219        capacity.add(provenance)?;
18220        capacity.child(b"pre-action-checkpoint", Self::CHECKPOINT_REFERENT_BYTES)?;
18221        Ok(capacity)
18222    }
18223
18224    /// Project one completed Proposal into typed action-law values and canonical
18225    /// byte-backed child materials. Private device structs never cross this API.
18226    #[cfg(feature = "semantic-policy")]
18227    pub fn prepared_completed_action_projection(
18228        &mut self,
18229        step: &SemanticPreparedStep,
18230        consumer_streams: &[u64],
18231    ) -> Result<SemanticCompletedActionProjectionMaterial, SemanticTransitionError> {
18232        let binding = self.prepared_model_binding(step, consumer_streams)?;
18233        if self.completed_prepared_transition_kind(step)? != SemanticTransitionKind::Proposal {
18234            return Err(publication_input_error(
18235                "completed action projection requires an original Proposal",
18236            ));
18237        }
18238        let successor = binding
18239            .1
18240            .ok_or(SemanticTransitionError::ObservationMismatch)?;
18241        let result_view = self
18242            .checked_prepared_step(step, false)?
18243            .prepared
18244            .as_ref()
18245            .expect("checked prepared owner")
18246            .result
18247            .view();
18248        let result = self.publication_read(result_view)?[0];
18249        let parent_header_view = self
18250            .checked_prepared_step(step, false)?
18251            .inputs
18252            .as_ref()
18253            .ok_or(SemanticTransitionError::ObservationMismatch)?
18254            .header
18255            .view();
18256        let parent_header = self.publication_read(parent_header_view)?[0];
18257        if (SemanticPublishedIdentity {
18258            instance: parent_header.instance,
18259            word: parent_header.publication_word,
18260            logical_digest: parent_header.logical_digest,
18261            state_digest: parent_header.state_digest,
18262        }) != binding.0
18263        {
18264            self.poisoned = true;
18265            return Err(SemanticTransitionError::ObservationMismatch);
18266        }
18267        let parent_semantic_digest = parent_header.semantic_digest;
18268        let world_root = self.prepared_parent_root_material(step, &parent_header)?;
18269        let world_root = SemanticCompletedStepWitnessMaterial {
18270            identity: Identity256::from_bytes(world_root.digest),
18271            bytes: world_root
18272                .encode()
18273                .map_err(SemanticTransitionError::Semantic)?,
18274        };
18275        let tape_index = self.completed_prepared_policy_tape(step)?;
18276        let bank = self.policy_tapes[tape_index]
18277            .prepared_bank
18278            .ok_or(SemanticTransitionError::ObservationMismatch)?;
18279        let (
18280            state_view,
18281            receipt_view,
18282            final_mask_view,
18283            active_set_view,
18284            pwl_cell_view,
18285            selected_score_vjp_view,
18286        ) = {
18287            let prepared = self
18288                .checked_prepared_step(step, false)?
18289                .prepared
18290                .as_ref()
18291                .expect("checked prepared owner");
18292            let branch = &prepared.branches[bank];
18293            let tape = &self.policy_tapes[tape_index];
18294            let policy = &tape.policy;
18295            (
18296                branch.state.view(),
18297                tape.receipts.view(),
18298                policy.final_masks.view(),
18299                policy.active_sets.view(),
18300                policy.pwl_cells.view(),
18301                policy.selected_score_vjps.view(),
18302            )
18303        };
18304        let state = self.publication_read(state_view)?[0];
18305        let receipts = self.publication_read(receipt_view)?;
18306        let final_masks = self.publication_read(final_mask_view)?;
18307        let active_sets = self.publication_read(active_set_view)?;
18308        let pwl_cells = self.publication_read(pwl_cell_view)?;
18309        let selected_score_vjps = self.publication_read(selected_score_vjp_view)?;
18310        let schema_generation = {
18311            let admission = self
18312                .graph
18313                .admission()
18314                .ok_or(SemanticTransitionError::ObservationMismatch)?;
18315            SemanticCompletedStepWitnessMaterial {
18316                identity: admission.schema_generation(),
18317                bytes: admission.schema_bytes().to_vec(),
18318            }
18319        };
18320        let catalogue = self.codebooks.binding;
18321        let batch_root = state.action_batch_root;
18322        let (
18323            task_identity,
18324            task_content,
18325            expected_truth,
18326            scoring,
18327            editable_program,
18328            objective_law,
18329            goal,
18330            priority_levels,
18331            task_result,
18332        ) = {
18333            let task = &self
18334                .task
18335                .as_ref()
18336                .ok_or(SemanticTransitionError::ObservationMismatch)?
18337                .0;
18338            (
18339                task.identity(),
18340                task.content_identity(),
18341                task.expected_truth(),
18342                task.spec().scoring,
18343                task.spec().program.editable_program().is_some(),
18344                task.objective_law,
18345                task.goal_witness()
18346                    .ok_or(SemanticTransitionError::ObservationMismatch)?,
18347                task.priority_levels().to_vec(),
18348                task.completed_result_material(),
18349            )
18350        };
18351        // A hard-constraint refusal follows completed queries. Scope and
18352        // program-resource refusals have no query result; their actual edit
18353        // costs and refusal penalties remain checked by the scoring law.
18354        let executed_slots = [
18355            true,
18356            matches!(state.task_evaluation.lane_refusal[0], 0 | 2),
18357            matches!(state.task_evaluation.lane_refusal[1], 0 | 2),
18358        ];
18359        let expected_query_count =
18360            executed_slots.iter().filter(|executed| **executed).count() as u64 * 3;
18361        let invalid_task_facts =
18362            state
18363                .task_evaluation
18364                .facts
18365                .iter()
18366                .zip(executed_slots)
18367                .any(|(facts, executed)| {
18368                    facts.correct.iter().any(|&value| value > 1)
18369                        || facts.g > 3
18370                        || facts.p > 1
18371                        || facts.eligible > 1
18372                        || if executed {
18373                            facts.truth.iter().any(|&value| value > 3)
18374                                || facts
18375                                    .truth
18376                                    .iter()
18377                                    .zip(expected_truth)
18378                                    .zip(facts.correct)
18379                                    .any(|((&truth, expected), correct)| {
18380                                        correct != u64::from(truth == expected as u64)
18381                                    })
18382                                || facts.g != facts.correct.iter().sum::<u64>()
18383                                || facts.p != u64::from(facts.correct == [1; 3])
18384                        } else {
18385                            facts.truth != [0; 3]
18386                                || facts.correct != [0; 3]
18387                                || facts.g != 0
18388                                || facts.p != 0
18389                                || facts.eligible != 0
18390                        }
18391                });
18392        let invalid_task_scoring = !validate_completed_task_scoring(
18393            scoring,
18394            editable_program,
18395            &priority_levels,
18396            &state.task_evaluation.facts,
18397            &state.work,
18398            state.task_evaluation.lane_refusal,
18399            state.task_evaluation.query_count,
18400            state.task_evaluation.winner,
18401            state.task_evaluation.return_value,
18402        );
18403        if result.refusal != 0
18404            || result.advanced != 1
18405            || state.status != 0
18406            || state.blocks != COMPONENT_COUNT as u64
18407            || receipts.len() != COMPONENT_COUNT
18408            || final_masks.len() != self.codebooks.input_cells
18409            || active_sets.len() != self.codebooks.input_cells
18410            || pwl_cells.len() != COMPONENT_COUNT
18411            || selected_score_vjps.len() != COMPONENT_COUNT
18412            || state.proposal.checked_add(1) != Some(state.next_proposal)
18413            || state.next_proposal != result.header.proposal
18414            || state.stream_serial != result.header.stream_serial
18415            || state.family_id as u64 != result.header.family_id
18416            || state.model_generation as u64 != result.header.model_generation
18417            || state.proposal > u32::MAX as u64
18418            || state.stream_serial >= 1 << 56
18419            || state.family_id > u8::MAX as u32
18420            || state.catalogue_generation > u32::MAX as u64
18421            || state.catalogue_generation != catalogue.generation
18422            || state.catalogue_digest != catalogue.digest
18423            || state.binding_digest != self.codebooks.binding.digest
18424            || self.codebooks.words[10..14]
18425                != identity_words(*schema_generation.identity.as_bytes())
18426            || state.task_evaluation.winner > 2
18427            || state.task_evaluation.query_count != expected_query_count
18428            || invalid_task_facts
18429            || invalid_task_scoring
18430            || state.task_evaluation.facts[state.task_evaluation.winner as usize].eligible != 1
18431            || state
18432                .task_evaluation
18433                .lane_refusal
18434                .iter()
18435                .any(|&code| code > 4)
18436            || (state.task_evaluation.winner != 0
18437                && state.task_evaluation.lane_refusal[state.task_evaluation.winner as usize - 1]
18438                    != 0)
18439            || state
18440                .task_evaluation
18441                .facts
18442                .iter()
18443                .any(|facts| facts.eligible > 1)
18444            || final_masks
18445                .iter()
18446                .chain(&active_sets)
18447                .any(|&value| value > 1)
18448            || state.actor_eligible > 1
18449            || state.action_batch.abi != 1
18450            || publication_action_batch_root(&state.action_batch) != batch_root
18451            || result.attempt.action_receipts_digest != batch_root
18452            || state.action_batch.proposal != state.proposal
18453            || state.action_batch.stream_serial != state.stream_serial
18454            || state.action_batch.family_id != u64::from(state.family_id)
18455            || state.action_batch.action_law_generation != state.catalogue_generation
18456            || state.action_batch.model_generation != u64::from(state.model_generation)
18457            || state.action_batch.actor_eligible != state.actor_eligible
18458            || state.action_batch.component_count != COMPONENT_COUNT as u64
18459            || state.action_batch.candidate_count != 3
18460            || state.action_batch.winner != state.task_evaluation.winner
18461            || state.action_batch.total_return_bits != state.task_evaluation.return_value as u64
18462            || state.action_batch.base_word != binding.0.word
18463            || state.action_batch.next_word != successor.word
18464            || state.action_batch.rng_base != state.proposal * COMPONENT_COUNT as u64
18465            || state.action_batch.rng_span != COMPONENT_COUNT as u64
18466            || state.action_batch.rng_successor != state.next_proposal * COMPONENT_COUNT as u64
18467            || state.action_batch.catalogue_digest != state.catalogue_digest
18468            || state.action_batch.semantic_receipts_digest
18469                != publication_semantic_receipts_digest(&state.semantic_receipts)
18470            || state.action_batch.base_logical_digest != binding.0.logical_digest
18471            || state.action_batch.execution_work != state.execution_work
18472            || [0usize, 3, 6]
18473                .into_iter()
18474                .enumerate()
18475                .any(|(candidate, receipt)| {
18476                    identity_words(*state.action_batch.candidate_roots[candidate].as_bytes())
18477                        != state.semantic_receipts[receipt][16..20]
18478                })
18479        {
18480            self.poisoned = true;
18481            return Err(SemanticTransitionError::ObservationMismatch);
18482        }
18483
18484        let owner = self.prepared_completed_action_witnesses(step, consumer_streams)?;
18485        let owner_identity = owner.identity;
18486        let initial_prefill = self.completed_initial_prefill_material(
18487            binding.0,
18488            parent_header.recovered_instance,
18489            parent_semantic_digest,
18490            parent_header.prefix_extent,
18491            state.model_generation as u64,
18492            task_identity,
18493            task_content,
18494            owner_identity,
18495        )?;
18496        let component_receipts_digest = publication_action_receipts_digest_bytes(
18497            &publication_abi_bytes(&self.codebooks.words),
18498            &receipts,
18499        )?;
18500        if state.action_batch.component_receipts_digest != component_receipts_digest {
18501            self.poisoned = true;
18502            return Err(SemanticTransitionError::ObservationMismatch);
18503        }
18504        let batch_receipt = SemanticCompletedStepWitnessMaterial {
18505            identity: batch_root,
18506            bytes: publication_abi_bytes(&[state.action_batch]),
18507        };
18508
18509        let slot_zero_admission = completed_receipt_material(
18510            owner_identity,
18511            b"slot-zero-admission",
18512            0,
18513            &state.semantic_receipts[0],
18514        );
18515        let lane_admissions: [SemanticCompletedStepWitnessMaterial; 2] =
18516            std::array::from_fn(|lane| {
18517                completed_receipt_material(
18518                    owner_identity,
18519                    b"lane-admission",
18520                    lane as u64,
18521                    &state.semantic_receipts[3 + lane * 3],
18522                )
18523            });
18524        let hard_decode_receipts: [[SemanticCompletedStepWitnessMaterial; 2]; 2] =
18525            std::array::from_fn(|lane| {
18526                std::array::from_fn(|slot| {
18527                    completed_receipt_material(
18528                        owner_identity,
18529                        b"hard-decode-receipt",
18530                        (lane * 2 + slot) as u64,
18531                        &state.semantic_receipts[1 + lane * 3 + slot],
18532                    )
18533                })
18534            });
18535
18536        let mut components = Vec::new();
18537        components
18538            .try_reserve_exact(COMPONENT_COUNT)
18539            .map_err(|error| runtime_error("completed action component reservation", error))?;
18540        for (ordinal, (&component, &receipt)) in
18541            self.codebooks.components.iter().zip(&receipts).enumerate()
18542        {
18543            let begin = component.offset as usize;
18544            let end = begin
18545                .checked_add(component.cardinality as usize)
18546                .filter(|&end| end <= final_masks.len())
18547                .ok_or(SemanticTransitionError::ObservationMismatch)?;
18548            let final_mask = &final_masks[begin..end];
18549            let active_set = &active_sets[begin..end];
18550            let pwl_cell = pwl_cells[ordinal];
18551            let selected_score_vjp = selected_score_vjps[ordinal];
18552            let block = (COMPONENT_COUNT as u64)
18553                .checked_mul(state.proposal)
18554                .and_then(|block| block.checked_add(ordinal as u64))
18555                .ok_or(SemanticTransitionError::ObservationMismatch)?;
18556            let packed = (state.stream_serial << 8) | state.family_id as u64;
18557            let expected_counter = [
18558                block as u32,
18559                (block >> 32) as u32,
18560                packed as u32,
18561                (packed >> 32) as u32,
18562            ];
18563            if receipt.ordinal as usize != ordinal
18564                || receipt.ordinal != component.ordinal
18565                || receipt.lane != component.lane
18566                || receipt.slot != component.slot
18567                || receipt.field != component.field
18568                || receipt.kind != component.kind
18569                || receipt.proposal != state.proposal
18570                || receipt.catalogue_generation != catalogue.generation
18571                || receipt.catalogue_digest != catalogue.digest
18572                || receipt.admission_binding != state.binding_digest
18573                || receipt.choice >= component.cardinality
18574                || receipt.legal_count == 0
18575                || receipt.active_count == 0
18576                || receipt.selected_rank >= receipt.legal_count
18577                || final_mask.iter().map(|&value| value as u32).sum::<u32>() != receipt.legal_count
18578                || active_set.iter().map(|&value| value as u32).sum::<u32>() != receipt.active_count
18579                || final_mask[receipt.choice as usize] != 1
18580                || active_set[receipt.choice as usize] != 1
18581                || receipt.cdf_start >= receipt.cdf_end
18582                || receipt.cdf_end > 1 << 63
18583                || receipt.mass != receipt.cdf_end - receipt.cdf_start
18584                || receipt.p == [0; 3]
18585                || receipt.q == [0; 3]
18586                || receipt.factor_denominator == [0; 3]
18587                || receipt.key != [state.catalogue_generation as u32, state.model_generation]
18588                || receipt.counter != expected_counter
18589                || pwl_cell.abi != 1
18590                || pwl_cell.ordinal != ordinal as u64
18591                || pwl_cell.cardinality != u64::from(component.cardinality)
18592                || pwl_cell.legal_count != u64::from(receipt.legal_count)
18593                || pwl_cell.active_count != u64::from(receipt.active_count)
18594                || pwl_cell.selected_rank != u64::from(receipt.selected_rank)
18595                || pwl_cell.singleton != u64::from(receipt.legal_count == 1)
18596                || pwl_cell.maximum_bits >> 32 != 0
18597                || !f32::from_bits(pwl_cell.maximum_bits as u32).is_finite()
18598                || pwl_cell.selected_probability != receipt.p
18599                || pwl_cell.probability_denominator != receipt.q
18600                || selected_score_vjp.abi != 1
18601                || selected_score_vjp.ordinal != ordinal as u64
18602                || selected_score_vjp.choice != u64::from(receipt.choice)
18603                || selected_score_vjp.active_count != u64::from(receipt.active_count)
18604                || selected_score_vjp.selected_active != 1
18605                || selected_score_vjp.singleton != u64::from(receipt.legal_count == 1)
18606                || selected_score_vjp.probability_numerator != receipt.p
18607                || selected_score_vjp.probability_denominator != receipt.q
18608            {
18609                self.poisoned = true;
18610                return Err(SemanticTransitionError::ObservationMismatch);
18611            }
18612
18613            let mut final_mask_bytes = Vec::new();
18614            material_u64(&mut final_mask_bytes, component.cardinality as u64);
18615            final_mask_bytes.extend_from_slice(final_mask);
18616            let final_mask_material = completed_action_child_material(
18617                owner_identity,
18618                b"final-mask",
18619                ordinal as u64,
18620                &final_mask_bytes,
18621            );
18622            let mut active_set_bytes = Vec::new();
18623            material_u64(&mut active_set_bytes, component.cardinality as u64);
18624            active_set_bytes.extend_from_slice(active_set);
18625            let active_set_material = completed_action_child_material(
18626                owner_identity,
18627                b"active-set",
18628                ordinal as u64,
18629                &active_set_bytes,
18630            );
18631            let mut receipt_bytes = Vec::new();
18632            encode_completed_component_receipt(&mut receipt_bytes, receipt);
18633            let component_receipt = completed_action_child_material(
18634                owner_identity,
18635                b"component-receipt",
18636                ordinal as u64,
18637                &receipt_bytes,
18638            );
18639            let pwl_cell = completed_action_child_material(
18640                owner_identity,
18641                b"pwl-cell",
18642                ordinal as u64,
18643                &publication_abi_bytes(&[pwl_cell]),
18644            );
18645
18646            let null = if component.is_text() {
18647                receipt.choice == TEXT_NULL as u32
18648            } else {
18649                component.field != 0
18650                    && receipt.choice == 0
18651                    && receipt.legal_count == 1
18652                    && receipt.active_count == 1
18653            };
18654            let vjp = completed_action_child_material(
18655                owner_identity,
18656                b"vjp",
18657                ordinal as u64,
18658                &publication_abi_bytes(&[selected_score_vjp]),
18659            );
18660            let hard_decode_receipt = (!component.is_text()).then(|| {
18661                hard_decode_receipts[component.lane as usize - 1][component.slot as usize].clone()
18662            });
18663            components.push(SemanticCompletedActionComponentMaterial {
18664                ordinal: receipt.ordinal,
18665                null,
18666                choice: receipt.choice,
18667                legal_count: receipt.legal_count,
18668                active_count: receipt.active_count,
18669                probability_numerator: receipt.p,
18670                probability_denominator: receipt.q,
18671                importance_denominator: receipt.factor_denominator,
18672                cumulative_mass_below: receipt.cumulative_mass_below,
18673                cdf_start: receipt.cdf_start,
18674                cdf_end: receipt.cdf_end,
18675                mass: receipt.mass,
18676                selected_rank: receipt.selected_rank,
18677                draw: receipt.draw,
18678                key: receipt.key,
18679                counter: receipt.counter,
18680                final_mask: final_mask_material,
18681                pwl_cell,
18682                active_set: active_set_material,
18683                vjp,
18684                component_receipt,
18685                hard_decode_receipt,
18686            });
18687        }
18688
18689        let lanes = std::array::from_fn(|lane| {
18690            let text_actions = (0..32)
18691                .filter_map(|slot| {
18692                    let receipt = receipts[lane * 68 + slot];
18693                    (receipt.choice != TEXT_NULL as u32).then_some((slot as u32, receipt.choice))
18694                })
18695                .collect();
18696            let mut edit_actions = [[0; 18]; 2];
18697            for slot in 0..2 {
18698                for field in 0..18 {
18699                    edit_actions[slot][field] = receipts[lane * 68 + 32 + slot * 18 + field].choice;
18700                }
18701            }
18702            SemanticCompletedActionLaneMaterial {
18703                text_actions,
18704                edit_actions,
18705                admitted: state.task_evaluation.lane_refusal[lane] == 0,
18706                refusal_reason: match state.task_evaluation.lane_refusal[lane] {
18707                    0 => None,
18708                    1 => Some(SemanticTaskRefusal::Scope.canonical_kind()),
18709                    2 => Some(SemanticTaskRefusal::HardConstraint.canonical_kind()),
18710                    3 => Some(SemanticTaskRefusal::FactCapacity.canonical_kind()),
18711                    4 => Some(SemanticTaskRefusal::FuelExhausted.canonical_kind()),
18712                    _ => unreachable!("validated lane refusal code"),
18713                },
18714                admission: lane_admissions[lane].clone(),
18715                hard_decode_receipts: hard_decode_receipts[lane].clone(),
18716            }
18717        });
18718
18719        let admission = self
18720            .graph
18721            .admission()
18722            .ok_or(SemanticTransitionError::ObservationMismatch)?;
18723        let task_program = self
18724            .task
18725            .as_ref()
18726            .and_then(|(task, _)| task.spec().program.editable_program())
18727            .cloned();
18728        if let Some(program) = task_program.as_ref() {
18729            let edits = std::array::from_fn(|lane| lanes[lane].edit_actions);
18730            if let Err(error) = validate_program_query_receipts(
18731                program,
18732                task_identity,
18733                &self.codebooks,
18734                &state,
18735                &edits,
18736            ) {
18737                self.poisoned = true;
18738                return Err(error);
18739            }
18740        }
18741        let mut theory_deltas = Vec::new();
18742        for (lane, lane_material) in lanes.iter().enumerate() {
18743            for slot in 0..2 {
18744                let begin = lane * 68 + 32 + slot * 18;
18745                let projected = completed_theory_delta_for_slot(
18746                    &self.codebooks,
18747                    admission,
18748                    task_program.as_ref(),
18749                    task_identity,
18750                    owner_identity,
18751                    parent_semantic_digest,
18752                    lane,
18753                    slot,
18754                    &lane_material.edit_actions[slot],
18755                    (slot == 1).then_some(&lane_material.edit_actions[0]),
18756                    &state.semantic_receipts[1 + lane * 3 + slot],
18757                    &state.semantic_receipts[3 + lane * 3],
18758                    &receipts[begin..begin + 18],
18759                    state.task_evaluation.lane_refusal[lane],
18760                );
18761                match projected {
18762                    Ok(Some(delta)) => theory_deltas.push(delta),
18763                    Ok(None) => {}
18764                    Err(error) => {
18765                        self.poisoned = true;
18766                        return Err(error);
18767                    }
18768                }
18769            }
18770        }
18771
18772        let base_truth = completed_task_truths(state.task_evaluation.facts[0])?;
18773        let lane_outcomes =
18774            std::array::from_fn(|lane| match state.task_evaluation.lane_refusal[lane] {
18775                0 => SemanticCompletedLaneOutcomeMaterial::Executed(
18776                    completed_task_truths(state.task_evaluation.facts[lane + 1])
18777                        .expect("validated executed task truth"),
18778                ),
18779                1 => SemanticCompletedLaneOutcomeMaterial::Refused(SemanticTaskRefusal::Scope),
18780                2 => SemanticCompletedLaneOutcomeMaterial::Refused(
18781                    SemanticTaskRefusal::HardConstraint,
18782                ),
18783                3 => {
18784                    SemanticCompletedLaneOutcomeMaterial::Refused(SemanticTaskRefusal::FactCapacity)
18785                }
18786                4 => SemanticCompletedLaneOutcomeMaterial::Refused(
18787                    SemanticTaskRefusal::FuelExhausted,
18788                ),
18789                _ => unreachable!("validated lane refusal code"),
18790            });
18791        let mut ground_bytes = Vec::new();
18792        ground_bytes.extend_from_slice(b"XLOG-COMPLETED-TASK-GROUND\0");
18793        material_u64(&mut ground_bytes, 3);
18794        let structural_cost = objective_law.structural_cost;
18795        ground_bytes.extend_from_slice(structural_cost.unit.as_bytes());
18796        material_u64(&mut ground_bytes, structural_cost.cap);
18797        ground_bytes.extend_from_slice(task_identity.as_bytes());
18798        for identity in [
18799            task_content.query,
18800            task_content.theory_program,
18801            task_content.result,
18802        ] {
18803            ground_bytes.extend_from_slice(identity.as_bytes());
18804        }
18805        for identity in [
18806            goal.semantic_root,
18807            goal.authority_root,
18808            goal.mandatory_links_root,
18809            goal.constraints_root,
18810        ] {
18811            ground_bytes.extend_from_slice(identity.as_bytes());
18812        }
18813        material_u64(&mut ground_bytes, goal.mandatory_link_count);
18814        material_u64(&mut ground_bytes, goal.constraint_count);
18815        material_u64(&mut ground_bytes, priority_levels.len() as u64);
18816        for level in &priority_levels {
18817            material_u64(&mut ground_bytes, level.goals.len() as u64);
18818            for goal in &level.goals {
18819                for value in [
18820                    u64::from(goal.query),
18821                    u64::from(goal.target_truth),
18822                    u64::from(goal.weight),
18823                ] {
18824                    material_u64(&mut ground_bytes, value);
18825                }
18826            }
18827        }
18828        encode_publication_identity(&mut ground_bytes, binding.0);
18829        for truth in expected_truth {
18830            material_u64(&mut ground_bytes, truth as u64);
18831        }
18832        for facts in state.task_evaluation.facts {
18833            encode_completed_task_facts(&mut ground_bytes, facts);
18834        }
18835        material_u64(&mut ground_bytes, state.task_evaluation.query_count);
18836        for refusal in state.task_evaluation.lane_refusal {
18837            material_u64(&mut ground_bytes, refusal);
18838        }
18839        for work in state.work {
18840            for value in [
18841                work.edit_commands,
18842                work.added_supports,
18843                work.defined_truth_changes,
18844            ] {
18845                material_u64(&mut ground_bytes, value);
18846            }
18847        }
18848        ground_bytes.extend_from_slice(batch_root.as_bytes());
18849        let task_ground = SemanticCompletedTaskGroundMaterial {
18850            witness: completed_action_child_material(
18851                owner_identity,
18852                b"task-ground",
18853                0,
18854                &ground_bytes,
18855            ),
18856            scoring_law: completed_action_child_material(
18857                owner_identity,
18858                b"task-scoring-law",
18859                0,
18860                &scoring.completed_law_bytes(task_identity, editable_program)?,
18861            ),
18862            scoring,
18863            return_bound: objective_law.return_bound,
18864            structural_cost,
18865            task_identity,
18866            content: task_content,
18867            goal,
18868            priority_levels,
18869            base: binding.0,
18870            expected_truth,
18871            facts: state.task_evaluation.facts,
18872            base_truth,
18873            lane_outcomes,
18874        };
18875
18876        let base_solves = state.task_evaluation.facts[0].eligible == 1
18877            && state.task_evaluation.facts[0].p == 1
18878            && state.task_evaluation.facts[0].correct == [1; 3];
18879        let decisive_lane = (0..2).find(|&lane| {
18880            let facts = state.task_evaluation.facts[lane + 1];
18881            state.task_evaluation.lane_refusal[lane] == 0
18882                && state.semantic_receipts[3 + lane * 3][0] == 0
18883                && state.work[lane].added_supports > 0
18884                && !base_solves
18885                && facts.eligible == 1
18886                && facts.p == 1
18887                && facts.correct == [1; 3]
18888        });
18889        let edit_solution = decisive_lane.map(|lane| {
18890            let component_begin = lane * 68 + 32;
18891            let component_end = lane * 68 + 68;
18892            let mut solution_bytes = Vec::new();
18893            solution_bytes.extend_from_slice(b"XLOG-COMPLETED-EDIT-SOLUTION\0");
18894            material_u64(&mut solution_bytes, 1);
18895            bind_completed_material(&mut solution_bytes, &task_ground.witness);
18896            solution_bytes.extend_from_slice(batch_root.as_bytes());
18897            material_u64(&mut solution_bytes, (lane + 1) as u64);
18898            material_u64(&mut solution_bytes, component_begin as u64);
18899            material_u64(&mut solution_bytes, component_end as u64);
18900            for value in [
18901                state.work[lane].edit_commands,
18902                state.work[lane].added_supports,
18903                state.work[lane].defined_truth_changes,
18904            ] {
18905                material_u64(&mut solution_bytes, value);
18906            }
18907            bind_completed_material(&mut solution_bytes, &lanes[lane].admission);
18908            for receipt in &lanes[lane].hard_decode_receipts {
18909                bind_completed_material(&mut solution_bytes, receipt);
18910            }
18911            for component in &components[lane * 68..(lane + 1) * 68] {
18912                for material in [
18913                    &component.component_receipt,
18914                    &component.final_mask,
18915                    &component.pwl_cell,
18916                    &component.active_set,
18917                    &component.vjp,
18918                ] {
18919                    bind_completed_material(&mut solution_bytes, material);
18920                }
18921            }
18922            SemanticCompletedEditSolutionMaterial {
18923                witness: completed_action_child_material(
18924                    owner_identity,
18925                    b"edit-solution",
18926                    lane as u64,
18927                    &solution_bytes,
18928                ),
18929                lane: (lane + 1) as u64,
18930                component_begin: component_begin as u64,
18931                component_end: component_end as u64,
18932                structural_delta: state.work[lane],
18933                resulting_state_receipt: lanes[lane].admission.clone(),
18934            }
18935        });
18936
18937        let mut attempt_bytes = Vec::new();
18938        material_u64(&mut attempt_bytes, result.attempt.abi);
18939        material_u64(&mut attempt_bytes, result.attempt.transition_kind);
18940        attempt_bytes.extend_from_slice(result.attempt.instance.as_bytes());
18941        material_u64(&mut attempt_bytes, result.attempt.base_word);
18942        material_u64(&mut attempt_bytes, result.attempt.next_word);
18943        for digest in [
18944            result.attempt.logical_digest,
18945            result.attempt.action_receipts_digest,
18946            result.attempt.semantic_receipts_digest,
18947            result.attempt.coverage_digest,
18948            result.attempt.replay_head_digest,
18949            result.attempt.intent_head_digest,
18950            result.attempt.acknowledgement_head_digest,
18951            result.attempt.previous_attempt_digest,
18952            result.attempt.receipt_digest,
18953        ] {
18954            attempt_bytes.extend_from_slice(digest.as_bytes());
18955        }
18956        let mut attempt_receipt =
18957            completed_action_child_material(owner_identity, b"attempt-receipt", 0, &attempt_bytes);
18958        attempt_receipt.identity = result.attempt.receipt_digest;
18959        let estimator_bound = if state.actor_eligible == 1 {
18960            self.prepared_completed_estimator_bound(
18961                step,
18962                bank,
18963                &parent_header,
18964                &task_ground.scoring_law,
18965                &batch_receipt,
18966                owner_identity,
18967            )?
18968        } else {
18969            None
18970        };
18971        let projection = SemanticCompletedActionProjectionMaterial {
18972            owner,
18973            initial_prefill,
18974            pre_action_checkpoint: self
18975                .checked_prepared_step(step, false)?
18976                .prepared
18977                .as_ref()
18978                .expect("checked prepared owner")
18979                .replay_custody
18980                .as_ref()
18981                .ok_or(SemanticTransitionError::ObservationMismatch)?
18982                .checkpoint_child
18983                .clone(),
18984            world_root: Some(world_root),
18985            schema_generation,
18986            action_law: SemanticActionCatalogue::current().completed_material(),
18987            edit_codebook: self.codebooks.completed_material(),
18988            roster: self.codebooks.completed_roster_material(),
18989            estimator_bound,
18990            predecessor_semantic_root_digest: parent_semantic_digest,
18991            predecessor: binding.0,
18992            successor,
18993            proposal: state.proposal,
18994            stream_serial: state.stream_serial,
18995            family_id: state.family_id as u64,
18996            action_law_generation: state.catalogue_generation,
18997            model_generation: state.model_generation as u64,
18998            winner: state.task_evaluation.winner,
18999            actor_eligible: state.actor_eligible == 1,
19000            total_return_bits: state.task_evaluation.return_value as u64,
19001            batch_root,
19002            batch_receipt,
19003            result: task_result,
19004            action_rng_base: completed_rng_material(
19005                owner_identity,
19006                0,
19007                state.model_generation as u64,
19008                state.stream_serial,
19009                state.family_id as u64,
19010                state.proposal,
19011            ),
19012            action_rng_successor: completed_rng_material(
19013                owner_identity,
19014                1,
19015                state.model_generation as u64,
19016                state.stream_serial,
19017                state.family_id as u64,
19018                state.next_proposal,
19019            ),
19020            base_logical_state: completed_logical_state_material(owner_identity, 0, binding.0),
19021            successor_logical_state: completed_logical_state_material(owner_identity, 1, successor),
19022            slot_zero_admission,
19023            lanes,
19024            theory_deltas,
19025            components,
19026            task_ground,
19027            edit_solution,
19028            attempt_receipt,
19029        };
19030        if self.prepared_model_binding(step, consumer_streams)? != binding {
19031            self.poisoned = true;
19032            return Err(SemanticTransitionError::ObservationMismatch);
19033        }
19034        Ok(projection)
19035    }
19036
19037    #[cfg(feature = "semantic-policy")]
19038    fn prepared_completed_estimator_bound(
19039        &mut self,
19040        step: &SemanticPreparedStep,
19041        bank: usize,
19042        parent: &PublicationHeader,
19043        scoring_law: &SemanticCompletedStepWitnessMaterial,
19044        batch_receipt: &SemanticCompletedStepWitnessMaterial,
19045        owner_identity: Identity256,
19046    ) -> Result<Option<SemanticCompletedStepWitnessMaterial>, SemanticTransitionError> {
19047        let tape_index = self.completed_prepared_policy_tape(step)?;
19048        let (original, storage, profile) = {
19049            let owner = self.checked_prepared_step(step, false)?;
19050            let inputs = owner.inputs.as_ref().expect("checked original inputs");
19051            let policy = &self.policy_tapes[tape_index].policy;
19052            let Some(profile) =
19053                inputs.views[bank].get(&(SemanticStateRole::RuntimeContract as u64, 0))
19054            else {
19055                return Err(SemanticTransitionError::ObservationMismatch);
19056            };
19057            (
19058                Arc::clone(&policy.text_binding),
19059                Arc::clone(&inputs.storage),
19060                profile.clone(),
19061            )
19062        };
19063        let Some(snapshot) = original.numerical_block_snapshot.as_ref() else {
19064            return Ok(None);
19065        };
19066        let contract = original
19067            .model_contract
19068            .as_ref()
19069            .ok_or(SemanticTransitionError::ObservationMismatch)?;
19070        let contract = self.publication_read(contract.clone())?;
19071        let layout = storage.contract_value.model_contract_layout;
19072        let roster = model_physical_parameter_roster(&contract, layout)?
19073            .ok_or(SemanticTransitionError::ObservationMismatch)?;
19074        let domain = self
19075            .task_training_domain()
19076            .ok_or(SemanticTransitionError::ObservationMismatch)?
19077            .identity();
19078        let bounds = self.publication_read(snapshot.view())?;
19079        if original.physical_blocks != roster.len() as u64
19080            || storage.physical_parameter_roster.as_ref() != Some(&roster)
19081            || roster.len().checked_mul(6) != Some(bounds.len())
19082            || u64::from_le_bytes(
19083                contract[layout.generation_offset as usize..layout.generation_offset as usize + 8]
19084                    .try_into()
19085                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
19086            ) != parent.model_generation
19087        {
19088            self.poisoned = true;
19089            return Err(SemanticTransitionError::ObservationMismatch);
19090        }
19091        // The successful completed action authenticates the original preflight.
19092        // Do not recompute its directed-rounding law on the host or read the
19093        // mutable producer tensor in place of this retained pre-draw snapshot.
19094        let profile = self.publication_read(profile)?;
19095        let mut bytes = b"XLOG-ESTIMATOR-BOUND\0".to_vec();
19096        material_u64(&mut bytes, 1);
19097        material_u64(&mut bytes, 1); // Native preflight law version.
19098        material_u64(&mut bytes, 100);
19099        material_u64(&mut bytes, bank as u64);
19100        encode_publication_identity(
19101            &mut bytes,
19102            SemanticPublishedIdentity {
19103                instance: parent.instance,
19104                word: parent.publication_word,
19105                logical_digest: parent.logical_digest,
19106                state_digest: parent.state_digest,
19107            },
19108        );
19109        material_u64(&mut bytes, parent.model_generation);
19110        bytes.extend_from_slice(parent.model_geometry_digest.as_bytes());
19111        bytes.extend_from_slice(parent.model_numerical_digest.as_bytes());
19112        bytes.extend_from_slice(domain.as_bytes());
19113        bind_completed_material(&mut bytes, scoring_law);
19114        bind_completed_material(&mut bytes, batch_receipt);
19115        for offset in [layout.schema_digest_offset, layout.identity_offset] {
19116            bytes.extend_from_slice(&contract[offset as usize..offset as usize + 32]);
19117        }
19118        for offset in [
19119            layout.schema_begin,
19120            layout.schema_bytes,
19121            layout.schema_digest_offset,
19122            layout.generation_offset,
19123            layout.numerical_digest_offset,
19124            layout.identity_offset,
19125        ] {
19126            material_u64(&mut bytes, offset);
19127        }
19128        for material in [&contract, &profile] {
19129            material_u64(&mut bytes, material.len() as u64);
19130            bytes.extend_from_slice(material);
19131        }
19132        material_u64(&mut bytes, roster.len() as u64);
19133        for (name, block) in roster.iter().zip(bounds.as_chunks::<6>().0) {
19134            material_u64(&mut bytes, name.len() as u64);
19135            bytes.extend_from_slice(name.as_bytes());
19136            for value in block {
19137                material_u64(&mut bytes, value.to_bits());
19138            }
19139        }
19140        Ok(Some(completed_action_child_material(
19141            owner_identity,
19142            b"estimator-bound",
19143            0,
19144            &bytes,
19145        )))
19146    }
19147
19148    #[cfg(feature = "semantic-policy")]
19149    fn prepared_completed_numerical_material(
19150        &mut self,
19151        step: &SemanticPreparedStep,
19152        consumer_streams: &[u64],
19153    ) -> Result<SemanticCompletedStepWitnessMaterial, SemanticTransitionError> {
19154        let binding = self.prepared_model_binding(step, consumer_streams)?;
19155        let work = self.prepared_completed_step_witnesses(step, consumer_streams)?;
19156        let action = self.prepared_completed_action_witnesses(step, consumer_streams)?;
19157        let launches = self
19158            .captured
19159            .as_ref()
19160            .ok_or(SemanticTransitionError::ObservationMismatch)?
19161            .captured_launch_bindings();
19162        if launches.is_empty()
19163            || launches
19164                .iter()
19165                .any(|launch| launch.artifact_sha256.is_none())
19166        {
19167            self.poisoned = true;
19168            return Err(SemanticTransitionError::ObservationMismatch);
19169        }
19170        let mut graph = Vec::new();
19171        graph.extend_from_slice(b"XLOG-CAPTURED-CUDA-LAUNCH-BINDINGS\0");
19172        material_u64(&mut graph, 1);
19173        material_u64(&mut graph, launches.len() as u64);
19174        for (ordinal, launch) in launches.iter().enumerate() {
19175            material_u64(&mut graph, ordinal as u64);
19176            material_u64(&mut graph, launch.module_name.len() as u64);
19177            graph.extend_from_slice(launch.module_name.as_bytes());
19178            material_u64(&mut graph, launch.artifact_name.len() as u64);
19179            graph.extend_from_slice(launch.artifact_name.as_bytes());
19180            graph.extend_from_slice(
19181                launch
19182                    .artifact_sha256
19183                    .as_ref()
19184                    .expect("checked captured artifact identity"),
19185            );
19186            material_u64(&mut graph, launch.function_name.len() as u64);
19187            graph.extend_from_slice(launch.function_name.as_bytes());
19188            for dimension in [launch.grid_dim.0, launch.grid_dim.1, launch.grid_dim.2] {
19189                material_u64(&mut graph, dimension as u64);
19190            }
19191            for dimension in [launch.block_dim.0, launch.block_dim.1, launch.block_dim.2] {
19192                material_u64(&mut graph, dimension as u64);
19193            }
19194            material_u64(&mut graph, launch.shared_mem_bytes as u64);
19195            material_u64(&mut graph, launch.parameter_count);
19196            material_u64(&mut graph, u64::from(launch.cooperative));
19197        }
19198
19199        let successor = binding
19200            .1
19201            .ok_or(SemanticTransitionError::ObservationMismatch)?;
19202        let mut owner_binding = Vec::new();
19203        owner_binding.extend_from_slice(b"xlog.completed-numerical-realization-owner.v2\0");
19204        encode_publication_identity(&mut owner_binding, binding.0);
19205        encode_publication_identity(&mut owner_binding, successor);
19206        owner_binding.extend_from_slice(work.identity.as_bytes());
19207        owner_binding.extend_from_slice(action.identity.as_bytes());
19208        let mut graph_hash = Sha256::new();
19209        graph_hash.update(&graph);
19210        owner_binding.extend_from_slice(&graph_hash.finalize());
19211        material_u64(&mut owner_binding, step.token);
19212        let mut owner_hash = Sha256::new();
19213        owner_hash.update(&owner_binding);
19214        let identity = Identity256::from_bytes(owner_hash.finalize().into());
19215
19216        let mut bytes = Vec::new();
19217        bytes.extend_from_slice(b"XLOG-COMPLETED-NUMERICAL-REALIZATION\0");
19218        material_u64(&mut bytes, 2);
19219        material_u64(&mut bytes, graph.len() as u64);
19220        bytes.extend_from_slice(&graph);
19221        material_u64(&mut bytes, work.bytes.len() as u64);
19222        bytes.extend_from_slice(&work.bytes);
19223        material_u64(&mut bytes, action.bytes.len() as u64);
19224        bytes.extend_from_slice(&action.bytes);
19225        if self.prepared_model_binding(step, consumer_streams)? != binding {
19226            self.poisoned = true;
19227            return Err(SemanticTransitionError::ObservationMismatch);
19228        }
19229        Ok(SemanticCompletedStepWitnessMaterial { identity, bytes })
19230    }
19231
19232    #[cfg(feature = "semantic-policy")]
19233    fn prepared_completed_logits_material(
19234        &mut self,
19235        step: &SemanticPreparedStep,
19236        consumer_streams: &[u64],
19237    ) -> Result<SemanticCompletedStepWitnessMaterial, SemanticTransitionError> {
19238        let binding = self.prepared_model_binding(step, consumer_streams)?;
19239        if self.completed_prepared_transition_kind(step)? != SemanticTransitionKind::Proposal {
19240            return Err(publication_input_error(
19241                "completed logits require an original Proposal",
19242            ));
19243        }
19244        let result_view = self.steps[&step.token]
19245            .prepared
19246            .as_ref()
19247            .expect("checked completed step")
19248            .result
19249            .view();
19250        let result = self.publication_read(result_view)?[0];
19251        let tape_index = self.completed_prepared_policy_tape(step)?;
19252        let (scores_view, layout) = {
19253            let policy = &self.policy_tapes[tape_index].policy;
19254            (policy.retained_scores.view(), policy.layout.clone())
19255        };
19256        let scores = self.publication_read(scores_view)?;
19257        if result.refusal != 0
19258            || result.advanced != 1
19259            || scores.len() != layout.retained_score_cells()
19260            || scores.iter().any(|value| !value.is_finite())
19261        {
19262            self.poisoned = true;
19263            return Err(SemanticTransitionError::ObservationMismatch);
19264        }
19265
19266        let successor = binding
19267            .1
19268            .ok_or(SemanticTransitionError::ObservationMismatch)?;
19269        let mut owner_binding = Vec::new();
19270        owner_binding.extend_from_slice(b"xlog.completed-logits-owner.v1\0");
19271        encode_publication_identity(&mut owner_binding, binding.0);
19272        encode_publication_identity(&mut owner_binding, successor);
19273        material_u64(&mut owner_binding, step.token);
19274        let mut owner_hash = Sha256::new();
19275        owner_hash.update(&owner_binding);
19276        let identity = Identity256::from_bytes(owner_hash.finalize().into());
19277
19278        let mut bytes = Vec::new();
19279        bytes.extend_from_slice(b"XLOG-COMPLETED-EDIT-LOGITS\0");
19280        material_u64(&mut bytes, 1);
19281        material_u64(&mut bytes, (4 * layout.fields.len()) as u64);
19282        let stride = layout.retained_score_stride();
19283        let mut next_offset = 0usize;
19284        let field_offsets = layout
19285            .fields
19286            .iter()
19287            .map(|field| {
19288                let offset = next_offset;
19289                next_offset += field.cardinality;
19290                offset
19291            })
19292            .collect::<Vec<_>>();
19293        for lane in 0..2usize {
19294            for slot in 0..2usize {
19295                for (field, field_layout) in layout.fields.iter().enumerate() {
19296                    let ordinal = lane * 68 + 32 + slot * 18 + field;
19297                    let offset = (lane * 2 + slot) * stride + field_offsets[field];
19298                    material_u64(&mut bytes, ordinal as u64);
19299                    material_u64(&mut bytes, lane as u64);
19300                    material_u64(&mut bytes, slot as u64);
19301                    material_u64(&mut bytes, field as u64);
19302                    material_u64(&mut bytes, field_layout.cardinality as u64);
19303                    for score in &scores[offset..offset + field_layout.cardinality] {
19304                        bytes.extend_from_slice(&score.to_bits().to_le_bytes());
19305                    }
19306                }
19307            }
19308        }
19309        if self.prepared_model_binding(step, consumer_streams)? != binding {
19310            self.poisoned = true;
19311            return Err(SemanticTransitionError::ObservationMismatch);
19312        }
19313        Ok(SemanticCompletedStepWitnessMaterial { identity, bytes })
19314    }
19315
19316    #[cfg(feature = "semantic-policy")]
19317    fn prepared_completed_random_material(
19318        &mut self,
19319        step: &SemanticPreparedStep,
19320        consumer_streams: &[u64],
19321    ) -> Result<SemanticCompletedStepWitnessMaterial, SemanticTransitionError> {
19322        let binding = self.prepared_model_binding(step, consumer_streams)?;
19323        let (header_view, result_view) = {
19324            let owner = self.checked_prepared_step(step, false)?;
19325            let inputs = owner
19326                .inputs
19327                .as_ref()
19328                .ok_or(SemanticTransitionError::ObservationMismatch)?;
19329            let prepared = owner.prepared.as_ref().expect("checked prepared owner");
19330            (inputs.header.view(), prepared.result.view())
19331        };
19332        let header = self.publication_read(header_view)?[0];
19333        let result = self.publication_read(result_view)?[0];
19334        let tape_index = self.completed_prepared_policy_tape(step)?;
19335        let receipt_view = self.policy_tapes[tape_index].receipts.view();
19336        let receipts = self.publication_read(receipt_view)?;
19337        if result.refusal != 0
19338            || result.advanced != 1
19339            || receipts.len() != COMPONENT_COUNT
19340            || receipts
19341                .iter()
19342                .any(|receipt| receipt.proposal != header.proposal)
19343        {
19344            self.poisoned = true;
19345            return Err(SemanticTransitionError::ObservationMismatch);
19346        }
19347
19348        let mut owner_binding = Vec::new();
19349        owner_binding.extend_from_slice(b"xlog.completed-random-state-owner.v1\0");
19350        encode_publication_identity(&mut owner_binding, binding.0);
19351        material_u64(&mut owner_binding, step.token);
19352        let mut owner_hash = Sha256::new();
19353        owner_hash.update(&owner_binding);
19354        let identity = Identity256::from_bytes(owner_hash.finalize().into());
19355
19356        let mut bytes = Vec::new();
19357        bytes.extend_from_slice(b"XLOG-COMPLETED-RANDOM-STATE\0");
19358        material_u64(&mut bytes, 1);
19359        material_u64(&mut bytes, header.model_generation);
19360        material_u64(&mut bytes, header.stream_serial);
19361        material_u64(&mut bytes, header.family_id);
19362        material_u64(&mut bytes, header.proposal);
19363        material_u64(&mut bytes, header.training_cursor);
19364        for value in header.training_rng {
19365            material_u64(&mut bytes, value);
19366        }
19367        material_u64(&mut bytes, receipts.len() as u64);
19368        for receipt in receipts {
19369            material_u64(&mut bytes, receipt.ordinal as u64);
19370            material_u64(&mut bytes, receipt.draw);
19371            for value in receipt.key {
19372                material_u64(&mut bytes, value as u64);
19373            }
19374            for value in receipt.counter {
19375                material_u64(&mut bytes, value as u64);
19376            }
19377            for value in receipt.random_words {
19378                material_u64(&mut bytes, value as u64);
19379            }
19380        }
19381        if self.prepared_model_binding(step, consumer_streams)? != binding {
19382            self.poisoned = true;
19383            return Err(SemanticTransitionError::ObservationMismatch);
19384        }
19385        Ok(SemanticCompletedStepWitnessMaterial { identity, bytes })
19386    }
19387
19388    #[cfg(feature = "semantic-policy")]
19389    pub fn prepared_completed_model_carrier(
19390        &mut self,
19391        step: &SemanticPreparedStep,
19392        consumer_streams: &[u64],
19393    ) -> Result<Option<SemanticCompletedModelCarrierMaterial>, SemanticTransitionError> {
19394        let binding = self.prepared_model_binding(step, consumer_streams)?;
19395        if self.completed_prepared_transition_kind(step)? != SemanticTransitionKind::Proposal
19396            || binding.1.is_none()
19397        {
19398            return Ok(None);
19399        }
19400        Ok(Some(SemanticCompletedModelCarrierMaterial {
19401            numerical_realization: self
19402                .prepared_completed_numerical_material(step, consumer_streams)?,
19403            logits: self.prepared_completed_logits_material(step, consumer_streams)?,
19404            random_state: self.prepared_completed_random_material(step, consumer_streams)?,
19405        }))
19406    }
19407
19408    /// The caller keeps the builder outside its Session lock while recording
19409    /// original producers. Retained resources own their preallocated pools.
19410    pub fn begin_prepared_segment(
19411        &mut self,
19412        resources: Vec<Arc<dyn Send + Sync>>,
19413    ) -> Result<(SemanticPreparedSegmentCapture, Arc<CudaStream>), SemanticTransitionError> {
19414        self.ensure_quiescent()?;
19415        let build = self
19416            .prepared_segment
19417            .as_ref()
19418            .ok_or(SemanticTransitionError::NotBound)?;
19419        if build.capturing || build.finished {
19420            return Err(publication_input_error(
19421                "prepared segment construction already began",
19422            ));
19423        }
19424        let external_floor = build.cold_capacity.external_floor()?;
19425        if build
19426            .cold_reservation
19427            .as_ref()
19428            .is_none_or(|reservation| reservation.remaining_bytes() != external_floor)
19429            || build.tokens.iter().any(|token| {
19430                self.steps
19431                    .get(token)
19432                    .and_then(|step| step.prepared.as_ref())
19433                    .is_none_or(|prepared| {
19434                        prepared.digests.is_none() || prepared.model_work.is_none()
19435                    })
19436            })
19437        {
19438            return Err(publication_input_error(
19439                "prepared segment lacks its complete frozen native cold allocation roster",
19440            ));
19441        }
19442        // Keep the actual pool/model allocations beyond graph retirement for
19443        // original late consumers. Unknown completion quarantines this same set.
19444        self.prepared_resources = resources.clone();
19445        let builder = crate::cuda_graph::ConditionalCudaGraphSequenceBuilder::new_retaining(
19446            &self.stream,
19447            resources,
19448        )
19449        .map_err(|error| runtime_error("bounded segment capture", error))?;
19450        let scope = Arc::clone(&build.scope);
19451        self.prepared_segment
19452            .as_mut()
19453            .expect("checked build")
19454            .capturing = true;
19455        self.graph.enter_transition();
19456        Ok((
19457            SemanticPreparedSegmentCapture { builder, scope },
19458            Arc::clone(&self.stream),
19459        ))
19460    }
19461
19462    fn check_prepared_content_stream(
19463        &self,
19464        step: &SemanticPreparedStep,
19465        consumer_stream: u64,
19466    ) -> Result<(), SemanticTransitionError> {
19467        self.checked_prepared_step(step, true)?;
19468        if dlpack_consumer_stream(consumer_stream)? != self.stream.cu_stream() {
19469            return Err(publication_input_error(
19470                "recorded content must use its original native capture stream",
19471            ));
19472        }
19473        if !self.steps[&step.token]
19474            .prepared
19475            .as_ref()
19476            .expect("prepared owner")
19477            .inputs_recorded
19478        {
19479            return Err(publication_input_error(
19480                "original step inputs must precede recorded content",
19481            ));
19482        }
19483        Ok(())
19484    }
19485
19486    /// Bind the original live model roster cold. Each execution later copies
19487    /// its expected seals from the actual device-acquired publication.
19488    pub fn bind_prepared_model_content(
19489        &mut self,
19490        step: &SemanticPreparedStep,
19491        bank: usize,
19492        tensors: Vec<SemanticTensorInput>,
19493        consumer_stream: u64,
19494    ) -> Result<SemanticTensorContentWitness, SemanticTransitionError> {
19495        self.check_prepared_cold(step)?;
19496        dlpack_consumer_stream(consumer_stream)?;
19497        if bank > 1 {
19498            return Err(publication_input_error(
19499                "prepared model content bank must be zero or one",
19500            ));
19501        }
19502        if self.steps[&step.token].content.iter().any(|content| {
19503            matches!(
19504                &content.seals,
19505                TensorContentSeals::Model(seals)
19506                    if seals.prepared.as_ref().is_some_and(|prepared| prepared.bank == bank)
19507            )
19508        }) {
19509            return Err(publication_input_error(
19510                "prepared model content binds once per original branch bank",
19511            ));
19512        }
19513        let storage = Arc::clone(self.publication.as_ref().expect("prepared publication"));
19514        let original = prepare_semantic_tensors(&self.provider, tensors)?;
19515        let directory = &storage.bank_templates[bank];
19516        let indices = model_content_ranges(
19517            directory,
19518            &storage.layouts,
19519            original.iter().map(|tensor| {
19520                (
19521                    tensor.layout,
19522                    tensor.logical_begin,
19523                    tensor.logical_end,
19524                    tensor.source.as_ref().map_or(0, DeviceMemoryView::len),
19525                )
19526            }),
19527        )?;
19528        let plan = model_content_copy_plan(
19529            directory,
19530            &indices,
19531            &storage
19532                .allocations
19533                .iter()
19534                .map(TrackedCudaSlice::len)
19535                .collect::<Vec<_>>(),
19536        )?;
19537        let values = original
19538            .iter()
19539            .flat_map(|tensor| [tensor.layout.role, tensor.layout.index])
19540            .collect::<Vec<_>>();
19541        let provider = Arc::clone(&self.provider);
19542        let allocated = (|| {
19543            let reservation = self
19544                .prepared_segment
19545                .as_mut()
19546                .expect("checked prepared segment")
19547                .cold_reservation
19548                .as_mut()
19549                .ok_or(SemanticTransitionError::ObservationMismatch)?;
19550            let seals = ModelContentSeals::allocate_reserved(&provider, &plan, reservation)?;
19551            let roster = reservation
19552                .alloc::<u64>(values.len())
19553                .map_err(|error| runtime_error("prepared model roster allocation", error))?;
19554            Ok::<_, SemanticTransitionError>((seals, roster))
19555        })();
19556        let (mut seals, roster) = match allocated {
19557            Ok(allocated) => allocated,
19558            Err(error) => {
19559                self.poisoned = true;
19560                return Err(error);
19561            }
19562        };
19563        #[cfg(feature = "semantic-policy")]
19564        let execute = self
19565            .provider
19566            .device()
19567            .inner()
19568            .get_func(
19569                "xlog_semantic_transition",
19570                "semantic_publication_model_seals",
19571            )
19572            .ok_or_else(|| {
19573                runtime_error("kernel lookup", "original model seal snapshot unavailable")
19574            })?;
19575        #[cfg(feature = "semantic-policy")]
19576        let reader = self.steps[&step.token]
19577            .prepared
19578            .as_ref()
19579            .expect("prepared lease")
19580            .reader
19581            .view();
19582        seals.prepared = Some(PreparedModelContentSeals {
19583            bank,
19584            #[cfg(feature = "semantic-policy")]
19585            storage,
19586            #[cfg(feature = "semantic-policy")]
19587            reader,
19588            roster,
19589            #[cfg(feature = "semantic-policy")]
19590            execute,
19591        });
19592        let owner = self.steps.get_mut(&step.token).expect("checked fixed step");
19593        owner.consumer_streams.insert(consumer_stream);
19594        let index = owner.content.len();
19595        owner.content.push(TensorContentBuffers {
19596            tensors: original,
19597            seals: TensorContentSeals::Model(seals),
19598            verification_inputs: Vec::new(),
19599        });
19600        let handle = SemanticTensorContentWitness {
19601            issuer: Arc::clone(&self.publication_issuer),
19602            reader_token: step.token,
19603            index,
19604            _witness: Arc::clone(&owner.content_witnesses),
19605        };
19606        let TensorContentSeals::Model(seals) = &owner.content[index].seals else {
19607            unreachable!("installed original model seals")
19608        };
19609        if let Err(error) = upload_publication(
19610            &self.provider,
19611            &values,
19612            &seals
19613                .prepared
19614                .as_ref()
19615                .expect("installed original roster")
19616                .roster,
19617        ) {
19618            self.poisoned = true;
19619            return Err(error);
19620        }
19621        Ok(handle)
19622    }
19623
19624    /// Authenticate and retain the original physical tensor rows used by one
19625    /// prepared bank's AccumulateGrad delivery owner. Every row must be the
19626    /// exact typed alias of that bank's roles 18 through 25.
19627    pub fn bind_prepared_gradient_delivery(
19628        &mut self,
19629        step: &SemanticPreparedStep,
19630        bank: usize,
19631        tensors: Vec<SemanticTensorInput>,
19632        consumer_stream: u64,
19633    ) -> Result<SemanticGradientDeliveryBinding, SemanticTransitionError> {
19634        self.bind_gradient_delivery(step, bank, tensors, consumer_stream, None)
19635    }
19636
19637    #[cfg(feature = "semantic-policy")]
19638    #[expect(
19639        clippy::too_many_arguments,
19640        reason = "gradient delivery retains the destination bank, original source reader and exact member invocation"
19641    )]
19642    pub fn bind_imported_group_gradient_delivery(
19643        &mut self,
19644        step: &SemanticPreparedStep,
19645        bank: usize,
19646        source: &SemanticTransitionSession,
19647        source_lease: &SemanticPublishedLease,
19648        invocation: SemanticRngBinding,
19649        member_ordinal: u64,
19650        member_row: &SemanticTrainingViewRow,
19651        tensors: Vec<SemanticTensorInput>,
19652        consumer_stream: u64,
19653    ) -> Result<SemanticGradientDeliveryBinding, SemanticTransitionError> {
19654        self.check_prepared_cold(step)?;
19655        if bank > 1 {
19656            return Err(publication_input_error(
19657                "group gradient delivery requires bank zero or one",
19658            ));
19659        }
19660        source.checked_reader(source_lease)?;
19661        if std::ptr::eq(self, source)
19662            || self.provider.device().ordinal() != source.provider.device().ordinal()
19663            || source.policy_tapes.iter().all(|tape| {
19664                tape.invocation != invocation
19665                    || tape.refusal.is_some()
19666                    || tape.prepared_bank.is_some()
19667                    || tape.policy.text_binding._witness.reader_token != source_lease.token
19668            })
19669        {
19670            return Err(publication_input_error(
19671                "group gradient delivery requires the original published policy on a distinct same-device Session",
19672            ));
19673        }
19674        let prepared = self.steps[&step.token]
19675            .prepared
19676            .as_ref()
19677            .expect("checked prepared step");
19678        if prepared.group_gradient_members[bank].contains(&member_ordinal) {
19679            return Err(publication_input_error(
19680                "original replay already owns this Update bank's physical gradient delivery",
19681            ));
19682        }
19683        let training = prepared.training_view.as_ref().ok_or_else(|| {
19684            publication_input_error(
19685                "group gradient delivery requires the frozen Update training view",
19686            )
19687        })?;
19688        if training
19689            .actor_group_member_index(member_ordinal, member_row)
19690            .is_err()
19691            && training
19692                .edit_group_member_index(member_ordinal, member_row)?
19693                .is_none()
19694        {
19695            return Err(publication_input_error(
19696                "original replay is absent from the frozen actor and edit groups",
19697            ));
19698        }
19699        let model = source.steps[&source_lease.token]
19700            .content
19701            .iter()
19702            .filter(|content| matches!(&content.seals, TensorContentSeals::Model(_)))
19703            .collect::<Vec<_>>();
19704        let [model] = model.as_slice() else {
19705            return Err(publication_input_error(
19706                "original replay has no unique authenticated physical model roster",
19707            ));
19708        };
19709        let binding = self.bind_gradient_delivery(
19710            step,
19711            bank,
19712            tensors,
19713            consumer_stream,
19714            Some(&model.tensors),
19715        )?;
19716        self.steps
19717            .get_mut(&step.token)
19718            .expect("checked prepared step")
19719            .prepared
19720            .as_mut()
19721            .expect("checked prepared owner")
19722            .group_gradient_members[bank]
19723            .insert(member_ordinal);
19724        Ok(binding)
19725    }
19726
19727    fn bind_gradient_delivery(
19728        &mut self,
19729        step: &SemanticPreparedStep,
19730        bank: usize,
19731        tensors: Vec<SemanticTensorInput>,
19732        consumer_stream: u64,
19733        foreign_model: Option<&[PreparedSemanticTensor]>,
19734    ) -> Result<SemanticGradientDeliveryBinding, SemanticTransitionError> {
19735        self.check_prepared_cold(step)?;
19736        dlpack_consumer_stream(consumer_stream)?;
19737        if bank > 1 || tensors.is_empty() {
19738            return Err(publication_input_error(
19739                "gradient delivery requires one prepared bank and a nonempty physical roster",
19740            ));
19741        }
19742        let imported = prepare_semantic_tensors(&self.provider, tensors)?;
19743        let inputs = self.steps[&step.token]
19744            .inputs
19745            .as_ref()
19746            .expect("fixed input owner");
19747        for tensor in &imported {
19748            let authentic = if let Some(model) =
19749                foreign_model.filter(|_| (18..=20).contains(&tensor.layout.role))
19750            {
19751                model
19752                    .iter()
19753                    .any(|original| same_tensor_content_owner(original, tensor))
19754            } else {
19755                inputs.owns_bank_model_tensor(bank, tensor)?
19756            };
19757            if !authentic {
19758                return Err(publication_input_error(
19759                    "gradient delivery input differs from its authenticated model or prepared bank tensor",
19760                ));
19761            }
19762        }
19763        if let Some(model) = foreign_model {
19764            let expected = model
19765                .iter()
19766                .filter(|tensor| (18..=20).contains(&tensor.layout.role))
19767                .map(|tensor| (tensor.layout.role, tensor.layout.index))
19768                .collect::<BTreeSet<_>>();
19769            let actual_rows = imported
19770                .iter()
19771                .filter(|tensor| (18..=20).contains(&tensor.layout.role));
19772            let actual = actual_rows
19773                .clone()
19774                .map(|tensor| (tensor.layout.role, tensor.layout.index))
19775                .collect::<BTreeSet<_>>();
19776            if actual != expected || actual_rows.count() != actual.len() {
19777                return Err(publication_input_error(
19778                    "group gradient delivery requires every original physical model leaf exactly once",
19779                ));
19780            }
19781        }
19782        for role in [
19783            SemanticStateRole::Gradients as u64,
19784            SemanticStateRole::GradientAccumulation as u64,
19785        ] {
19786            let expected = inputs
19787                .plans
19788                .iter()
19789                .filter(|input| input.role == role)
19790                .map(|input| (input.role, input.index))
19791                .collect::<BTreeSet<_>>();
19792            let actual_rows = imported.iter().filter(|tensor| tensor.layout.role == role);
19793            let actual = actual_rows
19794                .clone()
19795                .map(|tensor| (tensor.layout.role, tensor.layout.index))
19796                .collect::<BTreeSet<_>>();
19797            if actual != expected || actual_rows.count() != actual.len() {
19798                return Err(publication_input_error(
19799                    "gradient delivery requires every canonical gradient and presence input exactly once",
19800                ));
19801            }
19802        }
19803        let is_phase_mask = |layout: &SemanticTensorLayout| {
19804            layout.role == SemanticStateRole::TrainingSchedule as u64
19805                && layout.element_bytes == 1
19806                && layout.scalar_type == 8
19807                && layout.rank == 1
19808                && layout.logical_axis == u64::MAX
19809                && layout.dimensions == [3, 0, 0, 0]
19810                && layout.strides_bytes == [1, 0, 0, 0]
19811        };
19812        let expected_phase_masks = inputs
19813            .plans
19814            .iter()
19815            .filter(|input| is_phase_mask(&input.layout))
19816            .map(|input| (input.role, input.index))
19817            .collect::<BTreeSet<_>>();
19818        let actual_phase_mask_rows = imported
19819            .iter()
19820            .filter(|tensor| is_phase_mask(&tensor.layout));
19821        let actual_phase_masks = actual_phase_mask_rows
19822            .clone()
19823            .map(|tensor| (tensor.layout.role, tensor.layout.index))
19824            .collect::<BTreeSet<_>>();
19825        if actual_phase_masks != expected_phase_masks
19826            || actual_phase_mask_rows.count() != actual_phase_masks.len()
19827        {
19828            return Err(publication_input_error(
19829                "gradient delivery requires every canonical phase mask exactly once",
19830            ));
19831        }
19832        self.steps
19833            .get_mut(&step.token)
19834            .expect("checked gradient-delivery step")
19835            .consumer_streams
19836            .insert(consumer_stream);
19837        Ok(SemanticGradientDeliveryBinding { _tensors: imported })
19838    }
19839
19840    /// Attach actual original output owners as they are born during recording.
19841    /// Every private digest cell already exists; this operation cannot allocate
19842    /// device storage or establish a second baseline for native producer aliases.
19843    pub fn capture_prepared_tensor_content(
19844        &mut self,
19845        step: &SemanticPreparedStep,
19846        tensors: Vec<SemanticTensorInput>,
19847        consumer_stream: u64,
19848    ) -> Result<SemanticTensorContentWitness, SemanticTransitionError> {
19849        self.check_prepared_content_stream(step, consumer_stream)?;
19850        if tensors.is_empty() {
19851            return Err(publication_input_error(
19852                "original content requires an actual tensor roster",
19853            ));
19854        }
19855        let original = prepare_semantic_tensors(&self.provider, tensors)?;
19856        // Retain actual producers before validating coordinates or consuming
19857        // a reserved digest. Recording failure poisons this construction.
19858        let owner = self.steps.get_mut(&step.token).expect("checked fixed step");
19859        let index = owner.content.len();
19860        owner.content.push(TensorContentBuffers {
19861            tensors: original,
19862            seals: TensorContentSeals::Captured(Vec::new()),
19863            verification_inputs: Vec::new(),
19864        });
19865        let result = (|| {
19866            let owner = &self.steps[&step.token];
19867            let original = &owner.content[index].tensors;
19868            validate_content_coordinates(
19869                original
19870                    .iter()
19871                    .map(|tensor| (tensor.layout.role, tensor.layout.index)),
19872            )?;
19873            let mut digests = Vec::with_capacity(original.len());
19874            let prepared = owner.prepared.as_ref().expect("prepared content owner");
19875            let mut next = prepared.next_digest;
19876            for tensor in original {
19877                let mut native = owner.feedback_origin_digest(tensor)?;
19878                if native.is_none() {
19879                    let inputs = owner.inputs.as_ref().expect("fixed step inputs");
19880                    if inputs.owns_tensor(tensor)? {
19881                        native = Some(CapturedTensorDigest::Publication(Arc::clone(inputs)));
19882                    }
19883                }
19884                if let Some(native) = native {
19885                    digests.push(native);
19886                    continue;
19887                }
19888                for (&token, other) in &self.steps {
19889                    if token == step.token {
19890                        continue;
19891                    }
19892                    let other_input = match &other.inputs {
19893                        Some(inputs) => inputs.owns_tensor(tensor)?,
19894                        None => false,
19895                    };
19896                    if other.feedback_origin_digest(tensor)?.is_some() || other_input {
19897                        return Err(publication_input_error(
19898                            "original content belongs to another native prepared step",
19899                        ));
19900                    }
19901                }
19902                if tensor.native_allocation.is_some() {
19903                    return Err(publication_input_error("native allocation origin has no original content producer in this prepared step"));
19904                }
19905                tensor_content_range(
19906                    &tensor.layout,
19907                    tensor.logical_begin,
19908                    tensor.logical_end,
19909                    tensor.source.as_ref().map_or(0, DeviceMemoryView::len),
19910                )?;
19911                let cells = prepared
19912                    .digests
19913                    .as_ref()
19914                    .filter(|cells| next < cells.len() / 4)
19915                    .ok_or_else(|| {
19916                        publication_input_error(
19917                            "original tensor roster exceeds its cold native content reservation",
19918                        )
19919                    })?;
19920                let offset = next * 4;
19921                next += 1;
19922                digests.push(CapturedTensorDigest::Tensor {
19923                    cells: Arc::clone(cells),
19924                    offset,
19925                    producer_sealed: false,
19926                });
19927            }
19928            let owner = self.steps.get_mut(&step.token).expect("checked fixed step");
19929            owner
19930                .prepared
19931                .as_mut()
19932                .expect("prepared content owner")
19933                .next_digest = next;
19934            owner.content[index].seals = TensorContentSeals::Captured(digests);
19935            let handle = SemanticTensorContentWitness {
19936                issuer: Arc::clone(&self.publication_issuer),
19937                reader_token: step.token,
19938                index,
19939                _witness: Arc::clone(&owner.content_witnesses),
19940            };
19941            self.record_prepared_tensor_content(step, &handle, false)?;
19942            Ok(handle)
19943        })();
19944        if result.is_err() {
19945            self.poisoned = true;
19946        }
19947        result
19948    }
19949
19950    fn checked_prepared_content_witness(
19951        &self,
19952        step: &SemanticPreparedStep,
19953        witness: &SemanticTensorContentWitness,
19954    ) -> Result<(), SemanticTransitionError> {
19955        let owner = self.checked_prepared_step(step, false)?;
19956        if witness.reader_token != step.token
19957            || !Arc::ptr_eq(&witness.issuer, &self.publication_issuer)
19958            || !Arc::ptr_eq(&witness._witness, &owner.content_witnesses)
19959            || witness.index >= owner.content.len()
19960        {
19961            return Err(publication_input_error(
19962                "original content witness belongs to another native prepared step",
19963            ));
19964        }
19965        Ok(())
19966    }
19967
19968    pub fn record_prepared_tensor_content(
19969        &mut self,
19970        step: &SemanticPreparedStep,
19971        witness: &SemanticTensorContentWitness,
19972        verify: bool,
19973    ) -> Result<(), SemanticTransitionError> {
19974        self.checked_prepared_step(step, true)?;
19975        self.checked_prepared_content_witness(step, witness)?;
19976        let owner = &self.steps[&step.token];
19977        let execute = &owner
19978            .prepared
19979            .as_ref()
19980            .expect("prepared content owner")
19981            .witness;
19982        owner.content[witness.index].enqueue(&self.domain, &mut self.poisoned, execute, verify)
19983    }
19984
19985    /// Bind original forward outputs after their private witness was recorded.
19986    /// Numerical copies and native continuation preparation are recorded later
19987    /// by the complete step body; fresh authority bytes are uploaded at submit.
19988    /// Proposal blocks retain this bank's original model-content witness; their
19989    /// schema and identity come from its acquired device snapshot on each replay.
19990    pub fn bind_prepared_continuation(
19991        &mut self,
19992        step: &SemanticPreparedStep,
19993        bank: usize,
19994        continuation: SemanticContinuationInput,
19995        witness: &SemanticTensorContentWitness,
19996        model_content_witness: Option<&SemanticTensorContentWitness>,
19997        consumer_stream: u64,
19998    ) -> Result<(), SemanticTransitionError> {
19999        self.check_prepared_content_stream(step, consumer_stream)?;
20000        self.checked_prepared_content_witness(step, witness)?;
20001        if bank > 1 {
20002            return Err(publication_input_error(
20003                "prepared continuation bank must be zero or one",
20004            ));
20005        }
20006        if self.steps[&step.token]
20007            .prepared
20008            .as_ref()
20009            .expect("prepared owner")
20010            .branches[bank]
20011            .continuation
20012            .is_some()
20013        {
20014            return Err(publication_input_error(
20015                "original prepared continuation binds once",
20016            ));
20017        }
20018        if !matches!(
20019            self.steps[&step.token].content[witness.index].seals,
20020            TensorContentSeals::Captured(_)
20021        ) {
20022            return Err(publication_input_error(
20023                "continuation requires its original transient producer witness",
20024            ));
20025        }
20026        let storage = Arc::clone(self.publication.as_ref().expect("prepared publication"));
20027        let tensor_count = continuation.tensors.len();
20028        let capacity = storage
20029            .contract_value
20030            .feedback_capacity
20031            .checked_add(32)
20032            .ok_or(SemanticTransitionError::GenerationExhausted)?;
20033        let kind = self.prepared_transition_kind(step)?;
20034        let (physical_blocks, model_schema_digest, model_identity) =
20035            storage.continuation_block_contract(kind, &continuation, true)?;
20036        let model_contract = match (physical_blocks, model_content_witness) {
20037            (None, None) => None,
20038            (Some(_), Some(model_witness)) => {
20039                self.checked_prepared_content_witness(step, model_witness)?;
20040                let owner = &self.steps[&step.token];
20041                let TensorContentSeals::Model(seals) = &owner.content[model_witness.index].seals else {
20042                    return Err(publication_input_error(
20043                        "prepared block bounds require their original model-content witness",
20044                    ));
20045                };
20046                let prepared = owner.prepared.as_ref().expect("prepared model owner");
20047                if seals.prepared.as_ref().is_none_or(|source| source.bank != bank)
20048                    || prepared.model_content_recorded & (1 << bank) == 0
20049                {
20050                    return Err(publication_input_error(
20051                        "prepared block bounds require the same bank's recorded model-content guard",
20052                    ));
20053                }
20054                // This is the existing private role44 snapshot, refreshed by
20055                // the original acquire guard before this bank's model reads.
20056                // Retain its witness below; never read identities on the host.
20057                Some(seals.contract.view())
20058            }
20059            _ => return Err(publication_input_error(
20060                "prepared proposal blocks and their model-content witness must be supplied together",
20061            )),
20062        };
20063        let service_layouts =
20064            continuation_service_layouts(tensor_count, capacity, physical_blocks)?;
20065        let SemanticContinuationInput {
20066            mut tensors,
20067            authority_decisions,
20068            text_rows,
20069            text_row_count,
20070            selected_text,
20071            active_rows,
20072            active_row_count,
20073            numerical_admissibility,
20074            numerical_blocks,
20075            model_schema_digest: _,
20076            model_identity: _,
20077        } = continuation;
20078        if authority_decisions.is_empty() {
20079            return Err(publication_input_error(
20080                "continuation requires its original authority snapshot geometry",
20081            ));
20082        }
20083        let mut services = vec![
20084            text_rows,
20085            text_row_count,
20086            selected_text,
20087            active_rows,
20088            active_row_count,
20089            numerical_admissibility,
20090        ];
20091        services.extend(numerical_blocks);
20092        tensors.extend(
20093            services
20094                .into_iter()
20095                .zip(service_layouts)
20096                .map(|(tensor, layout)| SemanticTensorInput {
20097                    tensor,
20098                    layout,
20099                    logical_begin: 0,
20100                    logical_end: 0,
20101                    native_allocation: None,
20102                }),
20103        );
20104        self.verify_prepared_tensor_content(step, witness, tensors, consumer_stream)?;
20105        let numerical_block_snapshot = if physical_blocks.is_some() {
20106            let original =
20107                self.steps[&step.token].content[witness.index].tensors[tensor_count + 6].clone();
20108            let snapshot = Arc::clone(
20109                self.steps[&step.token]
20110                    .prepared
20111                    .as_ref()
20112                    .expect("prepared owner")
20113                    .branches[bank]
20114                    .numerical_block_snapshot
20115                    .as_ref()
20116                    .ok_or_else(|| {
20117                        publication_input_error(
20118                            "prepared block bounds lack their reserved native slot",
20119                        )
20120                    })?,
20121            );
20122            enqueue_numerical_block_snapshot(
20123                &self.domain,
20124                &mut self.poisoned,
20125                &original,
20126                &snapshot,
20127            )?;
20128            Some(snapshot)
20129        } else {
20130            None
20131        };
20132        let owner = &self.steps[&step.token];
20133        let original = &owner.content[witness.index].tensors;
20134        let services = original[tensor_count..].to_vec();
20135        if services.len() != 6 + usize::from(physical_blocks.is_some()) {
20136            return Err(publication_input_error(
20137                "continuation witness has the wrong original service roster",
20138            ));
20139        }
20140        let binding = Arc::new(TextBindingStorage {
20141            inputs: services,
20142            numerical_block_snapshot,
20143            model_contract,
20144            physical_blocks: physical_blocks.unwrap_or(0) as u64,
20145            model_schema_digest,
20146            model_identity,
20147            _witness: witness.clone(),
20148            _model_content_witness: model_content_witness.cloned(),
20149            consumer_stream,
20150            parent: TextBindingParent::Prepared(Arc::clone(
20151                owner.inputs.as_ref().expect("fixed inputs"),
20152            )),
20153        });
20154        let kind = self
20155            .prepared_segment
20156            .as_ref()
20157            .expect("prepared scope")
20158            .requested_kind(step, &self.publication_issuer)?;
20159        let (uploads, layouts) = prepare_continuation_payloads(
20160            &storage,
20161            &original[..tensor_count],
20162            &authority_decisions,
20163            kind,
20164        )?;
20165        let training_selection = match (
20166            kind,
20167            owner
20168                .prepared
20169                .as_ref()
20170                .expect("prepared selection owner")
20171                .training_view
20172                .as_ref(),
20173        ) {
20174            (SemanticTransitionKind::Update, Some(view)) => Some(view.selection()),
20175            (SemanticTransitionKind::Update, None) => {
20176                return Err(publication_input_error(
20177                    "prepared update continuation has no native training selection",
20178                ));
20179            }
20180            (_, None) => None,
20181            (_, Some(_)) => {
20182                return Err(publication_input_error(
20183                    "non-update continuation owns an unexpected training selection",
20184                ));
20185            }
20186        };
20187        let training_selection_pointer = training_selection
20188            .as_ref()
20189            .map_or(0, |selection| *selection.device_ptr());
20190        let model_update = owner
20191            .prepared
20192            .as_ref()
20193            .expect("prepared model update owner")
20194            .branches[bank]
20195            .model_update
20196            .as_ref()
20197            .map(PreparedModelUpdate::descriptor)
20198            .unwrap_or_default();
20199        let continuation = PreparedContinuation::prepare(
20200            &self.provider,
20201            storage,
20202            owner
20203                .prepared
20204                .as_ref()
20205                .expect("prepared lease")
20206                .reader
20207                .view(),
20208            Arc::clone(&binding),
20209            binding.continuation_inputs(
20210                kind,
20211                authority_decisions.len() as u64,
20212                training_selection_pointer,
20213                model_update,
20214            ),
20215            training_selection,
20216            &uploads,
20217            &layouts,
20218        )?;
20219        self.steps
20220            .get_mut(&step.token)
20221            .expect("checked prepared step")
20222            .prepared
20223            .as_mut()
20224            .expect("prepared owner")
20225            .branches[bank]
20226            .continuation = Some(continuation);
20227        #[cfg(feature = "semantic-policy")]
20228        self.attach_prepared_policy_continuation(step, bank)?;
20229        Ok(())
20230    }
20231
20232    /// Bind the complete producer-owned model backing after the original
20233    /// selected-view backward and optimizer update were recorded. The output is
20234    /// copied into the inactive neural bank by a prepared CUDA node before the
20235    /// sole publication transition commits its pointer and generation state.
20236    /// Record one baseline or candidate forward at the actual producer site.
20237    /// The receipt node is inserted into the active prepared bank capture and
20238    /// cannot be reconstructed later from handoff argument position.
20239    pub fn record_prepared_model_forward(
20240        &mut self,
20241        step: &SemanticPreparedStep,
20242        bank: usize,
20243        role: usize,
20244        logits: SemanticTensorInput,
20245        consumer_stream: u64,
20246    ) -> Result<SemanticModelForwardWitness, SemanticTransitionError> {
20247        self.check_prepared_content_stream(step, consumer_stream)?;
20248        if bank > 1 || role > 1 {
20249            return Err(publication_input_error(
20250                "prepared model forward bank and role must be zero or one",
20251            ));
20252        }
20253        if self.prepared_transition_kind(step)? != SemanticTransitionKind::Update {
20254            return Err(publication_input_error(
20255                "model forward receipts belong only to a prepared update",
20256            ));
20257        }
20258        let content = self.capture_prepared_tensor_content(step, vec![logits], consumer_stream)?;
20259        let storage = Arc::clone(self.publication.as_ref().expect("prepared publication"));
20260        let owner = self
20261            .steps
20262            .get_mut(&step.token)
20263            .expect("checked update step");
20264        let prepared = owner.prepared.as_mut().expect("prepared update owner");
20265        if prepared
20266            .model_work
20267            .as_ref()
20268            .is_none_or(|work| work.capture_bank != Some(bank))
20269        {
20270            return Err(publication_input_error(
20271                "model forward receipt requires the active producer bank capture",
20272            ));
20273        }
20274        let training_view = prepared.training_view.as_ref().ok_or_else(|| {
20275            publication_input_error("prepared update has no native training view")
20276        })?;
20277        let work_sequence = prepared
20278            .model_work
20279            .as_ref()
20280            .expect("active model work checked above")
20281            .next_slot()
20282            .map_err(publication_input_error)?;
20283        if work_sequence == 0 {
20284            return Err(publication_input_error(
20285                "model forward receipt requires recorded producer work before the logits occurrence",
20286            ));
20287        }
20288        let tensor = owner.content[content.index]
20289            .tensors
20290            .first()
20291            .ok_or(SemanticTransitionError::ObservationMismatch)?
20292            .clone();
20293        let layout = tensor.layout;
20294        let row_count = training_view.roster_rows().len() as u64;
20295        let capacity = training_view.capacity() as u64;
20296        if !matches!(
20297            (layout.scalar_type, layout.element_bytes),
20298            (4, 2) | (5, 2) | (6, 4)
20299        ) || layout.role != 0
20300            || layout.index != role as u64
20301            || layout.rank != 3
20302            || layout.logical_axis != u64::MAX
20303            || layout.dimensions[0] != row_count
20304            || layout.dimensions[1] != capacity
20305            || layout.dimensions[2] == 0
20306            || layout.dimensions[3] != 0
20307            || layout.strides_bytes[2] != layout.element_bytes
20308            || layout.strides_bytes[1]
20309                != layout.dimensions[2]
20310                    .checked_mul(layout.element_bytes)
20311                    .unwrap_or(0)
20312            || layout.strides_bytes[0]
20313                != layout.dimensions[1]
20314                    .checked_mul(layout.strides_bytes[1])
20315                    .unwrap_or(0)
20316            || layout.strides_bytes[3] != 0
20317            || tensor.logical_begin != 0
20318            || tensor.logical_end != 0
20319        {
20320            return Err(publication_input_error(
20321                "model forward logits must be aligned contiguous F16/BF16/F32 [rows,capacity,vocabulary] with its explicit role",
20322            ));
20323        }
20324        let TensorContentSeals::Captured(digests) = &owner.content[content.index].seals else {
20325            return Err(SemanticTransitionError::ObservationMismatch);
20326        };
20327        let (logits_digest, digest_cells) = captured_tensor_digest_pointer(digests, 0)?;
20328        let update = prepared.branches[bank]
20329            .model_update
20330            .as_mut()
20331            .ok_or_else(|| publication_input_error("prepared branch has no model update"))?;
20332        if update.forward_recorded != role as u8 {
20333            return Err(publication_input_error(
20334                "model forwards must be recorded exactly once in baseline then candidate order",
20335            ));
20336        }
20337        update.forward_recorded += 1;
20338        let receipt = update.forward_receipts.device_ptr_value()
20339            + (role * size_of::<ModelForwardReceipt>()) as u64;
20340        let inputs = ModelForwardReceiptInputs {
20341            control: storage.control.device_ptr_value(),
20342            lease: prepared.reader.device_ptr_value(),
20343            candidate_seals: update.forward_seals.device_ptr_value(),
20344            candidate_seal_count: update.forward_seals.len() as u64,
20345            role: role as u64,
20346            work_sequence: work_sequence as u64,
20347            logits: tensor.data,
20348            scalar_type: layout.scalar_type,
20349            row_count,
20350            capacity,
20351            vocabulary: layout.dimensions[2],
20352            row_stride_bytes: layout.strides_bytes[0],
20353            position_stride_bytes: layout.strides_bytes[1],
20354            vocabulary_stride_bytes: layout.strides_bytes[2],
20355            logits_digest,
20356            receipt,
20357        };
20358        let mut recorder = self.domain.new_strict_recorder();
20359        storage.record(&mut recorder);
20360        recorder.read(&prepared.reader);
20361        recorder.read(&update.forward_seals);
20362        recorder.read(digest_cells.as_ref());
20363        recorder.write(&update.forward_receipts);
20364        let result = enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
20365            // SAFETY: all pointers name retained native or producer-owned storage;
20366            // the launch is captured immediately after the actual forward.
20367            unsafe {
20368                update.forward_receipt.clone().launch_in(
20369                    enqueue,
20370                    LaunchConfig {
20371                        grid_dim: (1, 1, 1),
20372                        block_dim: (1, 1, 1),
20373                        shared_mem_bytes: 0,
20374                    },
20375                    (inputs,),
20376                )
20377            }
20378            .map_err(|error| XlogError::Kernel(error.to_string()))
20379        });
20380        if result.is_err() {
20381            self.poisoned = true;
20382        }
20383        result?;
20384        Ok(SemanticModelForwardWitness {
20385            issuer: Arc::clone(&self.publication_issuer),
20386            reader_token: step.token,
20387            bank,
20388            role,
20389            content,
20390        })
20391    }
20392
20393    #[expect(
20394        clippy::too_many_arguments,
20395        reason = "the native update handoff binds model geometry, numerical validity and canary evidence"
20396    )]
20397    pub fn bind_prepared_update_output(
20398        &mut self,
20399        step: &SemanticPreparedStep,
20400        bank: usize,
20401        mut model_memory: SemanticModelMemory,
20402        mut tensors: Vec<SemanticTensorInput>,
20403        admissibility: SemanticTensorInput,
20404        slab_backing: SemanticTensorInput,
20405        baseline_forward: &SemanticModelForwardWitness,
20406        candidate_forward: &SemanticModelForwardWitness,
20407        witness: &SemanticTensorContentWitness,
20408        consumer_stream: u64,
20409    ) -> Result<(), SemanticTransitionError> {
20410        self.check_prepared_content_stream(step, consumer_stream)?;
20411        self.checked_prepared_content_witness(step, witness)?;
20412        if bank > 1 {
20413            return Err(publication_input_error(
20414                "prepared model update bank must be zero or one",
20415            ));
20416        }
20417        for (role, forward) in [(0, baseline_forward), (1, candidate_forward)] {
20418            if !Arc::ptr_eq(&forward.issuer, &self.publication_issuer)
20419                || forward.reader_token != step.token
20420                || forward.bank != bank
20421                || forward.role != role
20422            {
20423                return Err(publication_input_error(
20424                    "model update requires exact producer-issued baseline and candidate forward witnesses",
20425                ));
20426            }
20427        }
20428        if self.prepared_transition_kind(step)? != SemanticTransitionKind::Update {
20429            return Err(publication_input_error(
20430                "model update output belongs only to a prepared update",
20431            ));
20432        }
20433        if self.steps[&step.token]
20434            .prepared
20435            .as_ref()
20436            .expect("prepared update owner")
20437            .branches[bank]
20438            .model_update
20439            .as_ref()
20440            .is_none_or(|update| update.output.is_some())
20441        {
20442            return Err(publication_input_error(
20443                "prepared update output binds exactly once",
20444            ));
20445        }
20446        if !matches!(
20447            self.steps[&step.token].content[witness.index].seals,
20448            TensorContentSeals::Captured(_)
20449        ) {
20450            return Err(publication_input_error(
20451                "model update output requires its original transient producer witness",
20452            ));
20453        }
20454        let allocation_count = model_memory.allocations.len();
20455        if allocation_count == 0 {
20456            return Err(publication_input_error(
20457                "model update output requires complete backing allocations",
20458            ));
20459        }
20460        let tensor_count = tensors.len();
20461        model_memory.allocations.append(&mut tensors);
20462        model_memory.allocations.push(admissibility);
20463        self.verify_prepared_tensor_content(
20464            step,
20465            witness,
20466            model_memory.allocations,
20467            consumer_stream,
20468        )?;
20469        let storage = Arc::clone(self.publication.as_ref().expect("prepared publication"));
20470        let outputs = self.steps[&step.token].content[witness.index]
20471            .tensors
20472            .clone();
20473        let (allocations, outputs) = outputs.split_at(allocation_count);
20474        let (tensors, update_metadata) = outputs.split_at(tensor_count);
20475        let [admissibility] = update_metadata else {
20476            return Err(publication_input_error(
20477                "model update output requires numerical admissibility",
20478            ));
20479        };
20480        let forward_tensor = |forward: &SemanticModelForwardWitness| {
20481            self.steps[&step.token].content[forward.content.index]
20482                .tensors
20483                .first()
20484                .cloned()
20485                .ok_or(SemanticTransitionError::ObservationMismatch)
20486        };
20487        let baseline_logits = forward_tensor(baseline_forward)?;
20488        let candidate_logits = forward_tensor(candidate_forward)?;
20489        let allocation_index = u64::try_from(allocation_count)
20490            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
20491        if admissibility.layout
20492            != (SemanticTensorLayout {
20493                role: 0,
20494                index: allocation_index,
20495                element_bytes: 1,
20496                scalar_type: 8,
20497                rank: 1,
20498                logical_axis: u64::MAX,
20499                dimensions: [1, 0, 0, 0],
20500                strides_bytes: [1, 0, 0, 0],
20501            })
20502            || admissibility.logical_begin != 0
20503            || admissibility.logical_end != 0
20504        {
20505            return Err(publication_input_error(
20506                "model update numerical admissibility must be Bool8[1]",
20507            ));
20508        }
20509        let training_view = self.steps[&step.token]
20510            .prepared
20511            .as_ref()
20512            .expect("prepared update owner")
20513            .training_view
20514            .as_ref()
20515            .ok_or_else(|| {
20516                publication_input_error("prepared update has no native training view")
20517            })?;
20518        let row_count = training_view.roster_rows().len() as u64;
20519        let capacity = training_view.capacity() as u64;
20520        let layout_valid = |tensor: &PreparedSemanticTensor, index: u64| {
20521            let layout = tensor.layout;
20522            matches!(layout.scalar_type, 4..=6)
20523                && matches!(
20524                    (layout.scalar_type, layout.element_bytes),
20525                    (4, 2) | (5, 2) | (6, 4)
20526                )
20527                && layout.role == 0
20528                && layout.index == index
20529                && layout.rank == 3
20530                && layout.logical_axis == u64::MAX
20531                && layout.dimensions[0] == row_count
20532                && layout.dimensions[1] == capacity
20533                && layout.dimensions[2] > 0
20534                && layout.dimensions[3] == 0
20535                && layout.strides_bytes[2] == layout.element_bytes
20536                && layout.strides_bytes[1]
20537                    == layout.dimensions[2]
20538                        .checked_mul(layout.element_bytes)
20539                        .unwrap_or(0)
20540                && layout.strides_bytes[0]
20541                    == layout.dimensions[1]
20542                        .checked_mul(layout.strides_bytes[1])
20543                        .unwrap_or(0)
20544                && layout.strides_bytes[3] == 0
20545                && tensor.logical_begin == 0
20546                && tensor.logical_end == 0
20547        };
20548        if !layout_valid(&baseline_logits, 0)
20549            || !layout_valid(&candidate_logits, 1)
20550            || baseline_logits.layout.scalar_type != candidate_logits.layout.scalar_type
20551            || baseline_logits.layout.dimensions != candidate_logits.layout.dimensions
20552            || baseline_logits.layout.strides_bytes != candidate_logits.layout.strides_bytes
20553        {
20554            return Err(publication_input_error(
20555                "model update canary logits must be aligned contiguous F16/BF16/F32 [rows,capacity,vocabulary]",
20556            ));
20557        }
20558        let geometry = prepare_model_memory(
20559            allocations,
20560            model_memory.storages,
20561            model_memory.views,
20562            tensors,
20563        )?;
20564        let actual_layouts = tensors
20565            .iter()
20566            .map(|tensor| ((tensor.layout.role, tensor.layout.index), tensor.layout))
20567            .collect::<BTreeMap<_, _>>();
20568        let expected_layouts = storage
20569            .layouts
20570            .iter()
20571            .filter(|((role, _), _)| matches!(role, 18..=25))
20572            .map(|(key, layout)| (*key, *layout))
20573            .collect::<BTreeMap<_, _>>();
20574        if geometry != storage.model_memory || actual_layouts != expected_layouts {
20575            return Err(publication_input_error(
20576                "model update output differs from the acquired model memory contract",
20577            ));
20578        }
20579        let TensorContentSeals::Captured(digests) =
20580            &self.steps[&step.token].content[witness.index].seals
20581        else {
20582            return Err(SemanticTransitionError::ObservationMismatch);
20583        };
20584        let mut forward_seal_values = Vec::new();
20585        let mut digest_cells = Vec::new();
20586        for range in storage.bank_templates[0]
20587            .iter()
20588            .filter(|range| matches!(range.role, 18..=25))
20589        {
20590            let tensor_index = tensors
20591                .iter()
20592                .position(|tensor| {
20593                    (tensor.layout.role, tensor.layout.index) == (range.role, range.index)
20594                })
20595                .ok_or(SemanticTransitionError::ObservationMismatch)?;
20596            let (allocation_index, _) = geometry.location(range.role, range.index)?;
20597            let (tensor_digest, tensor_cells) =
20598                captured_tensor_digest_pointer(digests, allocation_count + tensor_index)?;
20599            let (backing_digest, backing_cells) =
20600                captured_tensor_digest_pointer(digests, allocation_index)?;
20601            forward_seal_values.push(ModelForwardSealInput {
20602                role: range.role,
20603                index: range.index,
20604                tensor_digest,
20605                backing_digest,
20606            });
20607            digest_cells.push(tensor_cells);
20608            digest_cells.push(backing_cells);
20609        }
20610        let forward_digest = |forward: &SemanticModelForwardWitness| {
20611            let TensorContentSeals::Captured(digests) =
20612                &self.steps[&step.token].content[forward.content.index].seals
20613            else {
20614                return Err(SemanticTransitionError::ObservationMismatch);
20615            };
20616            captured_tensor_digest_pointer(digests, 0)
20617        };
20618        let (_, baseline_digest_cells) = forward_digest(baseline_forward)?;
20619        let (_, candidate_digest_cells) = forward_digest(candidate_forward)?;
20620        digest_cells.push(baseline_digest_cells);
20621        digest_cells.push(candidate_digest_cells);
20622        for allocation in allocations {
20623            let bytes = tensor_layout_bytes(&allocation.layout)?;
20624            if step_input_overlap(allocation.data, bytes, admissibility.data, 1)? {
20625                return Err(publication_input_error(
20626                    "model update numerical admissibility aliases an output allocation",
20627                ));
20628            }
20629            let logits_bytes = tensor_layout_bytes(&baseline_logits.layout)?;
20630            if step_input_overlap(allocation.data, bytes, baseline_logits.data, logits_bytes)?
20631                || step_input_overlap(allocation.data, bytes, candidate_logits.data, logits_bytes)?
20632            {
20633                return Err(publication_input_error(
20634                    "model update canary logits alias an output allocation",
20635                ));
20636            }
20637            for owned in &storage.allocations {
20638                if step_input_overlap(
20639                    allocation.data,
20640                    bytes,
20641                    owned.device_ptr_value(),
20642                    owned.len(),
20643                )? {
20644                    return Err(publication_input_error(
20645                        "model update output aliases native publication storage",
20646                    ));
20647                }
20648            }
20649        }
20650        let logits_bytes = tensor_layout_bytes(&baseline_logits.layout)?;
20651        if step_input_overlap(admissibility.data, 1, baseline_logits.data, logits_bytes)?
20652            || step_input_overlap(admissibility.data, 1, candidate_logits.data, logits_bytes)?
20653            || step_input_overlap(
20654                baseline_logits.data,
20655                logits_bytes,
20656                candidate_logits.data,
20657                logits_bytes,
20658            )?
20659        {
20660            return Err(publication_input_error(
20661                "model update canary logits alias one another or numerical admissibility",
20662            ));
20663        }
20664        for owned in &storage.allocations {
20665            if step_input_overlap(
20666                baseline_logits.data,
20667                logits_bytes,
20668                owned.device_ptr_value(),
20669                owned.len(),
20670            )? || step_input_overlap(
20671                candidate_logits.data,
20672                logits_bytes,
20673                owned.device_ptr_value(),
20674                owned.len(),
20675            )? {
20676                return Err(publication_input_error(
20677                    "model update canary logits alias native publication storage",
20678                ));
20679            }
20680        }
20681        let values = allocations
20682            .iter()
20683            .zip(&storage.model_slots)
20684            .zip(&geometry.allocation_bytes)
20685            .map(|((allocation, slots), &bytes)| ModelUpdateBinding {
20686                source: allocation.data,
20687                bytes,
20688                slots: [slots[0] as u64, slots[1] as u64],
20689            })
20690            .collect::<Vec<_>>();
20691        let retained_allocations = allocations.to_vec();
20692        let mut slab = prepare_semantic_tensors(&self.provider, vec![slab_backing])?;
20693        let slab = slab
20694            .pop()
20695            .ok_or(SemanticTransitionError::ObservationMismatch)?;
20696        if slab.layout.role != 0
20697            || slab.layout.index != 0
20698            || slab.layout.scalar_type != 1
20699            || slab.layout.element_bytes != 1
20700            || slab.layout.rank != 1
20701            || slab.layout.logical_axis != u64::MAX
20702            || slab.layout.dimensions[0] == 0
20703            || slab.layout.dimensions[1..] != [0, 0, 0]
20704            || slab.layout.strides_bytes != [1, 0, 0, 0]
20705            || slab.logical_begin != 0
20706            || slab.logical_end != 0
20707        {
20708            return Err(publication_input_error(
20709                "update slab must be its original contiguous CUDA UInt8 allocation",
20710            ));
20711        }
20712        #[cfg(feature = "semantic-policy")]
20713        let accounted_reserved_bytes = accounted_tensor_allocations(
20714            &outputs
20715                .iter()
20716                .chain([&baseline_logits, &candidate_logits])
20717                .collect::<Vec<_>>(),
20718            &slab,
20719        )?;
20720        #[cfg(feature = "semantic-policy")]
20721        let copy_bytes = values.iter().try_fold(0u64, |total, binding| {
20722            total
20723                .checked_add(binding.bytes)
20724                .ok_or(SemanticTransitionError::GenerationExhausted)
20725        })?;
20726        let prepared = self
20727            .steps
20728            .get_mut(&step.token)
20729            .expect("checked update step");
20730        let update = prepared
20731            .prepared
20732            .as_mut()
20733            .expect("prepared update owner")
20734            .branches[bank]
20735            .model_update
20736            .as_mut()
20737            .expect("prepared update binding allocation");
20738        if values.len() != update.bindings.len() {
20739            return Err(SemanticTransitionError::ObservationMismatch);
20740        }
20741        if forward_seal_values.len() != update.forward_seals.len() {
20742            return Err(SemanticTransitionError::ObservationMismatch);
20743        }
20744        if update.forward_recorded != 2 {
20745            return Err(publication_input_error(
20746                "model update output requires both producer-issued forward receipts",
20747            ));
20748        }
20749        update.output = Some(BoundModelUpdate {
20750            values,
20751            forward_seal_values,
20752            digest_cells,
20753            allocations: retained_allocations,
20754            admissibility: admissibility.clone(),
20755            baseline_logits,
20756            candidate_logits,
20757            _slab_backing: slab,
20758            #[cfg(feature = "semantic-policy")]
20759            accounted_reserved_bytes,
20760            #[cfg(feature = "semantic-policy")]
20761            copy_bytes,
20762            _witness: witness.clone(),
20763            _forward_witnesses: [baseline_forward.clone(), candidate_forward.clone()],
20764        });
20765        Ok(())
20766    }
20767
20768    pub fn verify_prepared_tensor_content(
20769        &mut self,
20770        step: &SemanticPreparedStep,
20771        witness: &SemanticTensorContentWitness,
20772        tensors: Vec<SemanticTensorInput>,
20773        consumer_stream: u64,
20774    ) -> Result<(), SemanticTransitionError> {
20775        self.checked_prepared_content_witness(step, witness)?;
20776        let build = self
20777            .prepared_segment
20778            .as_ref()
20779            .expect("checked prepared scope");
20780        let recorded = !build.finished;
20781        if recorded {
20782            self.check_prepared_content_stream(step, consumer_stream)?;
20783        } else if !build.completed
20784            || !self.steps[&step.token]
20785                .prepared
20786                .as_ref()
20787                .expect("prepared owner")
20788                .observed
20789        {
20790            return Err(publication_input_error(
20791                "retained content requires an actually completed prepared invocation",
20792            ));
20793        }
20794        let actual = prepare_semantic_tensors(&self.provider, tensors)?;
20795        let content = &mut self
20796            .steps
20797            .get_mut(&step.token)
20798            .expect("checked fixed step")
20799            .content[witness.index];
20800        let start = content.verification_inputs.len();
20801        content.verification_inputs.extend(actual);
20802        let actual = &content.verification_inputs[start..];
20803        if content.tensors.len() != actual.len()
20804            || content
20805                .tensors
20806                .iter()
20807                .zip(actual)
20808                .any(|(expected, actual)| !same_tensor_content_owner(expected, actual))
20809        {
20810            self.poisoned = true;
20811            return Err(publication_input_error("content verification requires the exact original tensor owners, layout and interval"));
20812        }
20813        if recorded {
20814            self.record_prepared_tensor_content(step, witness, true)
20815        } else {
20816            self.enqueue_content_witness(witness, consumer_stream, true)
20817        }
20818    }
20819
20820    pub fn record_prepared_step_admission(
20821        &mut self,
20822        step: &SemanticPreparedStep,
20823        conditional_handle: u64,
20824    ) -> Result<(), SemanticTransitionError> {
20825        self.checked_prepared_step(step, false)?;
20826        if conditional_handle == 0
20827            || !self
20828                .prepared_segment
20829                .as_ref()
20830                .expect("checked build")
20831                .capturing
20832        {
20833            return Err(publication_input_error(
20834                "step admission requires the actual conditional capture handle",
20835            ));
20836        }
20837        let requested_kind = self
20838            .prepared_segment
20839            .as_mut()
20840            .expect("checked build")
20841            .enter(step, &self.publication_issuer)?;
20842        let storage = self.publication.as_ref().expect("prepared publication");
20843        let prepared = self.steps[&step.token]
20844            .prepared
20845            .as_ref()
20846            .expect("prepared lease owner");
20847        let build = self
20848            .prepared_segment
20849            .as_ref()
20850            .expect("checked prepared scope");
20851        let previous = build.next.checked_sub(1).map(|index| {
20852            &self.steps[&build.tokens[index]]
20853                .prepared
20854                .as_ref()
20855                .expect("previous prepared step")
20856                .result
20857        });
20858        let mut recorder = self.domain.new_strict_recorder();
20859        storage.record(&mut recorder);
20860        recorder.write(&prepared.reader);
20861        if let Some(previous) = previous {
20862            recorder.read(previous);
20863        }
20864        let arguments = (
20865            storage.control.device_ptr_value(),
20866            prepared.reader.device_ptr_value(),
20867            requested_kind.code(),
20868            conditional_handle,
20869            previous.map_or(0, TrackedCudaSlice::device_ptr_value),
20870        );
20871        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
20872            // SAFETY: actual parent control and unique lease are fixed owners;
20873            // the graph issues this IF handle and the kernel writes every replay.
20874            unsafe {
20875                prepared.admit.clone().launch_in(
20876                    enqueue,
20877                    LaunchConfig {
20878                        grid_dim: (1, 1, 1),
20879                        block_dim: (1, 1, 1),
20880                        shared_mem_bytes: 0,
20881                    },
20882                    arguments,
20883                )
20884            }
20885            .map_err(|error| XlogError::Kernel(error.to_string()))
20886        })
20887    }
20888
20889    pub fn record_prepared_step_inputs(
20890        &mut self,
20891        step: &SemanticPreparedStep,
20892    ) -> Result<(), SemanticTransitionError> {
20893        self.checked_prepared_step(step, true)?;
20894        if self.steps[&step.token]
20895            .prepared
20896            .as_ref()
20897            .expect("prepared owner")
20898            .inputs_recorded
20899        {
20900            return Err(publication_input_error(
20901                "prepared input producer records exactly once",
20902            ));
20903        }
20904        // The complete original read roster is validated before feedback,
20905        // codebook, causal, or numerical consumers can read any parent value.
20906        let keys = self.prepared_range_keys(step)?;
20907        self.guard_prepared_content(step, &keys, self.stream.cu_stream() as usize as u64)?;
20908        let owner = &self.steps[&step.token];
20909        let descriptor = self.descriptor();
20910        owner
20911            .inputs
20912            .as_ref()
20913            .expect("fixed input owner")
20914            .enqueue(&self.domain, &mut self.poisoned)?;
20915        if let Some(custody) = &owner
20916            .prepared
20917            .as_ref()
20918            .expect("prepared owner")
20919            .replay_custody
20920        {
20921            custody.enqueue_parent(
20922                &self.domain,
20923                &mut self.poisoned,
20924                self.publication.as_ref().expect("prepared publication"),
20925                &owner.prepared.as_ref().expect("prepared owner").reader,
20926                &self.graph,
20927            )?;
20928        }
20929        owner.feedback[0].enqueue(
20930            &self.domain,
20931            &mut self.poisoned,
20932            &self.graph,
20933            self.publication.as_ref().expect("prepared publication"),
20934            &self
20935                .task
20936                .as_ref()
20937                .ok_or(SemanticTransitionError::InvalidTaskBank)?
20938                .1,
20939            &owner.prepared.as_ref().expect("prepared lease").reader,
20940            descriptor,
20941        )?;
20942        let selection = if let Some(selected) = owner
20943            .prepared
20944            .as_ref()
20945            .expect("prepared selection owner")
20946            .training_view
20947            .as_ref()
20948        {
20949            let selected_view = owner
20950                .inputs
20951                .as_ref()
20952                .expect("fixed input owner")
20953                .views
20954                .first()
20955                .expect("two publication input banks")
20956                .get(&(SemanticStateRole::TrainingView as u64, 0))
20957                .cloned()
20958                .ok_or_else(|| {
20959                    publication_input_error("prepared update has no acquired training-view input")
20960                })?;
20961            let coordinates = owner
20962                .inputs
20963                .as_ref()
20964                .expect("fixed input owner")
20965                .training_coordinates_view()?;
20966            selected.enqueue_device_selection(selected_view, coordinates)
20967        } else {
20968            Ok(())
20969        };
20970        if selection.is_err() {
20971            self.poisoned = true;
20972            return selection;
20973        }
20974        self.steps
20975            .get_mut(&step.token)
20976            .expect("checked step")
20977            .prepared
20978            .as_mut()
20979            .expect("prepared owner")
20980            .inputs_recorded = true;
20981        Ok(())
20982    }
20983
20984    fn record_prepared_step_kind_gate(
20985        &mut self,
20986        step: &SemanticPreparedStep,
20987        expected_kind: SemanticTransitionKind,
20988        conditional_handle: u64,
20989    ) -> Result<(), SemanticTransitionError> {
20990        self.checked_prepared_step(step, true)?;
20991        if conditional_handle == 0 {
20992            return Err(publication_input_error(
20993                "prepared kind gate requires the actual conditional capture handle",
20994            ));
20995        }
20996        let prepared = self.steps[&step.token]
20997            .prepared
20998            .as_ref()
20999            .expect("prepared lease owner");
21000        let mut recorder = self.domain.new_strict_recorder();
21001        recorder.read(&prepared.reader);
21002        let arguments = (
21003            prepared.reader.device_ptr_value(),
21004            expected_kind.code(),
21005            conditional_handle,
21006        );
21007        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
21008            // SAFETY: the lease and conditional handle belong to this original
21009            // prepared step and remain live throughout the captured segment.
21010            unsafe {
21011                prepared.kind_gate.clone().launch_in(
21012                    enqueue,
21013                    LaunchConfig {
21014                        grid_dim: (1, 1, 1),
21015                        block_dim: (1, 1, 1),
21016                        shared_mem_bytes: 0,
21017                    },
21018                    arguments,
21019                )
21020            }
21021            .map_err(|error| XlogError::Kernel(error.to_string()))
21022        })
21023    }
21024
21025    pub fn record_prepared_step_requested_bank_gate(
21026        &mut self,
21027        step: &SemanticPreparedStep,
21028        bank: usize,
21029        conditional_handle: u64,
21030    ) -> Result<(), SemanticTransitionError> {
21031        let expected = self.prepared_transition_kind(step)?;
21032        self.checked_prepared_step(step, true)?;
21033        if bank > 1 || conditional_handle == 0 {
21034            return Err(publication_input_error(
21035                "prepared bank gate requires bank zero or one and the actual conditional capture handle",
21036            ));
21037        }
21038        let prepared = self.steps[&step.token]
21039            .prepared
21040            .as_ref()
21041            .expect("prepared lease owner");
21042        let mut recorder = self.domain.new_strict_recorder();
21043        recorder.read(&prepared.reader);
21044        let arguments = (
21045            prepared.reader.device_ptr_value(),
21046            expected.code(),
21047            bank as u64,
21048            conditional_handle,
21049        );
21050        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
21051            // SAFETY: the device lease selects exactly one resident input bank;
21052            // this conditional exposes neither the lease nor its bank to host code.
21053            unsafe {
21054                prepared.kind_bank_gate.clone().launch_in(
21055                    enqueue,
21056                    LaunchConfig {
21057                        grid_dim: (1, 1, 1),
21058                        block_dim: (1, 1, 1),
21059                        shared_mem_bytes: 0,
21060                    },
21061                    arguments,
21062                )
21063            }
21064            .map_err(|error| XlogError::Kernel(error.to_string()))
21065        })
21066    }
21067
21068    #[cfg(feature = "semantic-policy")]
21069    pub fn begin_prepared_step_bank_capture(
21070        &mut self,
21071        step: &SemanticPreparedStep,
21072        bank: usize,
21073    ) -> Result<(), SemanticTransitionError> {
21074        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
21075        let prepared = self
21076            .steps
21077            .get_mut(&step.token)
21078            .expect("checked prepared bank step")
21079            .prepared
21080            .as_mut()
21081            .expect("prepared bank owner");
21082        let recorded = prepared.transition_recorded;
21083        let result = prepared
21084            .model_work
21085            .as_mut()
21086            .ok_or_else(|| publication_input_error("prepared bank requires original model work"))
21087            .and_then(|work| {
21088                work.begin_capture(bank, recorded)
21089                    .map_err(publication_input_error)
21090            });
21091        if result.is_err() {
21092            self.poisoned = true;
21093        }
21094        result
21095    }
21096
21097    #[cfg(feature = "semantic-policy")]
21098    /// Record the model seals owned by one prepared branch before its producer
21099    /// can enqueue model reads into that branch's conditional body.
21100    pub fn record_prepared_bank_model_content(
21101        &mut self,
21102        step: &SemanticPreparedStep,
21103        bank: usize,
21104    ) -> Result<(), SemanticTransitionError> {
21105        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
21106        if bank > 1 {
21107            return Err(publication_input_error(
21108                "prepared model content bank must be zero or one",
21109            ));
21110        }
21111        let owner = &self.steps[&step.token];
21112        let prepared = owner
21113            .prepared
21114            .as_ref()
21115            .expect("prepared model content owner");
21116        if prepared.model_content_recorded & (1 << bank) != 0 {
21117            return Err(publication_input_error(
21118                "prepared model content records once per bank branch",
21119            ));
21120        }
21121        let indices = owner
21122            .content
21123            .iter()
21124            .enumerate()
21125            .filter_map(|(index, content)| match &content.seals {
21126                TensorContentSeals::Model(seals)
21127                    if seals
21128                        .prepared
21129                        .as_ref()
21130                        .is_some_and(|source| source.bank == bank) =>
21131                {
21132                    Some(index)
21133                }
21134                _ => None,
21135            })
21136            .collect::<Vec<_>>();
21137        if indices.is_empty() {
21138            return Err(publication_input_error(
21139                "prepared branch has no original admitted model content",
21140            ));
21141        }
21142        for index in indices {
21143            let TensorContentSeals::Model(seals) = &self.steps[&step.token].content[index].seals
21144            else {
21145                return Err(SemanticTransitionError::ObservationMismatch);
21146            };
21147            seals.snapshot_prepared(&self.domain, &mut self.poisoned)?;
21148            let witness = SemanticTensorContentWitness {
21149                issuer: Arc::clone(&self.publication_issuer),
21150                reader_token: step.token,
21151                index,
21152                _witness: Arc::clone(&self.steps[&step.token].content_witnesses),
21153            };
21154            self.record_prepared_tensor_content(step, &witness, true)?;
21155        }
21156        self.steps
21157            .get_mut(&step.token)
21158            .expect("prepared model content owner")
21159            .prepared
21160            .as_mut()
21161            .expect("prepared model content storage")
21162            .model_content_recorded |= 1 << bank;
21163        Ok(())
21164    }
21165
21166    pub fn record_prepared_step_drain_gate(
21167        &mut self,
21168        step: &SemanticPreparedStep,
21169        conditional_handle: u64,
21170    ) -> Result<(), SemanticTransitionError> {
21171        self.record_prepared_step_kind_gate(step, SemanticTransitionKind::Drain, conditional_handle)
21172    }
21173
21174    pub fn record_prepared_step_active_gate(
21175        &mut self,
21176        step: &SemanticPreparedStep,
21177        conditional_handle: u64,
21178    ) -> Result<(), SemanticTransitionError> {
21179        self.checked_prepared_step(step, true)?;
21180        if conditional_handle == 0 {
21181            return Err(publication_input_error(
21182                "prepared release gate requires the actual conditional capture handle",
21183            ));
21184        }
21185        let prepared = self.steps[&step.token]
21186            .prepared
21187            .as_ref()
21188            .expect("prepared lease owner");
21189        let mut recorder = self.domain.new_strict_recorder();
21190        recorder.read(&prepared.reader);
21191        let arguments = (prepared.reader.device_ptr_value(), conditional_handle);
21192        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
21193            // SAFETY: this device predicate exposes no lease value to the host;
21194            // it only releases an actually acquired original step.
21195            unsafe {
21196                prepared.active_gate.clone().launch_in(
21197                    enqueue,
21198                    LaunchConfig {
21199                        grid_dim: (1, 1, 1),
21200                        block_dim: (1, 1, 1),
21201                        shared_mem_bytes: 0,
21202                    },
21203                    arguments,
21204                )
21205            }
21206            .map_err(|error| XlogError::Kernel(error.to_string()))
21207        })
21208    }
21209
21210    pub fn guard_prepared_content(
21211        &mut self,
21212        step: &SemanticPreparedStep,
21213        keys: &[(SemanticStateRole, u64)],
21214        consumer_stream: u64,
21215    ) -> Result<(), SemanticTransitionError> {
21216        self.checked_prepared_step(step, true)?;
21217        if dlpack_consumer_stream(consumer_stream)? != self.stream.cu_stream() || keys.is_empty() {
21218            return Err(publication_input_error(
21219                "prepared content guard requires original ranges on the native capture stream",
21220            ));
21221        }
21222        let storage = self.publication.as_ref().expect("prepared publication");
21223        let owner = &self.steps[&step.token];
21224        let prepared = owner.prepared.as_ref().expect("prepared lease");
21225        let mut distinct = BTreeSet::new();
21226        for &(role, index) in keys {
21227            if !distinct.insert((role as u64, index))
21228                || !storage.bank_templates[0]
21229                    .iter()
21230                    .any(|range| (range.role, range.index) == (role as u64, index))
21231            {
21232                return Err(publication_input_error(
21233                    "prepared guard names duplicate or undeclared original ranges",
21234                ));
21235            }
21236            let layout = if is_tensor_role(role as u64) {
21237                *storage
21238                    .layouts
21239                    .get(&(role as u64, index))
21240                    .ok_or(SemanticTransitionError::ObservationMismatch)?
21241            } else {
21242                SemanticTensorLayout::default()
21243            };
21244            storage.enqueue_content_guard(
21245                &self.domain,
21246                &mut self.poisoned,
21247                prepared.reader.view(),
21248                &prepared.content_guard,
21249                role as u64,
21250                index,
21251                layout,
21252            )?;
21253        }
21254        if prepared.inputs_recorded {
21255            owner
21256                .inputs
21257                .as_ref()
21258                .expect("fixed input owner")
21259                .verify(&self.domain, &mut self.poisoned)?;
21260            owner.feedback[0].content.enqueue(
21261                &self.domain,
21262                &mut self.poisoned,
21263                &prepared.witness,
21264                true,
21265            )?;
21266        }
21267        Ok(())
21268    }
21269
21270    pub fn record_prepared_step_release(
21271        &mut self,
21272        step: &SemanticPreparedStep,
21273    ) -> Result<(), SemanticTransitionError> {
21274        self.checked_prepared_step(step, true)?;
21275        let storage = self.publication.as_ref().expect("prepared publication");
21276        let prepared = self.steps[&step.token]
21277            .prepared
21278            .as_ref()
21279            .expect("prepared lease");
21280        if prepared.transition_recorded != PREPARED_TRANSITION_BANKS || !prepared.drain_recorded {
21281            return Err(publication_input_error(
21282                "release must follow this prepared step's complete native transition and drain branches",
21283            ));
21284        }
21285        let mut recorder = self.domain.new_strict_recorder();
21286        storage.record(&mut recorder);
21287        recorder.read_write(&prepared.reader);
21288        recorder.read(
21289            &self.steps[&step.token]
21290                .inputs
21291                .as_ref()
21292                .expect("fixed input owner")
21293                .header,
21294        );
21295        recorder.write(&prepared.result);
21296        if let Some(origin) = &prepared.training_origin {
21297            recorder.write(origin);
21298        }
21299        let arguments = (
21300            storage.control.device_ptr_value(),
21301            prepared.reader.device_ptr_value(),
21302        );
21303        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
21304            // SAFETY: save the actual successor or refusal while the exact
21305            // acquired parent and current bank still belong to this step.
21306            unsafe {
21307                prepared.result_kernel.clone().launch_in(
21308                    enqueue,
21309                    LaunchConfig {
21310                        grid_dim: (1, 1, 1),
21311                        block_dim: (1, 1, 1),
21312                        shared_mem_bytes: 0,
21313                    },
21314                    (
21315                        storage.control.device_ptr_value(),
21316                        prepared.reader.device_ptr_value(),
21317                        prepared.result.device_ptr_value(),
21318                        self.steps[&step.token]
21319                            .inputs
21320                            .as_ref()
21321                            .expect("fixed input owner")
21322                            .header
21323                            .device_ptr_value(),
21324                        prepared
21325                            .training_origin
21326                            .as_ref()
21327                            .map_or(0, |origin| *origin.device_ptr()),
21328                    ),
21329                )
21330            }
21331            .map_err(|error| XlogError::Kernel(error.to_string()))?;
21332            // SAFETY: release follows this step's body in the actual IF graph;
21333            // the native lease remains owned for all later retained witnesses.
21334            unsafe {
21335                prepared.release.clone().launch_in(
21336                    enqueue,
21337                    LaunchConfig {
21338                        grid_dim: (1, 1, 1),
21339                        block_dim: (1, 1, 1),
21340                        shared_mem_bytes: 0,
21341                    },
21342                    arguments,
21343                )
21344            }
21345            .map_err(|error| XlogError::Kernel(error.to_string()))
21346        })?;
21347        self.prepared_segment
21348            .as_mut()
21349            .expect("checked build")
21350            .leave(step, &self.publication_issuer)
21351    }
21352
21353    pub fn finish_prepared_segment(
21354        &mut self,
21355        executable: &mut Option<SemanticPreparedExecutable>,
21356    ) -> Result<(), SemanticTransitionError> {
21357        self.ensure_quiescent()?;
21358        let build = self
21359            .prepared_segment
21360            .as_mut()
21361            .ok_or(SemanticTransitionError::NotBound)?;
21362        if self.captured.is_some()
21363            || executable
21364                .as_ref()
21365                .is_none_or(|executable| !Arc::ptr_eq(&executable.scope, &build.scope))
21366        {
21367            return Err(publication_input_error(
21368                "executable differs from the original native segment construction",
21369            ));
21370        }
21371        #[cfg(feature = "semantic-policy")]
21372        for token in &build.tokens {
21373            let prepared = self.steps[token]
21374                .prepared
21375                .as_ref()
21376                .expect("original prepared owner");
21377            if prepared
21378                .training_view
21379                .as_ref()
21380                .is_some_and(|view| view.actor_group_member_count() > 1)
21381                && prepared.group_critic_recorded != 0b11
21382            {
21383                return Err(publication_input_error(
21384                    "multi-member Update requires the complete frozen group critic in both banks",
21385                ));
21386            }
21387            if (0..2).any(|bank| {
21388                prepared.group_imported_vjp_members[bank] != prepared.group_gradient_members[bank]
21389            }) {
21390                return Err(publication_input_error(
21391                    "every imported group VJP requires its original physical gradient delivery in the same bank",
21392                ));
21393            }
21394        }
21395        build.finish()?;
21396        // Upload only immutable first-recording geometry, after capture and
21397        // before any graph launch. The original step retains this allocation.
21398        for token in &build.tokens {
21399            let prepared = self.steps[token]
21400                .prepared
21401                .as_ref()
21402                .expect("original prepared owner");
21403            let work = prepared.model_work.as_ref().ok_or_else(|| {
21404                publication_input_error("prepared body has no frozen original model work")
21405            })?;
21406            if work.recording.frozen_bound().is_none() {
21407                return Err(publication_input_error(
21408                    "original model work was not frozen by its transition",
21409                ));
21410            }
21411            if let Some(custody) = &prepared.replay_custody {
21412                work.recording
21413                    .frozen_bound()
21414                    .expect("checked frozen original work")
21415                    .checked_add(custody.copy_work_bound()?)
21416                    .ok_or(SemanticTransitionError::GenerationExhausted)?;
21417            }
21418            let mut destination = work.device.view().slice(..work.recording.events().len());
21419            self.provider
21420                .htod_launch_metadata_sync_copy_into(work.recording.events(), &mut destination)
21421                .map_err(|error| runtime_error("original model work cold upload", error))?;
21422            for branch in &prepared.branches {
21423                if let Some(update) = &branch.model_update {
21424                    let output = update.output.as_ref().ok_or_else(|| {
21425                        publication_input_error(
21426                            "prepared update has no branch-owned model output binding",
21427                        )
21428                    })?;
21429                    let mut destination = update.bindings.view();
21430                    self.provider
21431                        .htod_launch_metadata_sync_copy_into(&output.values, &mut destination)
21432                        .map_err(|error| {
21433                            runtime_error("model update binding cold upload", error)
21434                        })?;
21435                    let mut forward_seals = update.forward_seals.view();
21436                    self.provider
21437                        .htod_launch_metadata_sync_copy_into(
21438                            &output.forward_seal_values,
21439                            &mut forward_seals,
21440                        )
21441                        .map_err(|error| runtime_error("model forward seal cold upload", error))?;
21442                }
21443            }
21444        }
21445        executable
21446            .as_ref()
21447            .expect("checked authentic executable")
21448            .graph
21449            .upload_cold(&self.stream)
21450            .map_err(|error| runtime_error("prepared graph cold upload", error))?;
21451        // Failure leaves the actual graph in the caller's owner. No graph
21452        // destructor or driver completion can run under its Session mutex.
21453        self.captured = Some(
21454            executable
21455                .take()
21456                .expect("checked authentic executable")
21457                .graph,
21458        );
21459        Ok(())
21460    }
21461
21462    /// Detach the completed executable so the caller can destroy it outside its
21463    /// Session mutex. The actual allocation resources remain Session-owned until
21464    /// every original prepared step and its final consumers have retired.
21465    pub fn take_prepared_executable_for_retirement(
21466        &mut self,
21467    ) -> Result<Option<CapturedCudaGraph>, SemanticTransitionError> {
21468        if self
21469            .prepared_segment
21470            .as_ref()
21471            .is_none_or(|build| !build.completed)
21472        {
21473            return Err(publication_input_error(
21474                "prepared executable retirement requires known actual completion",
21475            ));
21476        }
21477        Ok(self.captured.take())
21478    }
21479
21480    /// Return the original pool/model owners only after all joined step owners
21481    /// and their imported aliases are gone. Drop the returned owners unlocked.
21482    pub fn take_prepared_resources_for_retirement(
21483        &mut self,
21484    ) -> Result<Vec<Arc<dyn Send + Sync>>, SemanticTransitionError> {
21485        let build = self
21486            .prepared_segment
21487            .as_ref()
21488            .ok_or(SemanticTransitionError::NotBound)?;
21489        if !build.completed
21490            || self.captured.is_some()
21491            || build
21492                .tokens
21493                .iter()
21494                .any(|token| self.steps.contains_key(token))
21495        {
21496            return Err(publication_input_error(
21497                "original prepared resources still own an executable or retained step",
21498            ));
21499        }
21500        let resources = std::mem::take(&mut self.prepared_resources);
21501        self.prepared_segment = None;
21502        Ok(resources)
21503    }
21504
21505    #[cfg(feature = "semantic-policy")]
21506    fn prepared_segment_recorder(&self) -> Result<LaunchRecorder, SemanticTransitionError> {
21507        let build = self
21508            .prepared_segment
21509            .as_ref()
21510            .ok_or(SemanticTransitionError::NotBound)?;
21511        // Shared arena, scratch, immutable catalogue and the actual feedback
21512        // descriptor owners remain part of this same strict recorded launch.
21513        let mut recorder = self.kernel_recorder();
21514        self.publication
21515            .as_ref()
21516            .ok_or(SemanticTransitionError::NotBound)?
21517            .record(&mut recorder);
21518        for token in &build.tokens {
21519            let owner = self
21520                .steps
21521                .get(token)
21522                .ok_or(SemanticTransitionError::ObservationMismatch)?;
21523            let prepared = owner
21524                .prepared
21525                .as_ref()
21526                .ok_or(SemanticTransitionError::ObservationMismatch)?;
21527            recorder.read_write(&prepared.reader);
21528            recorder.write(&prepared.result);
21529            if let Some(custody) = &prepared.replay_custody {
21530                custody.record(&mut recorder);
21531            }
21532            if let Some(work) = &prepared.model_work {
21533                recorder.read(&work.device);
21534                recorder.read_write(&work.actual);
21535            }
21536            if let Some(digests) = &prepared.digests {
21537                recorder.read_write(digests.as_ref());
21538            }
21539            let inputs = owner
21540                .inputs
21541                .as_ref()
21542                .ok_or(SemanticTransitionError::ObservationMismatch)?;
21543            for bindings in &inputs.bindings {
21544                recorder.read(bindings);
21545            }
21546            recorder.write(&inputs.header);
21547            recorder.write(&inputs.source);
21548            recorder.write(&inputs.ranges);
21549            recorder.write(&inputs.metadata_digests);
21550            for allocation in &inputs.private {
21551                recorder.write(allocation);
21552            }
21553            for bank in &inputs.views {
21554                for view in bank.values() {
21555                    recorder.read_write(view);
21556                }
21557            }
21558            for feedback in &owner.feedback {
21559                recorder.write(&feedback.status);
21560            }
21561            for content in owner
21562                .content
21563                .iter()
21564                .chain(owner.feedback.iter().map(|feedback| &feedback.content))
21565            {
21566                for tensor in content.tensors.iter().chain(&content.verification_inputs) {
21567                    if let Some(source) = &tensor.source {
21568                        recorder.read_write(source);
21569                    }
21570                }
21571                match &content.seals {
21572                    TensorContentSeals::Captured(digests) => {
21573                        for digest in digests {
21574                            if let CapturedTensorDigest::Tensor { cells, .. } = digest {
21575                                recorder.read_write(cells.as_ref());
21576                            }
21577                        }
21578                    }
21579                    TensorContentSeals::Model(model) => {
21580                        recorder.read_write(&model.ranges);
21581                        recorder.read_write(&model.contract);
21582                        if let Some(source) = &model.prepared {
21583                            recorder.read(&source.roster);
21584                            recorder.read(&source.reader);
21585                        }
21586                    }
21587                }
21588            }
21589            for branch in &prepared.branches {
21590                if let Some(continuation) = &branch.continuation {
21591                    continuation.text_binding.record(&mut recorder);
21592                    for tensor in &continuation.sources {
21593                        if let Some(source) = &tensor.source {
21594                            recorder.read(source);
21595                        }
21596                    }
21597                }
21598                if let Some(update) = &branch.model_update {
21599                    update.record(&mut recorder);
21600                }
21601                #[cfg(feature = "semantic-policy")]
21602                {
21603                    recorder.write(&branch.state);
21604                    recorder.write(
21605                        branch
21606                            .support
21607                            .as_ref()
21608                            .ok_or(SemanticTransitionError::ObservationMismatch)?,
21609                    );
21610                    recorder.write(
21611                        branch
21612                            .receipts
21613                            .as_ref()
21614                            .ok_or(SemanticTransitionError::ObservationMismatch)?,
21615                    );
21616                    if let Some(policy) = &branch.policy {
21617                        policy.numerical.record(&mut recorder);
21618                        for buffer in [
21619                            &policy.parameters,
21620                            &policy.hidden,
21621                            &policy.scores,
21622                            &policy.retained_scores,
21623                            &policy.recurrent,
21624                            &policy.text_logits,
21625                        ] {
21626                            recorder.read_write(buffer);
21627                        }
21628                        policy.text_binding.record(&mut recorder);
21629                    } else {
21630                        recorder.read(
21631                            &branch
21632                                .policy_buffers
21633                                .as_ref()
21634                                .ok_or(SemanticTransitionError::NotBound)?
21635                                .text_logits,
21636                        );
21637                    }
21638                    for tensor in &branch.policy_sources {
21639                        if let Some(source) = &tensor.source {
21640                            recorder.read(source);
21641                        }
21642                    }
21643                }
21644            }
21645        }
21646        Ok(recorder)
21647    }
21648
21649    /// Reserve exactly one native prefill stage for the imported task. The
21650    /// expected tokens come from its admitted source mapping, not a model-side
21651    /// copy. This stage owns the device comparison input before any model call.
21652    pub fn begin_initial_prefill(
21653        &mut self,
21654        layout: SemanticInitialSourceLayout,
21655        model_generation: u64,
21656    ) -> Result<SemanticInitialPrefillLease, SemanticTransitionError> {
21657        self.ensure_rebindable()?;
21658        if self.publication.is_some() || self.initial_prefill.is_some() {
21659            return Err(publication_input_error(
21660                "initial prefill requires one unpublished imported task",
21661            ));
21662        }
21663        let task_identity = self
21664            .task_evaluation_identity()
21665            .ok_or(SemanticTransitionError::NotBound)?;
21666        if model_generation == 0 || layout.prefill_tokens.is_empty() {
21667            return Err(publication_input_error(
21668                "initial prefill requires a model generation and nonempty committed prefix",
21669            ));
21670        }
21671        if layout.prefill_tokens.len() != layout.prefix.len()
21672            || layout.prefix.iter().enumerate().any(|(position, row)| {
21673                row.token != layout.prefill_tokens[position]
21674                    || row.logical_position != position as u64
21675                    || row.kind != 1
21676                    || row.provenance != 1
21677                    || row.valid != 1
21678                    || row.committed != 1
21679            })
21680        {
21681            return Err(publication_input_error(
21682                "initial prefill layout differs from the admitted ordered prefix",
21683            ));
21684        }
21685        let expected_tokens = allocate_publication(&self.provider, layout.prefill_tokens.len())?;
21686        let scope = Arc::new(());
21687        self.initial_prefill = Some(InitialPrefillStage {
21688            scope: Arc::clone(&scope),
21689            task_identity,
21690            task_epoch: self.task_epoch,
21691            model_generation,
21692            layout,
21693            expected_tokens,
21694            input: None,
21695            model_content: None,
21696            output_content: None,
21697            captured_content: Vec::new(),
21698            consumer_stream: None,
21699        });
21700        let stage = self
21701            .initial_prefill
21702            .as_mut()
21703            .expect("stage installed before upload");
21704        if let Err(error) = self
21705            .provider
21706            .htod_sync_copy_into_tracked(&stage.layout.prefill_tokens, &mut stage.expected_tokens)
21707        {
21708            self.poisoned = true;
21709            return Err(runtime_error("initial prefill token upload", error));
21710        }
21711        Ok(SemanticInitialPrefillLease {
21712            issuer: Arc::clone(&self.publication_issuer),
21713            scope,
21714        })
21715    }
21716
21717    /// Compare the actual I64 tensor at the model's pre-hook against the
21718    /// admitted prefix on device. The stream edge completes before the model
21719    /// continues, and the original DLPack owner remains in this stage.
21720    pub fn record_initial_prefill_input(
21721        &mut self,
21722        lease: &SemanticInitialPrefillLease,
21723        input: SemanticTensorInput,
21724        consumer_stream: u64,
21725    ) -> Result<(), SemanticTransitionError> {
21726        self.ensure_quiescent()?;
21727        dlpack_consumer_stream(consumer_stream)?;
21728        let stage = self
21729            .initial_prefill
21730            .as_ref()
21731            .ok_or(SemanticTransitionError::NotBound)?;
21732        if !Arc::ptr_eq(&self.publication_issuer, &lease.issuer)
21733            || !Arc::ptr_eq(&stage.scope, &lease.scope)
21734            || self.publication.is_some()
21735            || stage.task_epoch != self.task_epoch
21736            || self.task_evaluation_identity() != Some(stage.task_identity)
21737            || stage.model_content.is_none()
21738            || stage.consumer_stream != Some(consumer_stream)
21739            || stage.input.is_some()
21740        {
21741            return Err(publication_input_error(
21742                "initial prefill input belongs to another or already-used task stage",
21743            ));
21744        }
21745        validate_initial_prefill_input_layout(
21746            &input.layout,
21747            stage.layout.prefill_tokens.len() as u64,
21748        )?;
21749        if input.logical_begin != 0 || input.logical_end != stage.layout.prefill_tokens.len() as u64
21750        {
21751            return Err(publication_input_error(
21752                "initial prefill input interval differs from the admitted prefix",
21753            ));
21754        }
21755        let mut prepared = prepare_semantic_tensors(&self.provider, vec![input])?;
21756        let input = prepared.pop().expect("one checked prefill input");
21757        let actual_ptr = input.data;
21758        self.initial_prefill.as_mut().expect("checked stage").input = Some(input);
21759        self.initial_prefill
21760            .as_mut()
21761            .expect("checked stage")
21762            .consumer_stream = Some(consumer_stream);
21763        let result = (|| {
21764            self.order_tensor_producer_inputs(consumer_stream)?;
21765            let stage = self
21766                .initial_prefill
21767                .as_ref()
21768                .expect("retained prefill stage");
21769            let execute = self
21770                .provider
21771                .device()
21772                .inner()
21773                .get_func(
21774                    "xlog_semantic_transition",
21775                    "semantic_initial_prefill_input_guard",
21776                )
21777                .ok_or_else(|| {
21778                    runtime_error("kernel lookup", "initial prefill input guard unavailable")
21779                })?;
21780            let mut recorder = self.domain.new_strict_recorder();
21781            recorder.read(&stage.expected_tokens);
21782            recorder.read(
21783                stage
21784                    .input
21785                    .as_ref()
21786                    .expect("retained prefill input")
21787                    .source
21788                    .as_ref()
21789                    .ok_or_else(|| {
21790                        publication_input_error(
21791                            "initial prefill input has no original device storage",
21792                        )
21793                    })?,
21794            );
21795            let arguments = (
21796                stage.expected_tokens.device_ptr_value(),
21797                actual_ptr,
21798                stage.layout.prefill_tokens.len() as u64,
21799            );
21800            enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
21801                // SAFETY: both original producer and expected-token allocations
21802                // are retained by this stage; layout and stream were checked.
21803                unsafe {
21804                    execute.launch_in(
21805                        enqueue,
21806                        LaunchConfig {
21807                            grid_dim: (1, 1, 1),
21808                            block_dim: (1, 1, 1),
21809                            shared_mem_bytes: 0,
21810                        },
21811                        arguments,
21812                    )
21813                }
21814                .map_err(|error| XlogError::Kernel(error.to_string()))
21815            })?;
21816            self.stream
21817                .synchronize()
21818                .map_err(|error| runtime_error("initial prefill input verification", error))?;
21819            self.order_content_consumers(consumer_stream)
21820        })();
21821        if result.is_err() {
21822            self.poisoned = true;
21823        }
21824        result
21825    }
21826
21827    /// Seal the original model roster before its prefill forward. The caller
21828    /// supplies model tensors followed by their complete original backing
21829    /// allocations, exactly as it will supply them to parent binding.
21830    pub fn bind_initial_prefill_model_content(
21831        &mut self,
21832        lease: &SemanticInitialPrefillLease,
21833        tensors: Vec<SemanticTensorInput>,
21834        consumer_stream: u64,
21835    ) -> Result<SemanticInitialPrefillContentWitness, SemanticTransitionError> {
21836        self.capture_initial_prefill_roster(
21837            lease,
21838            tensors,
21839            consumer_stream,
21840            InitialPrefillCaptureKind::Model,
21841        )?
21842        .ok_or(SemanticTransitionError::ObservationMismatch)
21843    }
21844
21845    /// Capture original pre-call, transient or saved tensors after the model
21846    /// roster is sealed, before any dependent read may change their bytes.
21847    /// Pre-call capture does not replace the actual input pre-hook.
21848    pub fn capture_initial_prefill_tensor_content(
21849        &mut self,
21850        lease: &SemanticInitialPrefillLease,
21851        tensors: Vec<SemanticTensorInput>,
21852        consumer_stream: u64,
21853    ) -> Result<SemanticInitialPrefillContentWitness, SemanticTransitionError> {
21854        self.capture_initial_prefill_roster(
21855            lease,
21856            tensors,
21857            consumer_stream,
21858            InitialPrefillCaptureKind::Captured,
21859        )?
21860        .ok_or(SemanticTransitionError::ObservationMismatch)
21861    }
21862
21863    /// Seal the original model outputs at the post-detach wrapper boundary.
21864    /// Every prefill cache/state tensor later supplied to parent binding must
21865    /// be this exact allocation, layout and logical interval.
21866    pub fn record_initial_prefill_outputs(
21867        &mut self,
21868        lease: &SemanticInitialPrefillLease,
21869        tensors: Vec<SemanticTensorInput>,
21870        consumer_stream: u64,
21871    ) -> Result<(), SemanticTransitionError> {
21872        self.capture_initial_prefill_roster(
21873            lease,
21874            tensors,
21875            consumer_stream,
21876            InitialPrefillCaptureKind::Outputs,
21877        )?;
21878        Ok(())
21879    }
21880
21881    fn capture_initial_prefill_roster(
21882        &mut self,
21883        lease: &SemanticInitialPrefillLease,
21884        tensors: Vec<SemanticTensorInput>,
21885        consumer_stream: u64,
21886        kind: InitialPrefillCaptureKind,
21887    ) -> Result<Option<SemanticInitialPrefillContentWitness>, SemanticTransitionError> {
21888        self.ensure_quiescent()?;
21889        dlpack_consumer_stream(consumer_stream)?;
21890        let stage = self
21891            .initial_prefill
21892            .as_ref()
21893            .ok_or(SemanticTransitionError::NotBound)?;
21894        if !Arc::ptr_eq(&self.publication_issuer, &lease.issuer)
21895            || !Arc::ptr_eq(&stage.scope, &lease.scope)
21896            || self.publication.is_some()
21897            || stage.task_epoch != self.task_epoch
21898            || self.task_evaluation_identity() != Some(stage.task_identity)
21899            || stage
21900                .consumer_stream
21901                .is_some_and(|stream| stream != consumer_stream)
21902            || match kind {
21903                InitialPrefillCaptureKind::Model => {
21904                    stage.model_content.is_some() || stage.input.is_some()
21905                }
21906                InitialPrefillCaptureKind::Outputs => {
21907                    stage.model_content.is_none()
21908                        || stage.input.is_none()
21909                        || stage.output_content.is_some()
21910                }
21911                InitialPrefillCaptureKind::Captured => {
21912                    stage.model_content.is_none() || stage.output_content.is_some()
21913                }
21914            }
21915        {
21916            return Err(publication_input_error(
21917                "initial prefill roster belongs to another stage, stream or forward order",
21918            ));
21919        }
21920        if tensors.is_empty()
21921            || tensors.iter().any(|tensor| match kind {
21922                InitialPrefillCaptureKind::Model => !matches!(tensor.layout.role, 0 | 18..=25),
21923                InitialPrefillCaptureKind::Outputs => !matches!(tensor.layout.role, 4..=13),
21924                InitialPrefillCaptureKind::Captured => false,
21925            })
21926        {
21927            return Err(publication_input_error(
21928                "initial prefill model or output roster has missing or foreign tensor roles",
21929            ));
21930        }
21931        let prepared = prepare_semantic_tensors(&self.provider, tensors)?;
21932        let stage = self
21933            .initial_prefill
21934            .as_mut()
21935            .expect("checked prefill stage");
21936        let content = TensorContentBuffers {
21937            tensors: prepared,
21938            seals: TensorContentSeals::Captured(Vec::new()),
21939            verification_inputs: Vec::new(),
21940        };
21941        let slot = match kind {
21942            InitialPrefillCaptureKind::Model => {
21943                stage.model_content = Some(content);
21944                Some(InitialPrefillContentSlot::Model)
21945            }
21946            InitialPrefillCaptureKind::Outputs => {
21947                stage.output_content = Some(content);
21948                None
21949            }
21950            InitialPrefillCaptureKind::Captured => {
21951                let index = stage.captured_content.len();
21952                stage.captured_content.push(content);
21953                Some(InitialPrefillContentSlot::Captured(index))
21954            }
21955        };
21956        stage.consumer_stream = Some(consumer_stream);
21957        let witness = slot.map(|slot| SemanticInitialPrefillContentWitness {
21958            issuer: Arc::clone(&self.publication_issuer),
21959            scope: Arc::clone(&stage.scope),
21960            task_identity: stage.task_identity,
21961            task_epoch: stage.task_epoch,
21962            model_generation: stage.model_generation,
21963            slot,
21964        });
21965        let result = (|| {
21966            self.order_tensor_producer_inputs(consumer_stream)?;
21967            let stage = self
21968                .initial_prefill
21969                .as_ref()
21970                .expect("retained prefill stage");
21971            let content = match kind {
21972                InitialPrefillCaptureKind::Model => stage
21973                    .model_content
21974                    .as_ref()
21975                    .expect("retained model content"),
21976                InitialPrefillCaptureKind::Outputs => stage
21977                    .output_content
21978                    .as_ref()
21979                    .expect("retained output content"),
21980                InitialPrefillCaptureKind::Captured => stage
21981                    .captured_content
21982                    .last()
21983                    .expect("retained transient content"),
21984            };
21985            // Model views precede their backing allocations. Role-zero indices
21986            // name allocation ordinals, unlike private capture positions.
21987            let private_prefix = if matches!(kind, InitialPrefillCaptureKind::Model) {
21988                content
21989                    .tensors
21990                    .iter()
21991                    .filter(|tensor| tensor.layout.role != 0)
21992                    .count()
21993            } else {
21994                0
21995            };
21996            validate_content_coordinates_after(
21997                content
21998                    .tensors
21999                    .iter()
22000                    .map(|tensor| (tensor.layout.role, tensor.layout.index)),
22001                private_prefix,
22002            )?;
22003            let digests = content
22004                .tensors
22005                .iter()
22006                .map(|tensor| {
22007                    tensor_content_range(
22008                        &tensor.layout,
22009                        tensor.logical_begin,
22010                        tensor.logical_end,
22011                        tensor.source.as_ref().map_or(0, DeviceMemoryView::len),
22012                    )?;
22013                    Ok(CapturedTensorDigest::Tensor {
22014                        cells: Arc::new(allocate_publication(&self.provider, 4)?),
22015                        offset: 0,
22016                        producer_sealed: false,
22017                    })
22018                })
22019                .collect::<Result<Vec<_>, SemanticTransitionError>>()?;
22020            let stage = self
22021                .initial_prefill
22022                .as_mut()
22023                .expect("retained prefill stage");
22024            let content = match kind {
22025                InitialPrefillCaptureKind::Model => stage
22026                    .model_content
22027                    .as_mut()
22028                    .expect("retained model content"),
22029                InitialPrefillCaptureKind::Outputs => stage
22030                    .output_content
22031                    .as_mut()
22032                    .expect("retained output content"),
22033                InitialPrefillCaptureKind::Captured => stage
22034                    .captured_content
22035                    .last_mut()
22036                    .expect("retained transient content"),
22037            };
22038            content.seals = TensorContentSeals::Captured(digests);
22039            let stage = self
22040                .initial_prefill
22041                .as_ref()
22042                .expect("retained prefill stage");
22043            let content = match kind {
22044                InitialPrefillCaptureKind::Model => stage
22045                    .model_content
22046                    .as_ref()
22047                    .expect("retained model content"),
22048                InitialPrefillCaptureKind::Outputs => stage
22049                    .output_content
22050                    .as_ref()
22051                    .expect("retained output content"),
22052                InitialPrefillCaptureKind::Captured => stage
22053                    .captured_content
22054                    .last()
22055                    .expect("retained transient content"),
22056            };
22057            let execute = self
22058                .provider
22059                .device()
22060                .inner()
22061                .get_func(
22062                    "xlog_semantic_transition",
22063                    "semantic_tensor_content_witness",
22064                )
22065                .ok_or_else(|| {
22066                    runtime_error("kernel lookup", "tensor content witness unavailable")
22067                })?;
22068            content.enqueue(&self.domain, &mut self.poisoned, &execute, false)?;
22069            self.order_content_consumers(consumer_stream)
22070        })();
22071        if result.is_err() {
22072            self.poisoned = true;
22073        }
22074        result.map(|()| witness)
22075    }
22076
22077    /// Check the same original prefill seal before a dependent model or saved
22078    /// tensor read, including after the parent has consumed the one-use stage.
22079    pub fn verify_initial_prefill_tensor_content(
22080        &mut self,
22081        lease: &SemanticInitialPrefillLease,
22082        witness: &SemanticInitialPrefillContentWitness,
22083        tensors: Vec<SemanticTensorInput>,
22084        consumer_stream: u64,
22085    ) -> Result<(), SemanticTransitionError> {
22086        let mut handoff = RetainedTensorAdmission {
22087            inputs: Some(tensors),
22088            stream: Arc::clone(self.provider.device().inner().stream()),
22089            ready: false,
22090        };
22091        if self.is_poisoned() {
22092            return Err(SemanticTransitionError::Poisoned);
22093        }
22094        dlpack_consumer_stream(consumer_stream)?;
22095        let (scope, task_identity, task_epoch, model_generation, captured_count) =
22096            if let Some(stage) = self.initial_prefill.as_ref() {
22097                (
22098                    &stage.scope,
22099                    stage.task_identity,
22100                    stage.task_epoch,
22101                    stage.model_generation,
22102                    stage.captured_content.len(),
22103                )
22104            } else if let Some(retained) = self.retained_initial_prefill.as_ref() {
22105                (
22106                    &retained.scope,
22107                    retained.task_identity,
22108                    retained.task_epoch,
22109                    retained.model_generation,
22110                    retained.captured.len(),
22111                )
22112            } else {
22113                return Err(SemanticTransitionError::NotBound);
22114            };
22115        if !Arc::ptr_eq(&self.publication_issuer, &lease.issuer)
22116            || !Arc::ptr_eq(scope, &lease.scope)
22117            || self.task_epoch != task_epoch
22118            || self.task_evaluation_identity() != Some(task_identity)
22119            || !witness.matches(
22120                &self.publication_issuer,
22121                scope,
22122                task_identity,
22123                task_epoch,
22124                model_generation,
22125                captured_count,
22126            )
22127        {
22128            return Err(publication_input_error(
22129                "initial prefill content witness belongs to another task, stream or stage",
22130            ));
22131        }
22132        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
22133            .map_err(|error| runtime_error("prefill content stream admission", error))?;
22134        let prepared = prepare_semantic_tensors(
22135            &self.provider,
22136            handoff
22137                .inputs
22138                .take()
22139                .expect("retained original prefill verification inputs"),
22140        )?;
22141        let content = if let Some(stage) = self.initial_prefill.as_mut() {
22142            match witness.slot {
22143                InitialPrefillContentSlot::Model => stage.model_content.as_mut(),
22144                InitialPrefillContentSlot::Captured(index) => stage.captured_content.get_mut(index),
22145            }
22146        } else {
22147            self.retained_initial_prefill
22148                .as_mut()
22149                .and_then(|retained| match witness.slot {
22150                    InitialPrefillContentSlot::Model => Some(&mut retained.model),
22151                    InitialPrefillContentSlot::Captured(index) => retained.captured.get_mut(index),
22152                })
22153        }
22154        .ok_or(SemanticTransitionError::ObservationMismatch)?;
22155        let offset = content.verification_inputs.len();
22156        content.verification_inputs.extend(prepared);
22157        let actual = &content.verification_inputs[offset..];
22158        if actual.len() != content.tensors.len()
22159            || content
22160                .tensors
22161                .iter()
22162                .zip(actual)
22163                .any(|(expected, actual)| !same_tensor_content_owner(expected, actual))
22164        {
22165            return Err(publication_input_error(
22166                "prefill content verification requires the original storage, layout and interval",
22167            ));
22168        }
22169        let result = (|| {
22170            self.order_tensor_producer_inputs(consumer_stream)?;
22171            let content = if let Some(stage) = self.initial_prefill.as_ref() {
22172                match witness.slot {
22173                    InitialPrefillContentSlot::Model => stage.model_content.as_ref(),
22174                    InitialPrefillContentSlot::Captured(index) => stage.captured_content.get(index),
22175                }
22176            } else {
22177                self.retained_initial_prefill
22178                    .as_ref()
22179                    .and_then(|retained| match witness.slot {
22180                        InitialPrefillContentSlot::Model => Some(&retained.model),
22181                        InitialPrefillContentSlot::Captured(index) => retained.captured.get(index),
22182                    })
22183            }
22184            .ok_or(SemanticTransitionError::ObservationMismatch)?;
22185            let execute = self
22186                .provider
22187                .device()
22188                .inner()
22189                .get_func(
22190                    "xlog_semantic_transition",
22191                    "semantic_tensor_content_witness",
22192                )
22193                .ok_or_else(|| {
22194                    runtime_error("kernel lookup", "tensor content witness unavailable")
22195                })?;
22196            content.enqueue(&self.domain, &mut self.poisoned, &execute, true)?;
22197            self.order_content_consumers(consumer_stream)
22198        })();
22199        if result.is_err() {
22200            self.poisoned = true;
22201        }
22202        result
22203    }
22204
22205    fn verify_initial_prefill_parent(
22206        &mut self,
22207        parent: &SemanticParentBinding,
22208        tensors: &[PreparedSemanticTensor],
22209        allocations: &[PreparedSemanticTensor],
22210    ) -> Result<(), SemanticTransitionError> {
22211        if parent.prefix.is_empty() {
22212            if self.initial_prefill.is_some() {
22213                return Err(publication_input_error(
22214                    "an initial prefill stage cannot be bound to an empty prefix",
22215                ));
22216            }
22217            return Ok(());
22218        }
22219        let stage = self.initial_prefill.as_ref().ok_or_else(|| {
22220            publication_input_error(
22221                "nonempty initial prefix requires its original model prefill stage",
22222            )
22223        })?;
22224        let model = stage.model_content.as_ref().ok_or_else(|| {
22225            publication_input_error("initial prefill has no original model-content witness")
22226        })?;
22227        let outputs = stage.output_content.as_ref().ok_or_else(|| {
22228            publication_input_error("initial prefill has no original model-output witness")
22229        })?;
22230        let model_inputs = tensors
22231            .iter()
22232            .filter(|tensor| matches!(tensor.layout.role, 18..=25))
22233            .chain(allocations);
22234        let output_inputs = tensors
22235            .iter()
22236            .filter(|tensor| matches!(tensor.layout.role, 4..=13));
22237        if self.publication.is_some()
22238            || stage.task_epoch != self.task_epoch
22239            || self.task_evaluation_identity() != Some(stage.task_identity)
22240            || stage.task_epoch != parent.authority_generation
22241            || stage.model_generation != parent.model_generation
22242            || stage.input.is_none()
22243            || stage.consumer_stream.is_none()
22244            || stage.layout.ring_head != parent.ring_head
22245            || !same_initial_source_rows(&stage.layout.source, &parent.source)
22246            || !same_initial_source_rows(&stage.layout.prefix, &parent.prefix)
22247            || parent.provenance_records != stage.layout.provenance_records
22248            || parent
22249                .records
22250                .iter()
22251                .filter(|record| record.role == SemanticStateRole::TokenProvenanceRecords)
22252                .count()
22253                != 1
22254            || !parent.records.iter().any(|record| {
22255                record.role == SemanticStateRole::TokenProvenanceRecords
22256                    && record.index == 0
22257                    && record.bytes == stage.layout.provenance_bytes
22258                    && record.capacity_bytes == stage.layout.provenance_capacity_bytes
22259            })
22260            || model.tensors.len() != model_inputs.clone().count()
22261            || !model
22262                .tensors
22263                .iter()
22264                .zip(model_inputs)
22265                .all(|(expected, actual)| same_tensor_content_owner(expected, actual))
22266            || outputs.tensors.len() != output_inputs.clone().count()
22267            || !outputs
22268                .tensors
22269                .iter()
22270                .zip(output_inputs)
22271                .all(|(expected, actual)| same_tensor_content_owner(expected, actual))
22272        {
22273            return Err(publication_input_error(
22274                "initial parent changed its admitted source, model or original prefill outputs",
22275            ));
22276        }
22277        let stream = stage.consumer_stream.expect("checked prefill stream");
22278        let result = (|| {
22279            self.order_tensor_producer_inputs(stream)?;
22280            let stage = self
22281                .initial_prefill
22282                .as_ref()
22283                .expect("retained prefill stage");
22284            let execute = self
22285                .provider
22286                .device()
22287                .inner()
22288                .get_func(
22289                    "xlog_semantic_transition",
22290                    "semantic_tensor_content_witness",
22291                )
22292                .ok_or_else(|| {
22293                    runtime_error("kernel lookup", "tensor content witness unavailable")
22294                })?;
22295            stage
22296                .model_content
22297                .as_ref()
22298                .expect("checked model content")
22299                .enqueue(&self.domain, &mut self.poisoned, &execute, true)?;
22300            stage
22301                .output_content
22302                .as_ref()
22303                .expect("checked output content")
22304                .enqueue(&self.domain, &mut self.poisoned, &execute, true)?;
22305            self.order_content_consumers(stream)
22306        })();
22307        if result.is_err() {
22308            self.poisoned = true;
22309        }
22310        result
22311    }
22312
22313    /// Snapshot every supplied cold owner into fixed publication storage, then
22314    /// initialize and seal bank zero through the actual native command.
22315    pub fn bind_parent(
22316        &mut self,
22317        mut parent: SemanticParentBinding,
22318    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
22319        // The handoff guard owns all managed inputs before any later validation
22320        // can return. Failed cold admission cannot drop an unfinished producer.
22321        let tensor_count = parent.tensors.len();
22322        let mut producers = std::mem::take(&mut parent.tensors);
22323        producers.append(&mut parent.model_memory.allocations);
22324        let producers = complete_tensor_handoff(&self.provider, producers)?;
22325        let mut tensors = prepare_semantic_tensors(&self.provider, producers)?;
22326        let allocations = tensors.split_off(tensor_count);
22327        let model_memory = prepare_model_memory(
22328            &allocations,
22329            std::mem::take(&mut parent.model_memory.storages),
22330            std::mem::take(&mut parent.model_memory.views),
22331            &tensors,
22332        )?;
22333        self.verify_initial_prefill_parent(&parent, &tensors, &allocations)?;
22334        self.ensure_rebindable_with_prefill()?;
22335        if self.publication.is_some() {
22336            return Err(publication_input_error(
22337                "this Session already owns a canonical publication instance",
22338            ));
22339        }
22340        let task_identity = self
22341            .task_evaluation_identity()
22342            .ok_or(SemanticTransitionError::NotBound)?;
22343        #[cfg(feature = "semantic-policy")]
22344        let task_content = self
22345            .task
22346            .as_ref()
22347            .ok_or(SemanticTransitionError::NotBound)?
22348            .0
22349            .content_identity();
22350        if parent.authority_generation != self.task_epoch {
22351            return Err(publication_input_error(
22352                "parent authority generation differs from the retained task import",
22353            ));
22354        }
22355        if parent.recovered_instance.is_some()
22356            || parent.records.iter().any(|record| {
22357                matches!(
22358                    record.role,
22359                    SemanticStateRole::IntentEntries
22360                        | SemanticStateRole::IntentPayload
22361                        | SemanticStateRole::Acknowledgements
22362                )
22363            })
22364        {
22365            return Err(publication_input_error("fresh parent initialization cannot replace recovered history or accept private intent records"));
22366        }
22367        parent.records.extend(initial_intent_records(
22368            &parent.intent_effect,
22369            parent.intent_entry_capacity,
22370            parent.intent_payload_capacity_bytes,
22371            parent.final_intent_payload_bytes,
22372        )?);
22373        parent.records.push(initial_acknowledgement_record(
22374            parent.intent_entry_capacity,
22375            parent.acknowledgement_payload_capacity_bytes,
22376            parent.intent_payload_capacity_bytes,
22377            parent.intent_effect.len(),
22378        )?);
22379        validate_parent_records(&parent, &tensors)?;
22380        let mut layouts = BTreeMap::new();
22381        let mut plans = Vec::new();
22382        for tensor in tensors {
22383            let layout = if matches!(tensor.layout.role, 18..=25) {
22384                tensor.layout
22385            } else if matches!(tensor.layout.role, 4 | 5) {
22386                prefix_capacity_layout(tensor.layout, parent.prefix_capacity)?
22387            } else {
22388                canonical_tensor_layout(tensor.layout)?
22389            };
22390            let bytes = tensor_layout_bytes(&layout)?;
22391            if bytes == 0 && !empty_model_tensor_layout(&layout) {
22392                return Err(publication_input_error(
22393                    "non-active tensor destination has no owned extent",
22394                ));
22395            }
22396            layouts.insert((layout.role, layout.index), layout);
22397            let capacity = if matches!(layout.role, 18..=25) {
22398                let (allocation, offset) = model_memory.location(layout.role, layout.index)?;
22399                model_memory.allocation_bytes[allocation] as usize - offset
22400            } else {
22401                bytes
22402            };
22403            plans.push(PublicationAllocationPlan {
22404                role: layout.role,
22405                index: layout.index,
22406                capacity,
22407                length: bytes,
22408                logical_begin: tensor.logical_begin,
22409                logical_end: tensor.logical_end,
22410                payload: if matches!(layout.role, 18..=25) {
22411                    PublicationPayload::Uncomputed
22412                } else {
22413                    PublicationPayload::Tensor(tensor)
22414                },
22415            });
22416        }
22417        for layout in &parent.active_layouts {
22418            let layout = canonical_tensor_layout(*layout)?;
22419            let bytes = tensor_layout_bytes(&layout)?;
22420            layouts.insert((layout.role, layout.index), layout);
22421            plans.push(PublicationAllocationPlan {
22422                role: layout.role,
22423                index: layout.index,
22424                capacity: bytes,
22425                length: 0,
22426                logical_begin: 0,
22427                logical_end: 0,
22428                payload: PublicationPayload::Uncomputed,
22429            });
22430        }
22431        for record in &parent.records {
22432            plans.push(PublicationAllocationPlan {
22433                role: record.role as u64,
22434                index: record.index,
22435                capacity: record.capacity_bytes,
22436                length: record.bytes.len(),
22437                logical_begin: 0,
22438                logical_end: if record.role == SemanticStateRole::TokenProvenanceRecords {
22439                    parent.provenance_records
22440                } else {
22441                    0
22442                },
22443                payload: PublicationPayload::Metadata(record.bytes.clone()),
22444            });
22445        }
22446        let statements = self.feedback_statement_bytes()?.map(<[u8]>::to_vec);
22447        let layout_rows: Vec<_> = layouts.values().copied().collect();
22448        let prefix_capacity = usize::try_from(parent.prefix_capacity)
22449            .ok()
22450            .and_then(|n| n.checked_mul(size_of::<SemanticTextSlot>()))
22451            .ok_or_else(|| publication_input_error("prefix source capacity overflow"))?;
22452        let feedback_capacity = usize::try_from(parent.feedback_capacity)
22453            .ok()
22454            .and_then(|n| n.checked_mul(size_of::<RawFeedbackRecord>()))
22455            .ok_or_else(|| publication_input_error("feedback capacity overflow"))?;
22456        for (role, index, bytes, capacity, end) in [
22457            (
22458                1,
22459                0,
22460                publication_abi_bytes(&parent.prefix),
22461                prefix_capacity,
22462                parent.prefix.len() as u64,
22463            ),
22464            // Output storage only; native initialization fills the actual
22465            // source digest before this bank can be sealed or acquired.
22466            (3, 0, vec![0; 32], 32, 0),
22467            (
22468                14,
22469                0,
22470                vec![0; size_of::<CompletionCoverage>()],
22471                size_of::<CompletionCoverage>(),
22472                0,
22473            ),
22474            (15, 0, vec![0; feedback_capacity], feedback_capacity, 0),
22475            (16, 0, statements[0].clone(), statements[0].len(), 0),
22476            (16, 1, statements[1].clone(), statements[1].len(), 0),
22477            (16, 2, statements[2].clone(), statements[2].len(), 0),
22478            (
22479                33,
22480                0,
22481                vec![0; size_of::<AttemptReceipt>()],
22482                size_of::<AttemptReceipt>(),
22483                0,
22484            ),
22485            (
22486                47,
22487                0,
22488                include_bytes!("semantic_action_catalogue_v1.def").to_vec(),
22489                include_bytes!("semantic_action_catalogue_v1.def").len(),
22490                0,
22491            ),
22492            (
22493                48,
22494                0,
22495                publication_abi_bytes(&self.codebooks.words),
22496                self.codebooks.words.len() * 8,
22497                0,
22498            ),
22499            (
22500                55,
22501                0,
22502                tensor_table_bytes(&layout_rows, false, &[])?,
22503                tensor_table_capacity(layout_rows.len(), 32 + parent.feedback_capacity)?,
22504                0,
22505            ),
22506        ] {
22507            plans.push(PublicationAllocationPlan {
22508                role,
22509                index,
22510                capacity,
22511                length: bytes.len(),
22512                logical_begin: 0,
22513                logical_end: end,
22514                payload: PublicationPayload::Metadata(bytes),
22515            });
22516        }
22517        let mut instance = [0u8; 32];
22518        getrandom::fill(&mut instance)
22519            .map_err(|error| runtime_error("publication instance entropy", error))?;
22520        let instance = Identity256::from_bytes(instance);
22521        let contract = PublicationContract {
22522            abi: 1,
22523            range_capacity: plans.len() as u64 + 1,
22524            prefix_capacity: parent.prefix_capacity,
22525            window_capacity: 32,
22526            feedback_capacity: parent.feedback_capacity,
22527            max_position: parent.max_position,
22528            pad_token: parent.pad_token,
22529            terminal_token_count: parent.terminal_tokens.len() as u64,
22530            final_intent_payload_bytes: parent.final_intent_payload_bytes,
22531            model_generation: parent.model_generation,
22532            policy_generation: parent.policy_generation,
22533            authority_generation: parent.authority_generation,
22534            semantic_owner: self.graph.transition_arena()[1],
22535            task_identity,
22536            topology_identity: parent.topology_identity,
22537            table_identity: parent.table_identity,
22538            model_contract_layout: parent.model_contract_layout,
22539            role_count: 55,
22540            ..PublicationContract::default()
22541        };
22542        let runtime = initial_runtime_contract_record(
22543            contract,
22544            &parent.role_counts,
22545            &parent.terminal_tokens,
22546            &layouts,
22547            plans
22548                .iter()
22549                .map(|plan| (plan.role, plan.index, plan.capacity))
22550                .collect(),
22551            &parent.model_numerical_mode,
22552            &model_memory,
22553        )?;
22554        plans.push(PublicationAllocationPlan {
22555            role: runtime.role as u64,
22556            index: runtime.index,
22557            capacity: runtime.capacity_bytes,
22558            length: runtime.bytes.len(),
22559            logical_begin: 0,
22560            logical_end: 0,
22561            payload: PublicationPayload::Metadata(runtime.bytes),
22562        });
22563        plans.sort_by_key(|plan| (plan.role, plan.index));
22564        let model_geometry_digest = model_memory.digest(&layouts)?;
22565        let model_payloads = allocations
22566            .into_iter()
22567            .map(PublicationPayload::Tensor)
22568            .collect::<Vec<_>>();
22569        let (storage, uploads) = PublicationStorage::allocate(
22570            &self.provider,
22571            &plans,
22572            layouts,
22573            model_memory,
22574            &model_payloads,
22575            contract,
22576            &parent.terminal_tokens,
22577            instance,
22578        )?;
22579        // Install all destinations and producer owners before the first command
22580        // that may enqueue. A partial copy failure keeps these owners in Session.
22581        self.publication = Some(Arc::new(storage));
22582        self.publication_uploads = uploads;
22583        self.captured = None;
22584        let extents = self.base_snapshot.extents();
22585        let header = PublicationHeader {
22586            instance,
22587            ring_head: parent.ring_head,
22588            prefix_extent: parent.prefix.len() as u64,
22589            semantic_owner: self.graph.transition_arena()[1],
22590            semantic_slot: u64::from(self.root.slot()),
22591            semantic_generation: self.root.generation(),
22592            semantic_digest: Identity256::from_bytes(*self.base_snapshot.digest().as_bytes()),
22593            semantic_extents: [
22594                u64::from(extents.statements()),
22595                u64::from(extents.supports()),
22596                u64::from(extents.versions()),
22597            ],
22598            model_generation: parent.model_generation,
22599            neural_generation: parent.neural_generation,
22600            cache_generation: parent.cache_generation,
22601            authority_generation: parent.authority_generation,
22602            fuel: parent.fuel,
22603            proposal: u64::from(parent.rng.proposal),
22604            stream_serial: parent.rng.stream_serial,
22605            family_id: u64::from(parent.rng.family_id),
22606            training_cursor: parent.training_cursor,
22607            training_rng: parent.training_rng,
22608            range_count: contract.range_capacity,
22609            model_geometry_digest,
22610            ..PublicationHeader::default()
22611        };
22612        let state = DeviceState {
22613            model_generation: parent.rng.model_generation,
22614            family_id: u32::from(parent.rng.family_id),
22615            stream_serial: parent.rng.stream_serial,
22616            next_proposal: u64::from(parent.rng.proposal),
22617            catalogue_generation: self.binding().generation,
22618            catalogue_digest: Identity256::from_bytes(CATALOGUE_DIGEST),
22619            binding_digest: self.binding().digest,
22620            ..DeviceState::default()
22621        };
22622        let bank = PublicationBank {
22623            header,
22624            source: parent.source,
22625            state,
22626            receipts: [SemanticTransitionReceipt::default(); COMPONENT_COUNT],
22627        };
22628        let result = self.initialize_publication(
22629            bank,
22630            &parent.terminal_tokens,
22631            &parent.role_counts,
22632            parent.rng,
22633            1,
22634            None,
22635        );
22636        if let Ok(_predecessor) = &result {
22637            #[cfg(feature = "semantic-policy")]
22638            let predecessor = *_predecessor;
22639            // Publication joins the original model and output snapshots. Only
22640            // their one-use stage closes: the model and transient seals remain
22641            // owned by this Session for late original-forward/autograd reads.
22642            self.retained_initial_prefill =
22643                self.initial_prefill
22644                    .take()
22645                    .map(|mut stage| RetainedInitialPrefillContent {
22646                        scope: stage.scope,
22647                        task_identity: stage.task_identity,
22648                        task_epoch: stage.task_epoch,
22649                        model_generation: stage.model_generation,
22650                        model: stage.model_content.take().expect("verified model content"),
22651                        #[cfg(feature = "semantic-policy")]
22652                        output: stage
22653                            .output_content
22654                            .take()
22655                            .expect("verified output content"),
22656                        #[cfg(feature = "semantic-policy")]
22657                        record: InitialPrefillRecord {
22658                            predecessor,
22659                            semantic_root: header.semantic_digest,
22660                            task_identity,
22661                            task_epoch: stage.task_epoch,
22662                            task_content,
22663                            model_generation: stage.model_generation,
22664                            tokens: stage.layout.prefill_tokens,
22665                            mapping: stage.layout.prefill_mapping,
22666                        },
22667                        captured: stage.captured_content,
22668                    });
22669        } else {
22670            self.poisoned = true;
22671        }
22672        result
22673    }
22674
22675    /// Reconstruct native material into this fresh admitted owner. This performs
22676    /// actual graph insert/seal and native state hashing; it does not establish
22677    /// an episode's provenance, current use rights, or model replay equivalence.
22678    /// The trusted execution importer must verify those before issuing TaskUse.
22679    pub fn restore_state_material(
22680        &mut self,
22681        bytes: &[u8],
22682    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
22683        self.restore_state_material_inner(bytes, None)
22684    }
22685
22686    /// Cold-create a private successor from an authentic complete checkpoint.
22687    /// Only the explicit phase and producer-authorized optimizer reset change;
22688    /// all effective parameters, caches, native records and progress are copied.
22689    /// The public Controller retains the old runnable owner until durable handoff.
22690    pub fn restore_learning_phase_material(
22691        &mut self,
22692        bytes: &[u8],
22693        transition: &SemanticLearningPhaseTransition,
22694    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
22695        self.restore_state_material_inner(bytes, Some(transition))
22696    }
22697
22698    fn restore_state_material_inner(
22699        &mut self,
22700        bytes: &[u8],
22701        transition: Option<&SemanticLearningPhaseTransition>,
22702    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
22703        self.ensure_rebindable()?;
22704        if self.publication.is_some() || self.captured.is_some() || self.task.is_none() {
22705            return Err(publication_input_error(
22706                "state restoration requires a fresh uncaptured task-bound Session",
22707            ));
22708        }
22709        let mut material = PublicationMaterial::decode(bytes)?;
22710        let header = material.bank.header;
22711        let mut rng = header.rng_binding()?;
22712        let mut fold = None;
22713        if let Some(transition) = transition {
22714            let (record, absorption) = transition.apply(&mut material)?;
22715            material.learning_phases.push(record);
22716            fold = absorption;
22717        }
22718        if fold.is_some() {
22719            let generation = header
22720                .model_generation
22721                .checked_add(1)
22722                .filter(|n| *n <= u64::from(u32::MAX))
22723                .ok_or(SemanticTransitionError::GenerationExhausted)?;
22724            material.bank.header.model_generation = generation;
22725            material.bank.header.neural_generation = header
22726                .neural_generation
22727                .checked_add(1)
22728                .ok_or(SemanticTransitionError::GenerationExhausted)?;
22729            material.bank.state.model_generation = generation as u32;
22730            rng.model_generation = generation as u32;
22731        }
22732        if header.authority_generation == 0 {
22733            return Err(publication_input_error(
22734                "restored RNG or task generation exceeds its native domain",
22735            ));
22736        }
22737        // Validate immutable task statements before any graph mutation. Symbols
22738        // are compared through admitted canonical bytes, never process IDs.
22739        for (index, statement) in self.feedback_statement_bytes()?.iter().enumerate() {
22740            let saved = material
22741                .ranges
22742                .iter()
22743                .find(|item| item.range.role == 16 && item.range.index == index as u64)
22744                .ok_or(SemanticTransitionError::ObservationMismatch)?;
22745            if saved.bytes != *statement {
22746                return Err(publication_input_error(
22747                    "restored feedback statement differs from the actual admitted task",
22748                ));
22749            }
22750        }
22751        let result = (|| {
22752            let root = self
22753                .graph
22754                .restore_root(&material.graph)
22755                .map_err(SemanticTransitionError::Semantic)?;
22756            let snapshot = self
22757                .graph
22758                .snapshot(crate::SemanticView::Root(root))
22759                .map_err(SemanticTransitionError::Semantic)?;
22760            let admission = self
22761                .graph
22762                .admission()
22763                .ok_or(SemanticTransitionError::NotBound)?;
22764            let codebooks = ActionCodebooks::derive(
22765                admission,
22766                self.graph.transition_arena()[1],
22767                self.task
22768                    .as_ref()
22769                    .and_then(|(task, _)| task.spec.program.editable_program()),
22770            )?;
22771            if codebooks.input_cells != self.codebooks.input_cells
22772                || codebooks.words.len() != self.device_codebooks.len()
22773            {
22774                return Err(publication_input_error(
22775                    "restored action catalogue changes its allocated shape",
22776                ));
22777            }
22778            let (task, device) = self
22779                .task
22780                .as_mut()
22781                .ok_or(SemanticTransitionError::NotBound)?;
22782            task.admission_identity = admission.identity();
22783            if task.identity() != material.contract.task_identity {
22784                return Err(publication_input_error(
22785                    "restored native task differs from its original complete admission",
22786                ));
22787            }
22788            let words = task.words(self.graph.transition_arena()[1]);
22789            self.provider
22790                .htod_sync_copy_into_tracked(&words, device)
22791                .map_err(|error| runtime_error("restored task owner upload", error))?;
22792            let codebook = material
22793                .ranges
22794                .iter_mut()
22795                .find(|item| item.range.role == 48)
22796                .ok_or(SemanticTransitionError::ObservationMismatch)?;
22797            codebook.bytes = relocate_publication_codebooks(&codebook.bytes, &codebooks.words)?;
22798            self.codebooks = codebooks;
22799            self.upload_cold_codebooks()?;
22800            self.root = root;
22801            self.base_snapshot = snapshot;
22802            self.task_epoch = header.authority_generation;
22803            self.learning_phases = material.learning_phases;
22804            let mut instance = [0; 32];
22805            getrandom::fill(&mut instance)
22806                .map_err(|error| runtime_error("restored instance entropy", error))?;
22807            let instance = Identity256::from_bytes(instance);
22808            if instance == header.instance {
22809                return Err(publication_input_error(
22810                    "restoration must create a fresh instance",
22811                ));
22812            }
22813            let mut contract = material.contract;
22814            contract.semantic_owner = self.graph.transition_arena()[1];
22815            let plans: Vec<_> = material
22816                .ranges
22817                .into_iter()
22818                .map(|item| PublicationAllocationPlan {
22819                    role: item.range.role,
22820                    index: item.range.index,
22821                    capacity: item.capacity,
22822                    length: item.bytes.len(),
22823                    logical_begin: item.range.logical_begin,
22824                    logical_end: item.range.logical_end,
22825                    payload: if matches!(item.range.role, 18..=25) {
22826                        PublicationPayload::Uncomputed
22827                    } else {
22828                        PublicationPayload::Metadata(item.bytes)
22829                    },
22830                })
22831                .collect();
22832            let model_payloads = material
22833                .model_allocations
22834                .into_iter()
22835                .map(PublicationPayload::Metadata)
22836                .collect::<Vec<_>>();
22837            let (storage, uploads) = PublicationStorage::allocate(
22838                &self.provider,
22839                &plans,
22840                material.layouts,
22841                material.model_memory,
22842                &model_payloads,
22843                contract,
22844                &material.terminals,
22845                instance,
22846            )?;
22847            material.bank.header.abi = 0;
22848            material.bank.header.instance = instance;
22849            material.bank.header.recovered_instance = header.instance;
22850            material.bank.header.sealed_epoch = 0;
22851            material.bank.header.base_word = 0;
22852            material.bank.header.publication_word = 0;
22853            material.bank.header.semantic_owner = contract.semantic_owner;
22854            material.bank.header.semantic_slot = u64::from(root.slot());
22855            material.bank.header.semantic_generation = root.generation();
22856            material.bank.header.neural_bank = 0;
22857            // Historical receipts and feedback stay unchanged. Only the live
22858            // descriptor is rebound by initialize_publication; its kernel checks
22859            // fresh native hashes against the saved logical/state expectations.
22860            self.publication = Some(Arc::new(storage));
22861            self.publication_uploads = uploads;
22862            let restored = self.initialize_publication(
22863                material.bank,
22864                &material.terminals,
22865                &material.role_counts,
22866                rng,
22867                if fold.is_some() {
22868                    7
22869                } else if transition.is_some() {
22870                    5
22871                } else {
22872                    4
22873                },
22874                fold.as_ref(),
22875            )?;
22876            if transition.is_none()
22877                && (restored.logical_digest != header.logical_digest
22878                    || restored.state_digest != header.state_digest)
22879            {
22880                return Err(SemanticTransitionError::ObservationMismatch);
22881            }
22882            Ok(restored)
22883        })();
22884        if result.is_err() {
22885            self.poisoned = true;
22886        }
22887        result
22888    }
22889
22890    /// Actual phase lineage owned by this Session. This is a cold metadata read,
22891    /// not a scientific acceptance result or permission to execute training.
22892    pub fn learning_phase_history(&self) -> &[SemanticLearningPhaseRecord] {
22893        &self.learning_phases
22894    }
22895
22896    /// Admit a new immutable training arena after an exact cold restore, while
22897    /// its Session is still private. The saved publication is the only source
22898    /// of model, replay, receipt and optimizer bytes; only the live task
22899    /// authority binding and its runtime contract are regenerated.
22900    pub fn rebind_restored_training_arena(
22901        &mut self,
22902        source: &[u8],
22903        witness: SemanticTaskGoalWitness,
22904        rows: Vec<SemanticTrainingViewRow>,
22905        objective: SemanticTrainingObjective,
22906    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
22907        self.ensure_quiescent()?;
22908        if self.poisoned
22909            || self.captured.is_some()
22910            || !self.readers.is_empty()
22911            || self.training_views.is_some()
22912            || self.task.is_none()
22913            || self.publication.is_none()
22914        {
22915            return Err(publication_input_error(
22916                "training arena transfer requires one private restored publication",
22917            ));
22918        }
22919        self.task_objective_law()
22920            .ok_or(SemanticTransitionError::NotBound)?
22921            .require_objective(&objective)?;
22922        let result = (|| {
22923            let mut material = PublicationMaterial::decode(source)?;
22924            material.require_successful_recompute()?;
22925            let original = material.bank.header;
22926            let restored = self.read_publication_header(0)?;
22927            if restored.recovered_instance != original.instance
22928                || restored.instance == original.instance
22929                || restored.publication_word != 0
22930                || restored.logical_digest != original.logical_digest
22931                || restored.state_digest != original.state_digest
22932                || self.task_epoch != original.authority_generation
22933            {
22934                return Err(publication_input_error(
22935                    "training arena source is not the exact private cold restoration",
22936                ));
22937            }
22938            let (task, _) = self
22939                .task
22940                .as_ref()
22941                .ok_or(SemanticTransitionError::NotBound)?;
22942            let old_witness = task.goal_witness.ok_or(SemanticTransitionError::NotBound)?;
22943            if task.identity() != material.contract.task_identity
22944                || witness.semantic_root != old_witness.semantic_root
22945                || witness.mandatory_link_count == 0
22946                || witness.constraint_count == 0
22947                || witness
22948                    .authority_root
22949                    .as_bytes()
22950                    .iter()
22951                    .all(|byte| *byte == 0)
22952                || witness
22953                    .mandatory_links_root
22954                    .as_bytes()
22955                    .iter()
22956                    .all(|byte| *byte == 0)
22957                || witness
22958                    .constraints_root
22959                    .as_bytes()
22960                    .iter()
22961                    .all(|byte| *byte == 0)
22962            {
22963                return Err(publication_input_error(
22964                    "training arena transfer changed the original task content or semantic goal",
22965                ));
22966            }
22967            let next_epoch = self
22968                .task_epoch
22969                .checked_add(1)
22970                .ok_or(SemanticTransitionError::GenerationExhausted)?;
22971            let model_mode = material.model_numerical_mode()?.to_vec();
22972            let (task, device) = self
22973                .task
22974                .as_mut()
22975                .ok_or(SemanticTransitionError::NotBound)?;
22976            task.goal_witness = Some(witness);
22977            let task_identity = task.identity();
22978            if task_identity == material.contract.task_identity {
22979                return Err(publication_input_error(
22980                    "training arena transfer requires a new current authority binding",
22981                ));
22982            }
22983            let words = task.words(self.graph.transition_arena()[1]);
22984            self.provider
22985                .htod_sync_copy_into_tracked(&words, device)
22986                .map_err(|error| runtime_error("training arena task owner upload", error))?;
22987            self.training_views = Some(SemanticTrainingViewArena::allocate(
22988                &self.provider,
22989                &self.domain,
22990                rows,
22991                objective,
22992                task.spec.training_domain.as_ref().ok_or_else(|| {
22993                    publication_input_error(
22994                        "training arena transfer requires the original pre-action input domain",
22995                    )
22996                })?,
22997                task_identity,
22998                task.content().0,
22999                task.content().1,
23000            )?);
23001            material.contract.task_identity = task_identity;
23002            material.contract.authority_generation = next_epoch;
23003            material.contract.semantic_owner = self.graph.transition_arena()[1];
23004            let capacities = material
23005                .ranges
23006                .iter()
23007                .filter(|item| item.range.role != 43)
23008                .map(|item| (item.range.role, item.range.index, item.capacity))
23009                .collect();
23010            let runtime = initial_runtime_contract_record(
23011                material.contract,
23012                &material.role_counts,
23013                &material.terminals,
23014                &material.layouts,
23015                capacities,
23016                &model_mode,
23017                &material.model_memory,
23018            )?;
23019            let runtime_range = material
23020                .ranges
23021                .iter_mut()
23022                .find(|item| item.range.role == 43 && item.range.index == 0)
23023                .ok_or(SemanticTransitionError::ObservationMismatch)?;
23024            if runtime.bytes.len() > runtime_range.capacity {
23025                return Err(publication_input_error(
23026                    "training arena runtime contract exceeds its retained allocation",
23027                ));
23028            }
23029            runtime_range.bytes = runtime.bytes;
23030            let plans = material
23031                .ranges
23032                .into_iter()
23033                .map(|item| PublicationAllocationPlan {
23034                    role: item.range.role,
23035                    index: item.range.index,
23036                    capacity: item.capacity,
23037                    length: item.bytes.len(),
23038                    logical_begin: item.range.logical_begin,
23039                    logical_end: item.range.logical_end,
23040                    payload: if matches!(item.range.role, 18..=25) {
23041                        PublicationPayload::Uncomputed
23042                    } else {
23043                        PublicationPayload::Metadata(item.bytes)
23044                    },
23045                })
23046                .collect::<Vec<_>>();
23047            let model_payloads = material
23048                .model_allocations
23049                .into_iter()
23050                .map(PublicationPayload::Metadata)
23051                .collect::<Vec<_>>();
23052            let mut instance = [0u8; 32];
23053            getrandom::fill(&mut instance)
23054                .map_err(|error| runtime_error("training arena instance entropy", error))?;
23055            let instance = Identity256::from_bytes(instance);
23056            if instance == original.instance || instance == restored.instance {
23057                return Err(publication_input_error(
23058                    "training arena requires a fresh instance",
23059                ));
23060            }
23061            let (storage, uploads) = PublicationStorage::allocate(
23062                &self.provider,
23063                &plans,
23064                material.layouts,
23065                material.model_memory,
23066                &model_payloads,
23067                material.contract,
23068                &material.terminals,
23069                instance,
23070            )?;
23071            let mut bank = material.bank;
23072            bank.header.abi = 0;
23073            bank.header.instance = instance;
23074            bank.header.recovered_instance = original.instance;
23075            bank.header.sealed_epoch = 0;
23076            bank.header.base_word = 0;
23077            bank.header.publication_word = 0;
23078            bank.header.semantic_owner = material.contract.semantic_owner;
23079            bank.header.semantic_slot = u64::from(self.root.slot());
23080            bank.header.semantic_generation = self.root.generation();
23081            bank.header.neural_bank = 0;
23082            bank.header.authority_generation = next_epoch;
23083            self.publication = Some(Arc::new(storage));
23084            self.publication_uploads = uploads;
23085            self.task_epoch = next_epoch;
23086            let published = self.initialize_publication(
23087                bank,
23088                &material.terminals,
23089                &material.role_counts,
23090                original.rng_binding()?,
23091                5,
23092                None,
23093            )?;
23094            if published.logical_digest == original.logical_digest
23095                || published.state_digest == original.state_digest
23096            {
23097                return Err(SemanticTransitionError::ObservationMismatch);
23098            }
23099            Ok(published)
23100        })();
23101        if result.is_err() {
23102            self.poisoned = true;
23103        }
23104        result
23105    }
23106
23107    /// Re-read the selected publication after its external model owner has been
23108    /// reconstructed and prove that it is still the fresh instance recovered
23109    /// from these exact original logical and state roots.
23110    pub fn verify_restored_state_material(
23111        &mut self,
23112        lease: &SemanticPublishedLease,
23113        bytes: &[u8],
23114    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
23115        let expected = PublicationMaterial::decode(bytes)?;
23116        let actual = PublicationMaterial::decode(&self.published_state_material(lease)?)?;
23117        if expected.learning_phases != actual.learning_phases {
23118            return Err(publication_input_error(
23119                "checkpoint restore changed retained learning-phase history",
23120            ));
23121        }
23122        let expected = expected.bank.header;
23123        let header = actual.bank.header;
23124        if header.instance == expected.instance
23125            || header.recovered_instance != expected.instance
23126            || header.publication_word != 0
23127            || header.logical_digest != expected.logical_digest
23128            || header.state_digest != expected.state_digest
23129        {
23130            return Err(publication_input_error(
23131                "checkpoint restore no longer owns the exact fresh recovered publication",
23132            ));
23133        }
23134        self.published_identity(lease)
23135    }
23136
23137    /// Snapshot the original prefill while its model and output producers are
23138    /// still owned. Later checkpoints reuse these exact seals, never a new
23139    /// baseline from a post-action model or restored publication.
23140    pub fn checkpoint_initial_prefill_material(
23141        &mut self,
23142        lease: &SemanticPublishedLease,
23143    ) -> Result<(Vec<u8>, bool), SemanticTransitionError> {
23144        self.ensure_quiescent()?;
23145        self.checked_reader(lease)?;
23146        #[cfg(feature = "semantic-policy")]
23147        if let Some(record) = self
23148            .retained_initial_prefill
23149            .as_ref()
23150            .map(|retained| retained.record.clone())
23151        {
23152            let content = self
23153                .original_initial_prefill_content(
23154                    record.predecessor,
23155                    record.semantic_root,
23156                    record.tokens.len() as u64,
23157                    record.model_generation,
23158                    record.task_identity,
23159                    record.task_content,
23160                )?
23161                .ok_or(SemanticTransitionError::ObservationMismatch)?;
23162            if let Some(saved) = &self.checkpoint_initial_prefill {
23163                if saved.original != record.predecessor || saved.content != content {
23164                    self.poisoned = true;
23165                    return Err(SemanticTransitionError::ObservationMismatch);
23166                }
23167            } else {
23168                self.checkpoint_initial_prefill = Some(CheckpointInitialPrefill {
23169                    original: record.predecessor,
23170                    content,
23171                    recovery_referent: None,
23172                });
23173            }
23174        }
23175        Ok((
23176            CheckpointInitialPrefill::encode_section(self.checkpoint_initial_prefill.as_ref())?,
23177            self.checkpoint_initial_prefill.is_some(),
23178        ))
23179    }
23180
23181    pub fn verify_checkpoint_initial_prefill_source(
23182        section: &[u8],
23183        native: &[u8],
23184        task_identity: Identity256,
23185        task_epoch: u64,
23186        task_content: SemanticTaskContentIdentity,
23187        require_original_publication: bool,
23188    ) -> Result<bool, SemanticTransitionError> {
23189        let Some(prefill) = CheckpointInitialPrefill::decode_section(section)? else {
23190            return Ok(false);
23191        };
23192        let material = PublicationMaterial::decode(native)?;
23193        let header = material.bank.header;
23194        let original = SemanticPublishedIdentity {
23195            instance: header.instance,
23196            word: header.publication_word,
23197            logical_digest: header.logical_digest,
23198            state_digest: header.state_digest,
23199        };
23200        if material.contract.task_identity != task_identity
23201            || prefill.original.word != 0
23202            || (require_original_publication && prefill.original != original)
23203        {
23204            return Err(publication_input_error(
23205                "checkpoint initial prefill names another original publication or task",
23206            ));
23207        }
23208        if prefill.original == original {
23209            prefill.verify_content(
23210                header.semantic_digest,
23211                header.model_generation,
23212                task_identity,
23213                task_epoch,
23214                task_content,
23215                header.prefix_extent,
23216            )?;
23217        } else {
23218            prefill.verify_recorded_content(task_identity, task_epoch, task_content)?;
23219        }
23220        Ok(true)
23221    }
23222
23223    /// Bind a restored pre-action publication to the exact original prefill
23224    /// section and compact reference of the full checkpoint that carried it.
23225    pub fn bind_restored_checkpoint_initial_prefill(
23226        &mut self,
23227        lease: &SemanticPublishedLease,
23228        native: &[u8],
23229        section: &[u8],
23230        referent: &[u8],
23231    ) -> Result<(), SemanticTransitionError> {
23232        if self.checkpoint_initial_prefill.is_some() || referent.is_empty() {
23233            return Err(publication_input_error(
23234                "restored initial prefill is already bound or has no source reference",
23235            ));
23236        }
23237        self.verify_restored_state_material(lease, native)?;
23238        let original_header = PublicationMaterial::decode(native)?.bank.header;
23239        let original = SemanticPublishedIdentity {
23240            instance: original_header.instance,
23241            word: original_header.publication_word,
23242            logical_digest: original_header.logical_digest,
23243            state_digest: original_header.state_digest,
23244        };
23245        let mut prefill = CheckpointInitialPrefill::decode_section(section)?.ok_or_else(|| {
23246            publication_input_error("pre-action checkpoint has no original initial prefill")
23247        })?;
23248        let task_identity = self
23249            .task_evaluation_identity()
23250            .ok_or(SemanticTransitionError::NotBound)?;
23251        let (task_content, _) = self
23252            .task_content()
23253            .ok_or(SemanticTransitionError::NotBound)?;
23254        if prefill.original != original {
23255            return Err(publication_input_error(
23256                "checkpoint prefill names another original publication",
23257            ));
23258        }
23259        prefill.verify_content(
23260            original_header.semantic_digest,
23261            original_header.model_generation,
23262            task_identity,
23263            self.task_epoch,
23264            task_content,
23265            original_header.prefix_extent,
23266        )?;
23267        prefill.recovery_referent = Some(referent.to_vec());
23268        self.checkpoint_initial_prefill = Some(prefill);
23269        Ok(())
23270    }
23271
23272    fn initialize_publication(
23273        &mut self,
23274        bank: PublicationBank,
23275        terminal_tokens: &[u64],
23276        role_counts: &[u64; 55],
23277        rng: SemanticRngBinding,
23278        operation: u64,
23279        fold: Option<&learning_phase::LearningFoldPlan>,
23280    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
23281        let storage = Arc::clone(
23282            self.publication
23283                .as_ref()
23284                .expect("installed publication owner"),
23285        );
23286        let mut recorder = self.domain.new_strict_recorder();
23287        storage.record(&mut recorder);
23288        for (_, payload) in &self.publication_uploads {
23289            if let PublicationPayload::Tensor(tensor) = payload {
23290                if let Some(source) = &tensor.source {
23291                    recorder.read(source);
23292                }
23293            }
23294        }
23295        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
23296            for allocation in &storage.allocations {
23297                // A genuine empty model buffer retains an owner and layout,
23298                // but has no device pointer on which to submit a memory write.
23299                if allocation.is_empty() {
23300                    continue;
23301                }
23302                // SAFETY: all actual fixed allocations were recorded before this
23303                // first may-enqueue boundary; zero bytes do not mark a bank valid.
23304                unsafe {
23305                    sys::cuMemsetD8Async(
23306                        allocation.device_ptr_value(),
23307                        0,
23308                        allocation.len(),
23309                        enqueue.stream().cu_stream(),
23310                    )
23311                }
23312                .result()
23313                .map_err(|error| XlogError::Kernel(error.to_string()))?;
23314            }
23315            for (slot, payload) in &self.publication_uploads {
23316                if let PublicationPayload::Tensor(tensor) = payload {
23317                    if let Some(source) = &tensor.source {
23318                        let destination = &storage.allocations[*slot];
23319                        let layout = if tensor.layout.role == 0 {
23320                            &tensor.layout
23321                        } else {
23322                            &storage.layouts[&(tensor.layout.role, tensor.layout.index)]
23323                        };
23324                        for (source_offset, destination_offset, bytes) in
23325                            tensor_copy_plan(&tensor.layout, layout)
23326                                .map_err(|error| XlogError::Kernel(error.to_string()))?
23327                        {
23328                            unsafe {
23329                                sys::cuMemcpyDtoDAsync_v2(
23330                                    destination.device_ptr_value() + destination_offset,
23331                                    *source.device_ptr() + source_offset,
23332                                    bytes,
23333                                    enqueue.stream().cu_stream(),
23334                                )
23335                            }
23336                            .result()
23337                            .map_err(|error| XlogError::Kernel(error.to_string()))?;
23338                        }
23339                    }
23340                }
23341            }
23342            Ok::<(), XlogError>(())
23343        })?;
23344        wait_on_stream(
23345            &self.stream,
23346            &mut self.poisoned,
23347            &mut self.stream_waits,
23348            "cold publication tensor snapshot",
23349            CudaStream::synchronize,
23350        )?;
23351        for (slot, payload) in &self.publication_uploads {
23352            if let PublicationPayload::Metadata(bytes) = payload {
23353                if !bytes.is_empty() {
23354                    let mut destination = storage.allocations[*slot].view().slice(..bytes.len());
23355                    self.provider
23356                        .htod_launch_metadata_sync_copy_into(bytes, &mut destination)
23357                        .map_err(|error| runtime_error("cold publication record upload", error))?;
23358                }
23359            }
23360        }
23361        if let Some(fold) = fold {
23362            self.apply_learning_fold(fold)?;
23363        }
23364        upload_publication(&self.provider, &[bank], &storage.banks[0])?;
23365        upload_publication(&self.provider, &[bank], &storage.banks[1])?;
23366        for bank in 0..2 {
23367            upload_publication(
23368                &self.provider,
23369                &storage.bank_templates[bank],
23370                &storage.directories[bank],
23371            )?;
23372        }
23373        let entries: Vec<_> = storage
23374            .allocations
23375            .iter()
23376            .map(|allocation| PublicationStorageEntry {
23377                pointer: allocation.device_ptr_value(),
23378                bytes: allocation.len() as u64,
23379                generation: 1,
23380            })
23381            .collect();
23382        upload_publication(&self.provider, &entries, &storage.storage)?;
23383        upload_publication(&self.provider, &[storage.contract_value], &storage.contract)?;
23384        upload_publication(&self.provider, terminal_tokens, &storage.terminals)?;
23385        let counts: Vec<_> = role_counts
23386            .iter()
23387            .enumerate()
23388            .map(|(index, &count)| PublicationRoleCount {
23389                role: index as u64 + 1,
23390                count,
23391            })
23392            .collect();
23393        upload_publication(&self.provider, &counts, &storage.role_counts)?;
23394        upload_publication(
23395            &self.provider,
23396            &[PendingContinuation {
23397                abi: 1,
23398                ranges: storage.continuation_directory.device_ptr_value(),
23399                range_count: storage.continuation_templates.len() as u64,
23400                ..PendingContinuation::default()
23401            }],
23402            &storage.continuation,
23403        )?;
23404        upload_publication(
23405            &self.provider,
23406            &storage.continuation_templates,
23407            &storage.continuation_directory,
23408        )?;
23409        upload_publication(
23410            &self.provider,
23411            &[PublicationControl {
23412                abi: 1,
23413                instance: storage.instance,
23414                banks: storage.banks.each_ref().map(|bank| bank.device_ptr_value()),
23415                directories: storage
23416                    .directories
23417                    .each_ref()
23418                    .map(|directory| directory.device_ptr_value()),
23419                storage: storage.storage.device_ptr_value(),
23420                storage_count: storage.allocations.len() as u64,
23421                contract: storage.contract.device_ptr_value(),
23422                continuation: storage.continuation.device_ptr_value(),
23423                ..PublicationControl::default()
23424            }],
23425            &storage.control,
23426        )?;
23427        self.upload_rng_state(self.binding(), rng)?;
23428        self.publication_command(operation, None)?;
23429        let control = self.publication_read(storage.control.view())?[0];
23430        if control.refusal != 0 {
23431            return Err(SemanticTransitionError::PublicationRefused {
23432                status: control.refusal,
23433            });
23434        }
23435        let header = self.read_publication_header(0)?;
23436        if header.abi != 1
23437            || header.instance != storage.instance
23438            || header.publication_word != 0
23439            || control.word != 0
23440            || header.model_geometry_digest != bank.header.model_geometry_digest
23441            || (operation == 4
23442                && header.model_numerical_digest != bank.header.model_numerical_digest)
23443        {
23444            return Err(SemanticTransitionError::ObservationMismatch);
23445        }
23446        self.publication_uploads.clear();
23447        self.rng = Some(rng);
23448        self.next_proposal = u64::from(rng.proposal);
23449        Ok(SemanticPublishedIdentity {
23450            instance: header.instance,
23451            word: header.publication_word,
23452            logical_digest: header.logical_digest,
23453            state_digest: header.state_digest,
23454        })
23455    }
23456
23457    fn publication_command(
23458        &mut self,
23459        operation: u64,
23460        token: Option<u64>,
23461    ) -> Result<(), SemanticTransitionError> {
23462        let storage = self
23463            .publication
23464            .as_ref()
23465            .ok_or(SemanticTransitionError::NotBound)?;
23466        let mut descriptor = self.descriptor();
23467        descriptor.publication = PublicationCommand {
23468            control: storage.control.device_ptr_value(),
23469            operation,
23470            lease: token.map_or(0, |token| self.readers[&token].device.device_ptr_value()),
23471        };
23472        let mut recorder = self.kernel_recorder();
23473        if let Some(token) = token {
23474            recorder.read_write(&self.readers[&token].device);
23475        }
23476        let execute = self.execute.clone();
23477        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |stream| {
23478            // SAFETY: command, bank directories, storage and optional lease all
23479            // have actual recorded owners, and the common descriptor ABI is fixed.
23480            unsafe {
23481                execute.launch_in(
23482                    stream,
23483                    LaunchConfig {
23484                        grid_dim: (1, 1, 1),
23485                        block_dim: (256, 1, 1),
23486                        shared_mem_bytes: 0,
23487                    },
23488                    (descriptor,),
23489                )
23490            }
23491            .map_err(|error| XlogError::Kernel(error.to_string()))
23492        })?;
23493        wait_on_stream(
23494            &self.stream,
23495            &mut self.poisoned,
23496            &mut self.stream_waits,
23497            "publication command completion",
23498            CudaStream::synchronize,
23499        )
23500    }
23501
23502    fn publication_read<T: DeviceRepr + Copy>(
23503        &mut self,
23504        source: DeviceMemoryView<T>,
23505    ) -> Result<Vec<T>, SemanticTransitionError> {
23506        let bytes = source
23507            .len()
23508            .checked_mul(size_of::<T>())
23509            .ok_or_else(|| publication_input_error("publication metadata read overflow"))?;
23510        let mut pinned = crate::device::PinnedHostBuffer::new(&self.stream, bytes)
23511            .map_err(|error| runtime_error("publication metadata staging", error))?;
23512        let mut recorder = self.domain.new_strict_recorder();
23513        recorder.read(&source);
23514        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |stream| {
23515            // SAFETY: recorder retains the complete source; pinned owner retains
23516            // its destination across enqueue failures and the final stream wait.
23517            unsafe {
23518                pinned.enqueue(stream.stream(), |destination| {
23519                    sys::cuMemcpyDtoHAsync_v2(
23520                        destination.cast(),
23521                        *source.device_ptr(),
23522                        bytes,
23523                        stream.stream().cu_stream(),
23524                    )
23525                    .result()
23526                })
23527            }
23528            .map_err(|error| XlogError::Kernel(error.to_string()))
23529        })?;
23530        wait_on_stream(
23531            &self.stream,
23532            &mut self.poisoned,
23533            &mut self.stream_waits,
23534            "publication metadata read completion",
23535            CudaStream::synchronize,
23536        )?;
23537        // SAFETY: the entire integral ABI slice completed its recorded copy.
23538        let result = unsafe { pinned.read_vec::<T>(source.len()) }
23539            .map_err(|error| runtime_error("publication metadata read", error))?;
23540        self.provider
23541            .record_final_observation_transfer(bytes as u64);
23542        Ok(result)
23543    }
23544
23545    fn read_publication_header(
23546        &mut self,
23547        bank: usize,
23548    ) -> Result<PublicationHeader, SemanticTransitionError> {
23549        let storage = Arc::clone(
23550            self.publication
23551                .as_ref()
23552                .ok_or(SemanticTransitionError::NotBound)?,
23553        );
23554        // SAFETY: PublicationBank starts with one initialized fixed Header and
23555        // the tracked allocation has sufficient alignment and checked ABI extent.
23556        let view = unsafe {
23557            storage.banks[bank]
23558                .view()
23559                .cast::<u8>()
23560                .expect("byte-aligned bank ABI")
23561                .slice(..size_of::<PublicationHeader>())
23562                .cast::<PublicationHeader>()
23563                .expect("aligned fixed header ABI")
23564        };
23565        Ok(self.publication_read(view)?[0])
23566    }
23567
23568    pub fn acquire(&mut self) -> Result<SemanticPublishedLease, SemanticTransitionError> {
23569        if self.pending {
23570            let proposal = u32::try_from(self.next_proposal)
23571                .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
23572            // Complete and reconcile the actual CAS outcome before returning a
23573            // reader. A failed publication can never return the old base as progress.
23574            self.observe(proposal)?.into_published()?;
23575        }
23576        self.ensure_quiescent()?;
23577        let storage = Arc::clone(
23578            self.publication
23579                .as_ref()
23580                .ok_or(SemanticTransitionError::NotBound)?,
23581        );
23582        let token = self
23583            .next_reader
23584            .checked_add(1)
23585            .ok_or(SemanticTransitionError::GenerationExhausted)?;
23586        self.next_reader = token;
23587        let device = allocate_publication(&self.provider, 1)?;
23588        self.steps.insert(token, StepContentStorage::new());
23589        self.readers.insert(
23590            token,
23591            PublishedReader {
23592                device,
23593                aliases: Arc::new(()),
23594                consumer_streams: BTreeSet::new(),
23595            },
23596        );
23597        // Lease storage is retained before upload or Acquire can enqueue.
23598        if let Err(error) = upload_publication(
23599            &self.provider,
23600            &[PublicationLease::default()],
23601            &self.readers[&token].device,
23602        ) {
23603            self.poisoned = true;
23604            return Err(error);
23605        }
23606        self.publication_command(2, Some(token))?;
23607        let lease = self.publication_read(self.readers[&token].device.view())?[0];
23608        if lease.status != 0 {
23609            self.readers.remove(&token);
23610            self.steps.remove(&token);
23611            return Err(SemanticTransitionError::PublicationRefused {
23612                status: lease.status,
23613            });
23614        }
23615        if lease.abi != 1
23616            || lease.active != 1
23617            || lease.instance != storage.instance
23618            || lease.bank > 1
23619            || lease.bank != (lease.word & 1)
23620            || lease.epoch != lease.word >> 1
23621        {
23622            self.poisoned = true;
23623            return Err(SemanticTransitionError::ObservationMismatch);
23624        }
23625        let header = self.read_publication_header(lease.bank as usize)?;
23626        let directory = self.publication_read(storage.directories[lease.bank as usize].view())?;
23627        // SAFETY: source follows Header in the checked fixed bank ABI; no private
23628        // task observation/result bytes are included in this metadata transfer.
23629        let source_view = unsafe {
23630            storage.banks[lease.bank as usize]
23631                .view()
23632                .cast::<u8>()
23633                .expect("byte-aligned bank ABI")
23634                .slice(
23635                    size_of::<PublicationHeader>()
23636                        ..size_of::<PublicationHeader>() + 32 * size_of::<SemanticTextSlot>(),
23637                )
23638                .cast::<SemanticTextSlot>()
23639                .expect("aligned fixed source ABI")
23640        };
23641        let source: [SemanticTextSlot; 32] = self
23642            .publication_read(source_view)?
23643            .try_into()
23644            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
23645        if header.abi != 1
23646            || header.instance != lease.instance
23647            || header.publication_word != lease.word
23648            || header.sealed_epoch != lease.epoch
23649            || header.range_count as usize != directory.len()
23650        {
23651            self.poisoned = true;
23652            return Err(SemanticTransitionError::ObservationMismatch);
23653        }
23654        let identity = SemanticPublishedIdentity {
23655            instance: lease.instance,
23656            word: lease.word,
23657            logical_digest: header.logical_digest,
23658            state_digest: header.state_digest,
23659        };
23660        self.steps
23661            .get_mut(&token)
23662            .expect("installed acquisition step")
23663            .identity = Some(identity);
23664        Ok(SemanticPublishedLease {
23665            issuer: Arc::clone(&self.publication_issuer),
23666            token,
23667            identity,
23668            header,
23669            source,
23670            directory,
23671            active: true,
23672        })
23673    }
23674
23675    fn checked_reader(
23676        &self,
23677        lease: &SemanticPublishedLease,
23678    ) -> Result<&PublishedReader, SemanticTransitionError> {
23679        self.ensure_quiescent()?;
23680        if !lease.active || !Arc::ptr_eq(&lease.issuer, &self.publication_issuer) {
23681            return Err(publication_input_error(
23682                "lease is released or belongs to a different Session",
23683            ));
23684        }
23685        self.readers
23686            .get(&lease.token)
23687            .ok_or_else(|| publication_input_error("lease has no live native reader owner"))
23688    }
23689
23690    fn checked_step(
23691        &self,
23692        lease: &SemanticPublishedLease,
23693    ) -> Result<&StepContentStorage, SemanticTransitionError> {
23694        self.ensure_quiescent()?;
23695        if !Arc::ptr_eq(&lease.issuer, &self.publication_issuer) {
23696            return Err(publication_input_error(
23697                "retained step belongs to a different Session",
23698            ));
23699        }
23700        let step = self
23701            .steps
23702            .get(&lease.token)
23703            .ok_or_else(|| publication_input_error("original step has been fully released"))?;
23704        if step.identity != Some(lease.identity)
23705            || lease.active != self.readers.contains_key(&lease.token)
23706        {
23707            return Err(publication_input_error(
23708                "retained step differs from its original acquired identity",
23709            ));
23710        }
23711        Ok(step)
23712    }
23713
23714    /// Authenticate the original step even after its publication bank retires.
23715    /// This grants no publication access and refuses poisoned or released owners.
23716    pub fn retained_step_identity(
23717        &self,
23718        lease: &SemanticPublishedLease,
23719    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
23720        self.checked_step(lease)?;
23721        Ok(lease.identity)
23722    }
23723
23724    /// Prove full consumer retirement of this original publication owner.
23725    /// A retired bank alone, an abort, or a failed identity lookup is not proof
23726    /// that its retained steps, evaluations and captured executables are gone.
23727    pub fn require_retired_publication(
23728        &self,
23729        lease: &SemanticPublishedLease,
23730    ) -> Result<(), SemanticTransitionError> {
23731        self.ensure_quiescent()?;
23732        #[cfg(feature = "semantic-policy")]
23733        self.require_closed_evaluations()?;
23734        if self.is_poisoned() {
23735            return Err(SemanticTransitionError::Poisoned);
23736        }
23737        if !Arc::ptr_eq(&lease.issuer, &self.publication_issuer)
23738            || lease.active
23739            || !self.readers.is_empty()
23740            || !self.steps.is_empty()
23741            || self.captured.is_some()
23742            || self.prepared_segment.is_some()
23743            || !self.prepared_resources.is_empty()
23744        {
23745            return Err(publication_input_error(
23746                "private publication requires known full retirement of its original consumers",
23747            ));
23748        }
23749        Ok(())
23750    }
23751
23752    pub fn published_identity(
23753        &self,
23754        lease: &SemanticPublishedLease,
23755    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
23756        self.checked_reader(lease)?;
23757        Ok(lease.identity)
23758    }
23759
23760    /// The selected parent must still be the current native publication, and
23761    /// its own sealed attempt must be a successful recompute. A later publish
23762    /// invalidates this admission source; a nonpublishing refusal does not.
23763    pub fn current_recompute_state_material(
23764        &mut self,
23765        lease: &SemanticPublishedLease,
23766    ) -> Result<Vec<u8>, SemanticTransitionError> {
23767        self.checked_reader(lease)?;
23768        let storage = Arc::clone(
23769            self.publication
23770                .as_ref()
23771                .ok_or(SemanticTransitionError::NotBound)?,
23772        );
23773        let control = self.publication_read(storage.control.view())?[0];
23774        if control.abi != 1
23775            || control.instance != lease.identity.instance
23776            || control.word != lease.identity.word
23777        {
23778            return Err(publication_input_error(
23779                "selected recompute is no longer the current publication",
23780            ));
23781        }
23782        let material = self.published_state_material(lease)?;
23783        PublicationMaterial::decode(&material)?.require_successful_recompute()?;
23784        Ok(material)
23785    }
23786
23787    /// Complete ordered role/index roster from this acquired directory, not a
23788    /// prediction from role counts or a read of a newer publication. This is
23789    /// cached structural metadata; it does not certify current tensor bytes.
23790    pub fn published_range_keys(
23791        &self,
23792        lease: &SemanticPublishedLease,
23793    ) -> Result<Vec<(SemanticStateRole, u64)>, SemanticTransitionError> {
23794        self.checked_reader(lease)?;
23795        lease
23796            .directory
23797            .iter()
23798            .map(|range| {
23799                SemanticStateRole::from_code(range.role)
23800                    .map(|role| (role, range.index))
23801                    .ok_or(SemanticTransitionError::ObservationMismatch)
23802            })
23803            .collect()
23804    }
23805
23806    // These event edges are enqueue-only. The producer protocol targets the
23807    // legacy default stream; caller-declared hook writes target consumer_stream.
23808    // Every event/owner is retained before a may-enqueue boundary. No host wait
23809    // or digest/status transfer is performed on this successful path.
23810    fn order_content_inputs(
23811        &mut self,
23812        lease: &SemanticPublishedLease,
23813        consumer_stream: u64,
23814    ) -> Result<(), SemanticTransitionError> {
23815        self.readers
23816            .get_mut(&lease.token)
23817            .expect("validated publication reader")
23818            .consumer_streams
23819            .insert(consumer_stream);
23820        self.order_step_content_inputs(lease.token, consumer_stream)
23821    }
23822
23823    fn order_step_content_inputs(
23824        &mut self,
23825        reader_token: u64,
23826        consumer_stream: u64,
23827    ) -> Result<(), SemanticTransitionError> {
23828        self.steps
23829            .get_mut(&reader_token)
23830            .expect("validated content step")
23831            .consumer_streams
23832            .insert(consumer_stream);
23833        self.order_tensor_producer_inputs(consumer_stream)
23834    }
23835
23836    fn order_tensor_producer_inputs(
23837        &mut self,
23838        consumer_stream: u64,
23839    ) -> Result<(), SemanticTransitionError> {
23840        let consumer = dlpack_consumer_stream(consumer_stream)?;
23841        self.stream
23842            .context()
23843            .bind_to_thread()
23844            .map_err(|e| runtime_error("content context binding", e))?;
23845        for source in [std::ptr::null_mut(), consumer] {
23846            let event = self
23847                .stream
23848                .context()
23849                .new_event(None)
23850                .map_err(|e| runtime_error("content producer event", e))?;
23851            self.release_events.push(event);
23852            let event = self.release_events.last().expect("retained content event");
23853            // SAFETY: the controlling application supplies a live same-context
23854            // CUDA stream, after all its writers. The native stream then waits
23855            // on this exact recorded event, not on future unrelated writes.
23856            unsafe { cudarc::driver::result::event::record(event.cu_event(), source) }
23857                .map_err(|e| runtime_error("content producer event record", e))?;
23858            self.stream
23859                .wait(event)
23860                .map_err(|e| runtime_error("content producer event join", e))?;
23861        }
23862        Ok(())
23863    }
23864
23865    fn order_content_consumers(
23866        &mut self,
23867        consumer_stream: u64,
23868    ) -> Result<(), SemanticTransitionError> {
23869        let event = self
23870            .stream
23871            .context()
23872            .new_event(None)
23873            .map_err(|e| runtime_error("content guard event", e))?;
23874        self.release_events.push(event);
23875        let event = self
23876            .release_events
23877            .last()
23878            .expect("retained content guard event");
23879        // SAFETY: record follows the guard on the admitted native stream. The
23880        // consumer must enqueue all dependent reads after this method returns.
23881        // CUDA events provide the dependency without a host synchronization.
23882        unsafe {
23883            cudarc::driver::result::event::record(event.cu_event(), self.stream.cu_stream())
23884                .map_err(|e| runtime_error("content guard event record", e))?;
23885            sys::cuStreamWaitEvent(
23886                dlpack_consumer_stream(consumer_stream)?,
23887                event.cu_event(),
23888                0,
23889            )
23890            .result()
23891            .map_err(|e| runtime_error("content guard consumer join", e))?;
23892        }
23893        Ok(())
23894    }
23895
23896    /// Enqueue a live-content check against this reader's original range seals.
23897    /// Call after hooks/writers and before reads on the declared consumer stream.
23898    /// Integrity corruption invokes an unconditional device trap: the isolated
23899    /// task process must terminate, not reset or reuse its Session/tensors.
23900    /// A successful return means enqueued, not GPU-complete or accepted output.
23901    /// Concurrent external alias writes through the end of consumption are forbidden.
23902    pub fn guard_published_content(
23903        &mut self,
23904        lease: &SemanticPublishedLease,
23905        keys: &[(SemanticStateRole, u64)],
23906        consumer_stream: u64,
23907    ) -> Result<(), SemanticTransitionError> {
23908        self.checked_reader(lease)?;
23909        dlpack_consumer_stream(consumer_stream)?;
23910        let storage = Arc::clone(
23911            self.publication
23912                .as_ref()
23913                .ok_or(SemanticTransitionError::NotBound)?,
23914        );
23915        let inputs = if keys
23916            .iter()
23917            .any(|(role, _)| matches!(*role as u64, 1 | 3..=13))
23918        {
23919            self.steps[&lease.token].inputs.as_ref().map(Arc::clone)
23920        } else {
23921            None
23922        };
23923        let directory = &storage.directories[(lease.identity.word & 1) as usize];
23924        let mut distinct = BTreeSet::new();
23925        let mut ranges = Vec::with_capacity(keys.len());
23926        if keys.is_empty() {
23927            return Err(publication_input_error(
23928                "content guard requires actual publication ranges",
23929            ));
23930        }
23931        for &(role, index) in keys {
23932            let key = (role as u64, index);
23933            if !distinct.insert(key) {
23934                return Err(publication_input_error(
23935                    "content guard has duplicate publication ranges",
23936                ));
23937            }
23938            let (range_index, &range) = lease
23939                .directory
23940                .iter()
23941                .enumerate()
23942                .find(|(_, range)| (range.role, range.index) == key)
23943                .ok_or_else(|| {
23944                    publication_input_error("content guard names an absent publication range")
23945                })?;
23946            if range_index >= directory.len() {
23947                return Err(SemanticTransitionError::ObservationMismatch);
23948            }
23949            let allocation = storage
23950                .allocations
23951                .get(range.storage_slot as usize)
23952                .ok_or(SemanticTransitionError::ObservationMismatch)?;
23953            if range.generation != 1
23954                || range
23955                    .offset_bytes
23956                    .checked_add(range.length_bytes)
23957                    .is_none_or(|end| end > allocation.len() as u64)
23958            {
23959                return Err(SemanticTransitionError::ObservationMismatch);
23960            }
23961            let layout = if is_tensor_role(role as u64) {
23962                *storage
23963                    .layouts
23964                    .get(&key)
23965                    .ok_or(SemanticTransitionError::ObservationMismatch)?
23966            } else {
23967                SemanticTensorLayout::default()
23968            };
23969            // PrefixSource is sealed as raw records. Its synthetic U64 export
23970            // layout is intentionally not substituted into this hash domain.
23971            // The original seal remains on the device. Passing its host-cached
23972            // digest as a launch argument would itself be a digest transfer.
23973            ranges.push((role as u64, index, layout));
23974        }
23975        let execute = self
23976            .provider
23977            .device()
23978            .inner()
23979            .get_func(
23980                "xlog_semantic_transition",
23981                "semantic_publication_content_guard",
23982            )
23983            .ok_or_else(|| {
23984                runtime_error("kernel lookup", "publication content guard unavailable")
23985            })?;
23986        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
23987            .map_err(|e| runtime_error("content guard stream admission", e))?;
23988        let result = (|| {
23989            self.order_content_inputs(lease, consumer_stream)?;
23990            if let Some(inputs) = &inputs {
23991                // Existing guards must cover the actual exported private
23992                // inputs as well as the still-acquired publication bank.
23993                self.steps
23994                    .get_mut(&lease.token)
23995                    .expect("validated input step")
23996                    .consumer_streams
23997                    .insert(consumer_stream);
23998                inputs.verify(&self.domain, &mut self.poisoned)?;
23999            }
24000            for (role, index, layout) in ranges {
24001                let reader = self
24002                    .readers
24003                    .get(&lease.token)
24004                    .expect("validated native reader");
24005                storage.enqueue_content_guard(
24006                    &self.domain,
24007                    &mut self.poisoned,
24008                    reader.device.view(),
24009                    &execute,
24010                    role,
24011                    index,
24012                    layout,
24013                )?;
24014            }
24015            self.order_content_consumers(consumer_stream)
24016        })();
24017        if result.is_err() {
24018            self.poisoned = true;
24019        }
24020        result
24021    }
24022
24023    /// Capture private device digests after the trusted original computation,
24024    /// before public hooks. This establishes stability, never derivation or rights.
24025    /// The model owner must attach the issued witness to its original execution.
24026    /// Native feedback and fixed input aliases verify their original producer
24027    /// seals; their exact type, shape, interval and coordinate are preserved.
24028    /// Requires stream-ordered allocation support; a synchronizing allocator is
24029    /// never substituted for this enqueue-only path.
24030    pub fn capture_tensor_content(
24031        &mut self,
24032        lease: &SemanticPublishedLease,
24033        tensors: Vec<SemanticTensorInput>,
24034        consumer_stream: u64,
24035    ) -> Result<SemanticTensorContentWitness, SemanticTransitionError> {
24036        self.bind_tensor_content(lease, tensors, consumer_stream, false)
24037    }
24038
24039    /// Bind the complete live model roster to this parent's originally sealed
24040    /// model content and generation. A new reader receives a new witness, not a
24041    /// new baseline. Initial physical layout/address may differ; later verify
24042    /// retains this invocation's exact producer storage and layout. Enqueue-only.
24043    pub fn bind_model_content(
24044        &mut self,
24045        lease: &SemanticPublishedLease,
24046        tensors: Vec<SemanticTensorInput>,
24047        consumer_stream: u64,
24048    ) -> Result<SemanticTensorContentWitness, SemanticTransitionError> {
24049        self.bind_tensor_content(lease, tensors, consumer_stream, true)
24050    }
24051
24052    fn bind_tensor_content(
24053        &mut self,
24054        lease: &SemanticPublishedLease,
24055        tensors: Vec<SemanticTensorInput>,
24056        consumer_stream: u64,
24057        model: bool,
24058    ) -> Result<SemanticTensorContentWitness, SemanticTransitionError> {
24059        let empty = tensors.is_empty();
24060        let mut handoff = RetainedTensorAdmission {
24061            inputs: Some(tensors),
24062            stream: Arc::clone(self.provider.device().inner().stream()),
24063            ready: false,
24064        };
24065        self.checked_reader(lease)?;
24066        dlpack_consumer_stream(consumer_stream)?;
24067        if empty {
24068            return Err(publication_input_error(
24069                "content witness requires an actual tensor roster",
24070            ));
24071        }
24072        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
24073            .map_err(|e| runtime_error("content binding stream admission", e))?;
24074        if !self
24075            .provider
24076            .device()
24077            .inner()
24078            .stream()
24079            .context()
24080            .has_async_alloc()
24081        {
24082            return Err(publication_input_error(
24083                "device content capture requires stream-ordered CUDA allocation support",
24084            ));
24085        }
24086        // Include even rejected handoffs in final retirement. Post-import
24087        // interval/allocation errors must not hide this caller's writer stream.
24088        self.steps
24089            .get_mut(&lease.token)
24090            .expect("validated content step")
24091            .consumer_streams
24092            .insert(consumer_stream);
24093        let tensors = prepare_semantic_tensors(
24094            &self.provider,
24095            handoff
24096                .inputs
24097                .take()
24098                .expect("retained original content inputs"),
24099        )?;
24100        let reader = self
24101            .steps
24102            .get_mut(&lease.token)
24103            .expect("validated content step");
24104        let index = reader.content.len();
24105        reader.content.push(TensorContentBuffers {
24106            tensors,
24107            seals: TensorContentSeals::Captured(Vec::new()),
24108            verification_inputs: Vec::new(),
24109        });
24110        let reader = &self.steps[&lease.token];
24111        let content = &reader.content[index];
24112        validate_content_coordinates(
24113            content
24114                .tensors
24115                .iter()
24116                .map(|tensor| (tensor.layout.role, tensor.layout.index)),
24117        )?;
24118        let mut native_origins = Vec::with_capacity(content.tensors.len());
24119        for tensor in &content.tensors {
24120            let mut original = None;
24121            if !model {
24122                // Shared prefix/key-value storage can belong to older steps
24123                // too. Match the actual current step before checking foreign
24124                // private owners, preserving its original logical interval.
24125                if let Some(inputs) = &reader.inputs {
24126                    if inputs.owns_tensor(tensor)? {
24127                        original = Some(Arc::clone(inputs));
24128                    }
24129                }
24130                if original.is_none() {
24131                    for (&token, owner) in &self.steps {
24132                        if token == lease.token {
24133                            continue;
24134                        }
24135                        if let Some(inputs) = &owner.inputs {
24136                            if inputs.owns_tensor(tensor)? {
24137                                return Err(publication_input_error(
24138                                    "native step content belongs to another acquired reader",
24139                                ));
24140                            }
24141                        }
24142                    }
24143                }
24144            }
24145            if original.is_none() {
24146                tensor_content_range(
24147                    &tensor.layout,
24148                    tensor.logical_begin,
24149                    tensor.logical_end,
24150                    tensor.source.as_ref().map_or(0, DeviceMemoryView::len),
24151                )?;
24152            }
24153            native_origins.push(original);
24154        }
24155        let model_plan = if model {
24156            let storage = self
24157                .publication
24158                .as_ref()
24159                .ok_or(SemanticTransitionError::NotBound)?;
24160            let ranges = model_content_ranges(
24161                &lease.directory,
24162                &storage.layouts,
24163                content.tensors.iter().map(|tensor| {
24164                    (
24165                        tensor.layout,
24166                        tensor.logical_begin,
24167                        tensor.logical_end,
24168                        tensor.source.as_ref().map_or(0, DeviceMemoryView::len),
24169                    )
24170                }),
24171            )?;
24172            Some(model_content_copy_plan(
24173                &lease.directory,
24174                &ranges,
24175                &storage
24176                    .allocations
24177                    .iter()
24178                    .map(TrackedCudaSlice::len)
24179                    .collect::<Vec<_>>(),
24180            )?)
24181        } else {
24182            None
24183        };
24184        let seals = if let Some(plan) = &model_plan {
24185            TensorContentSeals::Model(ModelContentSeals::allocate(&self.provider, plan)?)
24186        } else {
24187            let mut digests = Vec::with_capacity(content.tensors.len());
24188            for (tensor, native) in content.tensors.iter().zip(native_origins) {
24189                if let Some(inputs) = native {
24190                    digests.push(CapturedTensorDigest::Publication(inputs));
24191                    continue;
24192                }
24193                let mut origin = None;
24194                for (&token, owner) in &self.steps {
24195                    if let Some(digest) = owner.feedback_origin_digest(tensor)? {
24196                        if token != lease.token {
24197                            return Err(publication_input_error(
24198                                "native feedback content belongs to another acquired reader",
24199                            ));
24200                        }
24201                        origin = Some(digest);
24202                        break;
24203                    }
24204                }
24205                digests.push(match origin {
24206                    Some(original) => original,
24207                    None => {
24208                        if tensor.native_allocation.is_some() {
24209                            return Err(publication_input_error("native allocation origin has no original content producer in this acquired reader"));
24210                        }
24211                        CapturedTensorDigest::Tensor {
24212                            cells: Arc::new(allocate_publication(&self.provider, 4)?), offset: 0, producer_sealed: false,
24213                        }
24214                    }
24215                });
24216            }
24217            TensorContentSeals::Captured(digests)
24218        };
24219        let handle = SemanticTensorContentWitness {
24220            issuer: Arc::clone(&self.publication_issuer),
24221            reader_token: lease.token,
24222            index,
24223            _witness: Arc::clone(&reader.content_witnesses),
24224        };
24225        self.steps
24226            .get_mut(&lease.token)
24227            .expect("validated content step")
24228            .content[index]
24229            .seals = seals;
24230        if let Some(plan) = model_plan {
24231            // Validate the original contract while the actual reader still pins
24232            // its directory. Then preserve those expected seals and contract
24233            // bytes, never a new digest of the supplied numerical model.
24234            self.guard_published_content(
24235                lease,
24236                &[(SemanticStateRole::ModelContract, 0)],
24237                consumer_stream,
24238            )?;
24239            let storage = self
24240                .publication
24241                .as_ref()
24242                .ok_or(SemanticTransitionError::NotBound)?;
24243            let TensorContentSeals::Model(model) = &self.steps[&lease.token].content[index].seals
24244            else {
24245                return Err(SemanticTransitionError::ObservationMismatch);
24246            };
24247            model.snapshot(
24248                &self.domain,
24249                &mut self.poisoned,
24250                &storage.directories[(lease.identity.word & 1) as usize],
24251                &storage.allocations[plan.contract_storage_slot],
24252                &plan,
24253            )?;
24254        }
24255        self.enqueue_tensor_content(lease, &handle, consumer_stream, model)?;
24256        Ok(handle)
24257    }
24258
24259    /// Verify the actual consumer tensors against the original private witness.
24260    /// Metadata/pointer substitution is a typed input refusal; later byte mutation
24261    /// is a terminal device integrity error. Return is enqueue-only. Ordinary
24262    /// completion/observation must succeed before activating outputs or replay.
24263    pub fn verify_tensor_content(
24264        &mut self,
24265        lease: &SemanticPublishedLease,
24266        witness: &SemanticTensorContentWitness,
24267        tensors: Vec<SemanticTensorInput>,
24268        consumer_stream: u64,
24269    ) -> Result<(), SemanticTransitionError> {
24270        let mut handoff = RetainedTensorAdmission {
24271            inputs: Some(tensors),
24272            stream: Arc::clone(self.provider.device().inner().stream()),
24273            ready: false,
24274        };
24275        self.checked_content_witness(lease, witness)?;
24276        dlpack_consumer_stream(consumer_stream)?;
24277        self.steps
24278            .get_mut(&lease.token)
24279            .expect("validated witness step")
24280            .consumer_streams
24281            .insert(consumer_stream);
24282        let tensors = prepare_semantic_tensors(
24283            &self.provider,
24284            handoff
24285                .inputs
24286                .take()
24287                .expect("retained original verification inputs"),
24288        )?;
24289        let content = &mut self
24290            .steps
24291            .get_mut(&lease.token)
24292            .expect("validated witness step")
24293            .content[witness.index];
24294        let offset = content.verification_inputs.len();
24295        content.verification_inputs.extend(tensors);
24296        let actual = &content.verification_inputs[offset..];
24297        if actual.len() != content.tensors.len()
24298            || content
24299                .tensors
24300                .iter()
24301                .zip(actual)
24302                .any(|(expected, actual)| !same_tensor_content_owner(expected, actual))
24303        {
24304            return Err(publication_input_error("content verification must use the exact original tensor storage, layout and interval"));
24305        }
24306        self.enqueue_tensor_content(lease, witness, consumer_stream, true)
24307    }
24308
24309    fn checked_content_witness(
24310        &self,
24311        lease: &SemanticPublishedLease,
24312        witness: &SemanticTensorContentWitness,
24313    ) -> Result<(), SemanticTransitionError> {
24314        let reader = self.checked_step(lease)?;
24315        if !Arc::ptr_eq(&self.publication_issuer, &witness.issuer)
24316            || witness.reader_token != lease.token
24317            || !Arc::ptr_eq(&reader.content_witnesses, &witness._witness)
24318            || witness.index >= reader.content.len()
24319        {
24320            return Err(publication_input_error(
24321                "content witness belongs to another parent or Session",
24322            ));
24323        }
24324        Ok(())
24325    }
24326
24327    fn enqueue_tensor_content(
24328        &mut self,
24329        lease: &SemanticPublishedLease,
24330        witness: &SemanticTensorContentWitness,
24331        consumer_stream: u64,
24332        verify: bool,
24333    ) -> Result<(), SemanticTransitionError> {
24334        self.checked_content_witness(lease, witness)?;
24335        lease.model_context_header()?;
24336        // Model witnesses retain the record authenticated by their own reader,
24337        // including after its release. A later publication must not replace that
24338        // baseline, nor force it to match the initial admission generation.
24339        self.enqueue_content_witness(witness, consumer_stream, verify)
24340    }
24341
24342    // The handle is issued only by the original reader. A retained policy may
24343    // check it after publication without manufacturing a second acquired lease.
24344    fn guard_continuation_content(
24345        &mut self,
24346        binding: &TextBindingStorage,
24347    ) -> Result<(), SemanticTransitionError> {
24348        let witness = &binding._witness;
24349        let reader = self.steps.get(&witness.reader_token).ok_or_else(|| {
24350            publication_input_error("original continuation step has been released")
24351        })?;
24352        let original_parent = match &binding.parent {
24353            TextBindingParent::Published { .. } => reader.identity.is_some(),
24354            TextBindingParent::Prepared(inputs) => {
24355                reader
24356                    .inputs
24357                    .as_ref()
24358                    .is_some_and(|original| Arc::ptr_eq(original, inputs))
24359                    && reader
24360                        .prepared
24361                        .as_ref()
24362                        .is_some_and(|prepared| prepared.observed)
24363                    && self
24364                        .prepared_segment
24365                        .as_ref()
24366                        .is_some_and(|build| build.completed)
24367            }
24368        };
24369        if !Arc::ptr_eq(&self.publication_issuer, &witness.issuer)
24370            || !original_parent
24371            || !Arc::ptr_eq(&reader.content_witnesses, &witness._witness)
24372            || reader
24373                .content
24374                .get(witness.index)
24375                .is_none_or(|content| !matches!(content.seals, TensorContentSeals::Captured(_)))
24376        {
24377            return Err(publication_input_error(
24378                "continuation no longer owns its original captured content",
24379            ));
24380        }
24381        self.enqueue_content_witness(witness, binding.consumer_stream, true)
24382    }
24383
24384    fn enqueue_content_witness(
24385        &mut self,
24386        witness: &SemanticTensorContentWitness,
24387        consumer_stream: u64,
24388        verify: bool,
24389    ) -> Result<(), SemanticTransitionError> {
24390        let execute = self
24391            .provider
24392            .device()
24393            .inner()
24394            .get_func(
24395                "xlog_semantic_transition",
24396                "semantic_tensor_content_witness",
24397            )
24398            .ok_or_else(|| runtime_error("kernel lookup", "tensor content witness unavailable"))?;
24399        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
24400            .map_err(|e| runtime_error("tensor content stream admission", e))?;
24401        let result = (|| {
24402            self.order_step_content_inputs(witness.reader_token, consumer_stream)?;
24403            let step_owner = &self.steps[&witness.reader_token];
24404            let retained = self
24405                .prepared_segment
24406                .as_ref()
24407                .is_some_and(|build| build.completed)
24408                && step_owner
24409                    .prepared
24410                    .as_ref()
24411                    .is_some_and(|prepared| prepared.observed);
24412            let custody = if retained {
24413                let bank = self.prepared_completed_parent_bank(witness.reader_token)?;
24414                let content = &self.steps[&witness.reader_token].content[witness.index];
24415                if matches!(&content.seals, TensorContentSeals::Model(seals)
24416                    if seals.prepared.as_ref().is_none_or(|source| source.bank != bank))
24417                {
24418                    return Err(publication_input_error(
24419                        "completed model witness requires its original executed branch bank",
24420                    ));
24421                }
24422                self.steps[&witness.reader_token]
24423                    .prepared
24424                    .as_ref()
24425                    .expect("checked prepared owner")
24426                    .replay_custody
24427                    .as_ref()
24428            } else {
24429                None
24430            };
24431            let content = &self.steps[&witness.reader_token].content[witness.index];
24432            content.enqueue_with_custody(
24433                &self.domain,
24434                &mut self.poisoned,
24435                &execute,
24436                verify,
24437                custody,
24438                retained,
24439            )?;
24440            self.order_content_consumers(consumer_stream)
24441        })();
24442        if result.is_err() {
24443            self.poisoned = true;
24444        }
24445        result
24446    }
24447
24448    fn ensure_step_inputs(
24449        &mut self,
24450        lease: &SemanticPublishedLease,
24451    ) -> Result<Arc<PreparedStepInputs>, SemanticTransitionError> {
24452        self.checked_reader(lease)?;
24453        self.checked_step(lease)?;
24454        lease.model_context_header()?;
24455        if let Some(inputs) = &self.steps[&lease.token].inputs {
24456            return Ok(Arc::clone(inputs));
24457        }
24458        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
24459            .map_err(|error| runtime_error("step input preparation stream admission", error))?;
24460        let storage = Arc::clone(
24461            self.publication
24462                .as_ref()
24463                .ok_or(SemanticTransitionError::NotBound)?,
24464        );
24465        let inputs = Arc::new(PreparedStepInputs::allocate(
24466            &self.provider,
24467            storage,
24468            self.readers[&lease.token].device.view(),
24469        )?);
24470        // Retain every output before the first upload or producer enqueue. A
24471        // partially initialized step remains owned by the poisoned Session.
24472        self.steps
24473            .get_mut(&lease.token)
24474            .expect("validated input step")
24475            .inputs = Some(Arc::clone(&inputs));
24476        let result = inputs
24477            .initialize(&self.provider)
24478            .and_then(|()| inputs.enqueue(&self.domain, &mut self.poisoned));
24479        if let Err(error) = result {
24480            self.poisoned = true;
24481            return Err(error);
24482        }
24483        Ok(inputs)
24484    }
24485
24486    /// Export private step-owned physical source slots without host copying or rotation.
24487    pub fn published_source(
24488        &mut self,
24489        lease: &SemanticPublishedLease,
24490        consumer_stream: u64,
24491    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
24492        self.export_publication_bank_field(lease, PublicationBankField::Source, consumer_stream)
24493    }
24494
24495    /// Export the original acquired terminal flag as a read-only U64[1] view
24496    /// into the same private step inputs used by source and model context.
24497    /// The ordinary cold input preparation and retained consumer lifetime apply;
24498    /// no terminal value is inferred from source tokens or model metadata.
24499    pub fn published_terminal(
24500        &mut self,
24501        lease: &SemanticPublishedLease,
24502        consumer_stream: u64,
24503    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
24504        self.export_publication_bank_field(lease, PublicationBankField::Terminal, consumer_stream)
24505    }
24506
24507    /// Join retained acquisition metadata with fixed private prefix identity,
24508    /// extent, ring head and source views. Device acquisition supplies every
24509    /// value once; the step retains these inputs through the final consumer.
24510    pub fn published_model_context(
24511        &mut self,
24512        lease: &SemanticPublishedLease,
24513        consumer_stream: u64,
24514    ) -> Result<SemanticModelContext, SemanticTransitionError> {
24515        dlpack_consumer_stream(consumer_stream)?;
24516        self.checked_reader(lease)?;
24517        let header = lease.model_context_header()?;
24518        let contract = self
24519            .publication
24520            .as_ref()
24521            .ok_or(SemanticTransitionError::NotBound)?
24522            .contract_value;
24523        let prefix_range = lease
24524            .directory
24525            .iter()
24526            .find(|range| {
24527                range.role == SemanticStateRole::PrefixIdentity as u64 && range.index == 0
24528            })
24529            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24530        if prefix_range.length_bytes != 32 {
24531            return Err(SemanticTransitionError::ObservationMismatch);
24532        }
24533        let prefix_identity =
24534            self.published_record(lease, SemanticStateRole::PrefixIdentity, 0, consumer_stream)?;
24535        let prefix_extent = self.export_publication_bank_field(
24536            lease,
24537            PublicationBankField::PrefixExtent,
24538            consumer_stream,
24539        )?;
24540        let ring_head = self.export_publication_bank_field(
24541            lease,
24542            PublicationBankField::RingHead,
24543            consumer_stream,
24544        )?;
24545        let source = self.published_source(lease, consumer_stream)?;
24546        Ok(SemanticModelContext {
24547            parent: lease.identity,
24548            descriptor_digest: header.descriptor_digest,
24549            numerical_state: (header.model_geometry_digest, header.model_numerical_digest),
24550            semantic_root: (
24551                header.semantic_owner,
24552                header.semantic_slot,
24553                header.semantic_generation,
24554                header.semantic_digest,
24555                header.semantic_extents,
24556            ),
24557            prefix: (prefix_identity, prefix_extent),
24558            ring_head,
24559            source,
24560            generations: (
24561                header.model_generation,
24562                header.neural_bank,
24563                header.neural_generation,
24564                header.cache_generation,
24565                header.authority_generation,
24566            ),
24567            topology_identity: contract.topology_identity,
24568            table_identity: contract.table_identity,
24569            capacities: (
24570                contract.prefix_capacity,
24571                contract.feedback_capacity,
24572                contract.max_position,
24573            ),
24574        })
24575    }
24576
24577    /// Export the selected resident neural bank without the private step copy
24578    /// used by per-tensor late-backward exports. Full backing allocations occur
24579    /// once and retain the acquired reader, while the returned geometry names
24580    /// every typed view in roles 18..=25. Callers must keep these aliases
24581    /// read-only and release the parent only after every consumer stream joins.
24582    pub fn published_resident_model_memory(
24583        &mut self,
24584        lease: &SemanticPublishedLease,
24585        consumer_stream: u64,
24586    ) -> Result<SemanticResidentModelMemory, SemanticTransitionError> {
24587        dlpack_consumer_stream(consumer_stream)?;
24588        self.checked_reader(lease)?;
24589        let header = lease.model_context_header()?;
24590        let storage = Arc::clone(
24591            self.publication
24592                .as_ref()
24593                .ok_or(SemanticTransitionError::NotBound)?,
24594        );
24595        storage.model_memory.validate(&storage.layouts)?;
24596        if storage.model_slots.len() != storage.model_memory.allocation_bytes.len() {
24597            return Err(SemanticTransitionError::ObservationMismatch);
24598        }
24599        let keys = lease
24600            .directory
24601            .iter()
24602            .filter(|range| matches!(range.role, 18..=25))
24603            .map(|range| {
24604                SemanticStateRole::from_code(range.role)
24605                    .map(|role| (role, range.index))
24606                    .ok_or(SemanticTransitionError::ObservationMismatch)
24607            })
24608            .collect::<Result<Vec<_>, _>>()?;
24609        if keys.len() != storage.model_memory.views.len() {
24610            return Err(publication_input_error(
24611                "resident model memory requires the complete selected model roster",
24612            ));
24613        }
24614        self.guard_published_content(lease, &keys, consumer_stream)?;
24615
24616        let mut allocations = Vec::with_capacity(storage.model_slots.len());
24617        for (allocation_index, (&bytes, slots)) in storage
24618            .model_memory
24619            .allocation_bytes
24620            .iter()
24621            .zip(&storage.model_slots)
24622            .enumerate()
24623        {
24624            let mut selected_slot = None;
24625            for range in lease
24626                .directory
24627                .iter()
24628                .filter(|range| matches!(range.role, 18..=25))
24629            {
24630                let (owner, _) = storage.model_memory.location(range.role, range.index)?;
24631                if owner == allocation_index
24632                    && selected_slot
24633                        .replace(range.storage_slot as usize)
24634                        .is_some_and(|prior| prior != range.storage_slot as usize)
24635                {
24636                    return Err(SemanticTransitionError::ObservationMismatch);
24637                }
24638            }
24639            let slot = selected_slot.unwrap_or(slots[(lease.identity.word & 1) as usize]);
24640            if !slots.contains(&slot) {
24641                return Err(SemanticTransitionError::ObservationMismatch);
24642            }
24643            let allocation = storage
24644                .allocations
24645                .get(slot)
24646                .ok_or(SemanticTransitionError::ObservationMismatch)?;
24647            if allocation.len() as u64 != bytes {
24648                return Err(SemanticTransitionError::ObservationMismatch);
24649            }
24650            let view = allocation.view();
24651            let provenance = view.allocation_provenance().ok_or_else(|| {
24652                publication_input_error("resident model backing has no native allocation owner")
24653            })?;
24654            let extent =
24655                i64::try_from(bytes).map_err(|_| SemanticTransitionError::ObservationMismatch)?;
24656            let tensor = self.export_reader_view(
24657                lease,
24658                view,
24659                vec![extent],
24660                vec![1],
24661                (1, 8),
24662                consumer_stream,
24663            )?;
24664            allocations.push((provenance, tensor));
24665        }
24666        let views = storage
24667            .model_memory
24668            .views
24669            .iter()
24670            .cloned()
24671            .map(|view| {
24672                let layout = storage
24673                    .layouts
24674                    .get(&(view.role, view.index))
24675                    .copied()
24676                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
24677                Ok((view, layout))
24678            })
24679            .collect::<Result<Vec<_>, SemanticTransitionError>>()?;
24680        Ok(SemanticResidentModelMemory {
24681            parent: lease.identity,
24682            generations: (
24683                header.model_generation,
24684                header.neural_bank,
24685                header.neural_generation,
24686            ),
24687            numerical_state: (header.model_geometry_digest, header.model_numerical_digest),
24688            allocations,
24689            storages: storage.model_memory.storages.clone(),
24690            views,
24691        })
24692    }
24693
24694    /// Export this acquired parent's prefix storage as U64[capacity, 8]. Columns
24695    /// follow SemanticTextSlot exactly, including source/generated provenance and
24696    /// its native ledger index. Only [0, prefix_extent) is committed, including
24697    /// the legal empty prefix; unused capacity must not be consumed as content.
24698    /// The export neither acquires again nor copies rows to host.
24699    /// The managed owner retains the same reader and append-only prefix storage.
24700    /// Consumers must not modify this sealed view and must join their final use
24701    /// through release, just as for published_tensor.
24702    pub fn published_prefix(
24703        &mut self,
24704        lease: &SemanticPublishedLease,
24705        consumer_stream: u64,
24706    ) -> Result<(SemanticPublishedIdentity, DlpackManagedTensor), SemanticTransitionError> {
24707        self.checked_reader(lease)?;
24708        let range = *lease
24709            .directory
24710            .iter()
24711            .find(|range| range.role == SemanticStateRole::PrefixSource as u64 && range.index == 0)
24712            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24713        if range.logical_end != lease.header.prefix_extent {
24714            return Err(SemanticTransitionError::ObservationMismatch);
24715        }
24716        let capacity = self
24717            .publication
24718            .as_ref()
24719            .ok_or(SemanticTransitionError::NotBound)?
24720            .contract_value
24721            .prefix_capacity;
24722        let layout = committed_prefix_layout(&range, capacity)?;
24723        let tensor = self.export_publication_range(lease, range, layout, consumer_stream)?;
24724        Ok((lease.identity, tensor))
24725    }
24726
24727    /// Read RNG coordinates from the actual parent of the pending continuation.
24728    /// The application cannot supply a replacement stream or proposal identity.
24729    pub fn continuation_rng(
24730        &self,
24731        lease: &SemanticPublishedLease,
24732    ) -> Result<SemanticRngBinding, SemanticTransitionError> {
24733        self.checked_reader(lease)?;
24734        if self.continuation_base != Some(lease.identity.word)
24735            || self
24736                .admitted_transition
24737                .is_none_or(|(token, word, _)| token != lease.token || word != lease.identity.word)
24738        {
24739            return Err(publication_input_error(
24740                "execution requires this exact acquired reader's admitted continuation",
24741            ));
24742        }
24743        lease.header.rng_binding()
24744    }
24745
24746    /// Original coordinates for policy snapshot admission, before continuation
24747    /// binding. This does not authorize capture, execution or a draw.
24748    #[cfg(feature = "semantic-policy")]
24749    pub fn admitted_policy_rng(
24750        &self,
24751        lease: &SemanticPublishedLease,
24752    ) -> Result<SemanticRngBinding, SemanticTransitionError> {
24753        self.checked_reader(lease)?;
24754        if self.admitted_transition
24755            != Some((
24756                lease.token,
24757                lease.identity.word,
24758                SemanticTransitionKind::Proposal,
24759            ))
24760        {
24761            return Err(publication_input_error(
24762                "policy snapshot requires this exact acquired reader's admitted proposal",
24763            ));
24764        }
24765        lease.header.rng_binding()
24766    }
24767
24768    fn read_published_control_record(
24769        &mut self,
24770        lease: &SemanticPublishedLease,
24771        role: u64,
24772    ) -> Result<PublicationMaterialRange, SemanticTransitionError> {
24773        self.checked_reader(lease)?;
24774        let range = *lease
24775            .directory
24776            .iter()
24777            .find(|range| range.role == role && range.index == 0)
24778            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24779        let storage = Arc::clone(
24780            self.publication
24781                .as_ref()
24782                .ok_or(SemanticTransitionError::NotBound)?,
24783        );
24784        let allocation = storage
24785            .allocations
24786            .get(range.storage_slot as usize)
24787            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24788        let begin = usize::try_from(range.offset_bytes)
24789            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
24790        let end = usize::try_from(range.length_bytes)
24791            .ok()
24792            .and_then(|length| begin.checked_add(length))
24793            .filter(|&end| end <= allocation.len())
24794            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24795        let bytes = self.publication_read(allocation.view().slice(begin..end))?;
24796        let material = PublicationMaterialRange {
24797            range,
24798            capacity: allocation.len() - begin,
24799            bytes,
24800        };
24801        if material.original_record_digest() != range.digest {
24802            return Err(SemanticTransitionError::ObservationMismatch);
24803        }
24804        Ok(material)
24805    }
24806
24807    /// Verify a durable receiver receipt against the actual current FINAL
24808    /// intent, then append it through the publication word's sole CAS. This is
24809    /// cold external-effect control, not a model or semantic transition.
24810    pub fn acknowledge_delivery(
24811        &mut self,
24812        lease: &SemanticPublishedLease,
24813        receipt: &[u8],
24814        recipient_id: Identity256,
24815        verification_key: &[u8; 32],
24816        expected_effect: &[u8],
24817    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
24818        self.checked_reader(lease)?;
24819        if self.pending || self.admitted_transition.is_some() || self.continuation_base.is_some() {
24820            return Err(publication_input_error(
24821                "delivery acknowledgement cannot overlap a transition",
24822            ));
24823        }
24824        if lease.header.terminal != 2
24825            || receipt.len() < 169
24826            || verification_key.iter().all(|&byte| byte == 0)
24827        {
24828            return Err(publication_input_error(
24829                "delivery acknowledgement requires a FINAL parent and trusted receipt",
24830            ));
24831        }
24832        let entries = self.read_published_control_record(lease, 30)?;
24833        let payload = self.read_published_control_record(lease, 31)?;
24834        let acknowledgements = self.read_published_control_record(lease, 32)?;
24835        let intents = output_intents_from_ranges(&entries, &payload)?;
24836        let acknowledged =
24837            acknowledgement_receipts(&acknowledgements.bytes, acknowledgements.capacity)?;
24838        let stable_identity =
24839            Identity256::from_bytes(receipt[25..57].try_into().expect("checked receipt extent"));
24840        let intent = intents
24841            .iter()
24842            .find(|intent| intent.stable_identity == stable_identity)
24843            .ok_or_else(|| {
24844                publication_input_error("delivery receipt has no native FINAL intent")
24845            })?;
24846        if expected_effect.is_empty() || intent.effect.as_slice() != expected_effect {
24847            return Err(publication_input_error(
24848                "native FINAL effect differs from the bound receiver",
24849            ));
24850        }
24851        let receipt_digest =
24852            verify_delivery_receipt(receipt, intent, recipient_id, verification_key)?;
24853        let storage = Arc::clone(
24854            self.publication
24855                .as_ref()
24856                .ok_or(SemanticTransitionError::NotBound)?,
24857        );
24858        let current = self.publication_read(storage.control.view())?[0];
24859        if current.instance != lease.identity.instance || current.word != lease.identity.word {
24860            return Err(publication_input_error(
24861                "delivery acknowledgement requires the current acquired FINAL parent",
24862            ));
24863        }
24864        if let Some((_, previous)) = acknowledged
24865            .iter()
24866            .find(|(identity, _)| *identity == stable_identity)
24867        {
24868            if previous == receipt {
24869                return Ok(lease.identity);
24870            }
24871            return Err(publication_input_error(
24872                "native intent was acknowledged with a different receipt",
24873            ));
24874        }
24875        if lease.header.fuel == 0 {
24876            return Err(publication_input_error(
24877                "FINAL parent has no reserved acknowledgement fuel",
24878            ));
24879        }
24880        let receipt_device = allocate_publication::<u8>(&self.provider, receipt.len())?;
24881        upload_publication(&self.provider, receipt, &receipt_device)?;
24882        let input_device = allocate_publication::<PublicationDeliveryInput>(&self.provider, 1)?;
24883        upload_publication(
24884            &self.provider,
24885            &[PublicationDeliveryInput {
24886                lease: self.readers[&lease.token].device.device_ptr_value(),
24887                receipt: receipt_device.device_ptr_value(),
24888                receipt_len: receipt.len() as u64,
24889                recipient_id,
24890                receipt_digest,
24891            }],
24892            &input_device,
24893        )?;
24894        let mut descriptor = self.descriptor();
24895        descriptor.publication = PublicationCommand {
24896            control: storage.control.device_ptr_value(),
24897            lease: input_device.device_ptr_value(),
24898            operation: 6,
24899        };
24900        let mut recorder = self.kernel_recorder();
24901        recorder.read(&receipt_device);
24902        recorder.read(&input_device);
24903        recorder.read(&self.readers[&lease.token].device);
24904        let execute = self.execute.clone();
24905        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |stream| {
24906            // SAFETY: the strict recorder retains the acquired lease, exact
24907            // receipt and command until the native CAS completes.
24908            unsafe {
24909                execute.launch_in(
24910                    stream,
24911                    LaunchConfig {
24912                        grid_dim: (1, 1, 1),
24913                        block_dim: (256, 1, 1),
24914                        shared_mem_bytes: 0,
24915                    },
24916                    (descriptor,),
24917                )
24918            }
24919            .map_err(|error| XlogError::Kernel(error.to_string()))
24920        })?;
24921        wait_on_stream(
24922            &self.stream,
24923            &mut self.poisoned,
24924            &mut self.stream_waits,
24925            "delivery acknowledgement publication",
24926            CudaStream::synchronize,
24927        )?;
24928        let control = self.publication_read(storage.control.view())?[0];
24929        if control.refusal != 0 {
24930            return Err(SemanticTransitionError::PublicationRefused {
24931                status: control.refusal,
24932            });
24933        }
24934        let header = self.read_publication_header((control.word & 1) as usize)?;
24935        let expected_word = ((lease.identity.word >> 1) + 1) << 1 | ((lease.identity.word & 1) ^ 1);
24936        if control.word != expected_word
24937            || header.publication_word != control.word
24938            || header.terminal != 2
24939            || header.fuel + 1 != lease.header.fuel
24940            || header.instance != lease.identity.instance
24941        {
24942            self.poisoned = true;
24943            return Err(SemanticTransitionError::ObservationMismatch);
24944        }
24945        Ok(SemanticPublishedIdentity {
24946            instance: header.instance,
24947            word: header.publication_word,
24948            logical_digest: header.logical_digest,
24949            state_digest: header.state_digest,
24950        })
24951    }
24952
24953    /// A FINAL acquired bank must contain its actual native terminal intent.
24954    /// This readiness check does not deliver an effect or issue use authority.
24955    pub fn admit_external_activation(
24956        &mut self,
24957        lease: &SemanticPublishedLease,
24958    ) -> Result<(), SemanticTransitionError> {
24959        self.checked_reader(lease)?;
24960        if lease.header.terminal != 2 {
24961            return Err(publication_input_error(
24962                "external activation requires a genuinely published FINAL parent",
24963            ));
24964        }
24965        if lease.header.fuel == 0 {
24966            return Err(publication_input_error(
24967                "FINAL parent has no reserved fuel for durable delivery acknowledgement",
24968            ));
24969        }
24970        let storage = Arc::clone(
24971            self.publication
24972                .as_ref()
24973                .ok_or(SemanticTransitionError::NotBound)?,
24974        );
24975        let range = lease
24976            .directory
24977            .iter()
24978            .find(|range| range.role == 30)
24979            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24980        let payload = lease
24981            .directory
24982            .iter()
24983            .find(|range| range.role == 31)
24984            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24985        let owner = storage
24986            .allocations
24987            .get(range.storage_slot as usize)
24988            .ok_or(SemanticTransitionError::ObservationMismatch)?;
24989        if range.offset_bytes != 0
24990            || range.length_bytes < size_of::<IntentQueueHeader>() as u64
24991            || range.length_bytes > owner.len() as u64
24992        {
24993            return Err(SemanticTransitionError::ObservationMismatch);
24994        }
24995        // SAFETY: checked header range is integral, aligned and initialized by
24996        // the acquired sealed directory's actual native queue owner.
24997        let header_view = unsafe {
24998            owner
24999                .view()
25000                .slice(..size_of::<IntentQueueHeader>())
25001                .cast::<IntentQueueHeader>()
25002        }
25003        .ok_or(SemanticTransitionError::ObservationMismatch)?;
25004        let header = self.publication_read(header_view)?[0];
25005        if header.abi != 1
25006            || header.count == 0
25007            || header.count > header.capacity
25008            || header
25009                .count
25010                .checked_mul(size_of::<IntentEntry>() as u64)
25011                .and_then(|n| n.checked_add(size_of::<IntentQueueHeader>() as u64))
25012                != Some(range.length_bytes)
25013            || header.payload_used_bytes != payload.length_bytes
25014            || header.payload_used_bytes > header.payload_capacity_bytes
25015            || header.effect_length_bytes == 0
25016            || header
25017                .effect_offset_bytes
25018                .checked_add(header.effect_length_bytes)
25019                .is_none_or(|n| n > header.payload_used_bytes)
25020        {
25021            return Err(publication_input_error(
25022                "FINAL bank has no complete native terminal intent queue",
25023            ));
25024        }
25025        let begin =
25026            size_of::<IntentQueueHeader>() + (header.count as usize - 1) * size_of::<IntentEntry>();
25027        // SAFETY: exact final entry extent follows from the checked queue count.
25028        let entry_view = unsafe {
25029            owner
25030                .view()
25031                .slice(begin..begin + size_of::<IntentEntry>())
25032                .cast::<IntentEntry>()
25033        }
25034        .ok_or(SemanticTransitionError::ObservationMismatch)?;
25035        let entry = self.publication_read(entry_view)?[0];
25036        if entry.audit_instance != lease.identity.instance
25037            || entry.audit_epoch != lease.identity.word >> 1
25038            || entry.result_logical != lease.identity.logical_digest
25039            || entry.chain != header.chain_head
25040            || entry.payload_len < 8
25041            || entry
25042                .payload_offset
25043                .checked_add(entry.payload_len)
25044                .is_none_or(|n| n > header.payload_used_bytes)
25045            || entry.stable_identity == Identity256::default()
25046            || entry.effect_digest == Identity256::default()
25047        {
25048            return Err(publication_input_error(
25049                "terminal intent is not the actual final effect of this acquired publication",
25050            ));
25051        }
25052        let current = self.publication_read(storage.control.view())?[0];
25053        if current.instance != lease.identity.instance || current.word != lease.identity.word {
25054            return Err(publication_input_error(
25055                "external activation requires the current acquired FINAL parent",
25056            ));
25057        }
25058        let entries = self.read_published_control_record(lease, 30)?;
25059        let payload = self.read_published_control_record(lease, 31)?;
25060        let acknowledgements = self.read_published_control_record(lease, 32)?;
25061        let intents = output_intents_from_ranges(&entries, &payload)?;
25062        let acknowledged =
25063            acknowledgement_receipts(&acknowledgements.bytes, acknowledgements.capacity)?;
25064        if intents.iter().all(|intent| {
25065            acknowledged
25066                .iter()
25067                .any(|(identity, _)| *identity == intent.stable_identity)
25068        }) {
25069            return Err(publication_input_error(
25070                "FINAL publication has no unacknowledged delivery intent",
25071            ));
25072        }
25073        Ok(())
25074    }
25075
25076    /// Export the cold physical-capacity tensor shape, retaining its original
25077    /// sealed logical range. Unused rows are not content. Shared prefix caches
25078    /// retain the reader; private input caches retain their original step.
25079    pub fn published_tensor(
25080        &mut self,
25081        lease: &SemanticPublishedLease,
25082        role: SemanticStateRole,
25083        index: u64,
25084        consumer_stream: u64,
25085    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25086        let (range, layout) = self.published_tensor_layout(lease, role, index)?;
25087        if matches!(role as u64, 18..=25 | 51..=54) {
25088            self.guard_published_content(lease, &[(role, index)], consumer_stream)?;
25089        }
25090        self.export_publication_range(lease, range, layout, consumer_stream)
25091    }
25092
25093    /// Select the exact published training view from the cold resident arena.
25094    /// The host supplies neither an ordinal nor an identity: both the cursor and
25095    /// RNG coordinates come from this acquired publication, while CUDA verifies
25096    /// the complete role-29 bytes before exposing fixed output ports.
25097    pub fn select_training_view(
25098        &mut self,
25099        lease: &SemanticPublishedLease,
25100    ) -> Result<SemanticSelectedTrainingView, SemanticTransitionError> {
25101        self.checked_reader(lease)?;
25102        let arena = Arc::clone(
25103            self.training_views
25104                .as_ref()
25105                .ok_or(SemanticTransitionError::NotBound)?,
25106        );
25107        let range = *lease
25108            .directory
25109            .iter()
25110            .find(|range| range.role == SemanticStateRole::TrainingView as u64 && range.index == 0)
25111            .ok_or_else(|| publication_input_error("acquired training-view range is absent"))?;
25112        let storage = Arc::clone(
25113            self.publication
25114                .as_ref()
25115                .ok_or(SemanticTransitionError::NotBound)?,
25116        );
25117        let allocation = storage
25118            .allocations
25119            .get(
25120                usize::try_from(range.storage_slot)
25121                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
25122            )
25123            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25124        let begin = usize::try_from(range.offset_bytes)
25125            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
25126        let length = usize::try_from(range.length_bytes)
25127            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
25128        let end = begin
25129            .checked_add(length)
25130            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25131        let selected = allocation
25132            .view()
25133            .try_slice(begin..end)
25134            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25135        let result = arena.enqueue_selection(
25136            selected,
25137            lease.header.training_cursor,
25138            lease.header.training_rng,
25139            self.training_origins.clone(),
25140        );
25141        if matches!(
25142            &result,
25143            Err(SemanticTransitionError::Runtime {
25144                operation: "training-view device selection" | "training-view launch commit",
25145                ..
25146            })
25147        ) {
25148            self.poisoned = true;
25149        }
25150        result
25151    }
25152
25153    /// Allocation origin and complete backing bytes of the exact view exported
25154    /// by `published_tensor`, retaining that view's reader/step access grant.
25155    /// Exported capacity is not evidence that unused contents are model inputs.
25156    pub fn published_tensor_allocation(
25157        &mut self,
25158        lease: &SemanticPublishedLease,
25159        role: SemanticStateRole,
25160        index: u64,
25161        consumer_stream: u64,
25162    ) -> Result<(DeviceAllocationProvenance, DlpackManagedTensor), SemanticTransitionError> {
25163        dlpack_consumer_stream(consumer_stream)?;
25164        let (range, layout) = self.published_tensor_layout(lease, role, index)?;
25165        if matches!(role as u64, 18..=25 | 51..=54) {
25166            self.guard_published_content(lease, &[(role, index)], consumer_stream)?;
25167        }
25168        let view = self.publication_tensor_view(lease, range, layout)?;
25169        let provenance = view.allocation_provenance().ok_or_else(|| {
25170            publication_input_error("published tensor has no complete native allocation owner")
25171        })?;
25172        let allocation = view
25173            .allocation_view()
25174            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25175        let bytes = i64::try_from(allocation.len())
25176            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
25177        let tensor = self.export_publication_tensor_view(
25178            lease,
25179            range.role,
25180            allocation,
25181            vec![bytes],
25182            vec![1],
25183            (1, 8),
25184            consumer_stream,
25185        )?;
25186        Ok((provenance, tensor))
25187    }
25188
25189    fn published_tensor_layout(
25190        &self,
25191        lease: &SemanticPublishedLease,
25192        role: SemanticStateRole,
25193        index: u64,
25194    ) -> Result<(PublicationRange, SemanticTensorLayout), SemanticTransitionError> {
25195        self.checked_reader(lease)?;
25196        let storage = self
25197            .publication
25198            .as_ref()
25199            .ok_or(SemanticTransitionError::NotBound)?;
25200        let layout = *storage
25201            .layouts
25202            .get(&(role as u64, index))
25203            .ok_or_else(|| publication_input_error("acquired role has no model tensor layout"))?;
25204        let range = *lease
25205            .directory
25206            .iter()
25207            .find(|range| range.role == role as u64 && range.index == index)
25208            .ok_or_else(|| publication_input_error("acquired tensor range is absent"))?;
25209        Ok((range, layout))
25210    }
25211
25212    /// Read the map from this acquired bank's sealed record, not a later pending
25213    /// invocation. Reading these small identity records never reads tensor values.
25214    pub fn published_active_rows(
25215        &mut self,
25216        lease: &SemanticPublishedLease,
25217    ) -> Result<SemanticActiveRows, SemanticTransitionError> {
25218        self.checked_reader(lease)?;
25219        let bytes = self.read_published_record_bytes(lease, SemanticStateRole::TensorLayout)?;
25220        let (_, layouts, active) = decode_tensor_table(&bytes)?;
25221        let storage = self
25222            .publication
25223            .as_ref()
25224            .ok_or(SemanticTransitionError::NotBound)?;
25225        if layouts != storage.layouts.values().copied().collect::<Vec<_>>()
25226            || active.rows.len() as u64 > 32 + storage.contract_value.feedback_capacity
25227            || lease
25228                .directory
25229                .iter()
25230                .filter(|range| matches!(range.role, 51..=54))
25231                .any(|range| {
25232                    range.logical_begin != 0
25233                        || range.logical_end != active.rows.len() as u64
25234                        || (active.rows.is_empty() != (range.length_bytes == 0))
25235                })
25236        {
25237            return Err(SemanticTransitionError::ObservationMismatch);
25238        }
25239        Ok(active)
25240    }
25241
25242    /// Cold read of the original model contribution from this acquired parent.
25243    /// The application freezes external writers; registered consumer prefixes
25244    /// are joined before reading and verifying the original sealed bytes.
25245    /// This is never a host query inside a resident reasoning loop.
25246    pub fn published_model_numerical_mode(
25247        &mut self,
25248        lease: &SemanticPublishedLease,
25249    ) -> Result<Vec<u8>, SemanticTransitionError> {
25250        self.ensure_quiescent()?;
25251        let streams = self
25252            .checked_reader(lease)?
25253            .consumer_streams
25254            .iter()
25255            .chain(&self.checked_step(lease)?.consumer_streams)
25256            .copied()
25257            .collect::<BTreeSet<_>>()
25258            .into_iter()
25259            .collect::<Vec<_>>();
25260        self.complete_step_consumers(lease, &streams)?;
25261        let record = self.read_published_material_range(lease, 43, 0)?;
25262        if record.original_record_digest() != record.range.digest {
25263            return Err(SemanticTransitionError::ObservationMismatch);
25264        }
25265        let table =
25266            self.read_published_material_range(lease, SemanticStateRole::TensorLayout as u64, 0)?;
25267        let storage = Arc::clone(
25268            self.publication
25269                .as_ref()
25270                .ok_or(SemanticTransitionError::NotBound)?,
25271        );
25272        let contract = self.publication_read(storage.contract.view())?[0];
25273        if publication_abi_bytes(&[contract]) != publication_abi_bytes(&[storage.contract_value]) {
25274            return Err(SemanticTransitionError::ObservationMismatch);
25275        }
25276        let counts = self.publication_read(storage.role_counts.view())?;
25277        let mut role_counts = [0; 55];
25278        for (index, count) in counts.iter().enumerate() {
25279            if count.role != index as u64 + 1 {
25280                return Err(SemanticTransitionError::ObservationMismatch);
25281            }
25282            role_counts[index] = count.count;
25283        }
25284        let terminals = self.publication_read(storage.terminals.view())?;
25285        let capacities = lease
25286            .directory
25287            .iter()
25288            .map(|range| {
25289                let allocation = usize::try_from(range.storage_slot)
25290                    .ok()
25291                    .and_then(|slot| storage.allocations.get(slot))
25292                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
25293                let capacity = usize::try_from(range.offset_bytes)
25294                    .ok()
25295                    .and_then(|offset| allocation.len().checked_sub(offset))
25296                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
25297                Ok((range.role, range.index, capacity))
25298            })
25299            .collect::<Result<Vec<_>, SemanticTransitionError>>()?;
25300        Ok(verified_runtime_model_mode(
25301            &record.bytes,
25302            contract,
25303            &role_counts,
25304            &terminals,
25305            &storage.layouts,
25306            &capacities,
25307            &table,
25308            &storage.model_memory,
25309        )?
25310        .to_vec())
25311    }
25312
25313    /// Cold export of the complete native material reachable from this acquired
25314    /// parent. The bytes carry content, not a use grant or publication authority.
25315    /// The canonical execution carrier must bind them to its original invocation.
25316    pub fn published_state_material(
25317        &mut self,
25318        lease: &SemanticPublishedLease,
25319    ) -> Result<Vec<u8>, SemanticTransitionError> {
25320        self.ensure_quiescent()?;
25321        self.checked_reader(lease)?;
25322        let storage = Arc::clone(
25323            self.publication
25324                .as_ref()
25325                .ok_or(SemanticTransitionError::NotBound)?,
25326        );
25327        let bank = self.read_published_bank(lease)?;
25328        let graph = self
25329            .graph
25330            .export_transition_root_parts(
25331                bank.header.semantic_owner,
25332                bank.header.semantic_slot,
25333                bank.header.semantic_generation,
25334            )
25335            .map_err(SemanticTransitionError::Semantic)?;
25336        let counts = self.publication_read(storage.role_counts.view())?;
25337        let mut role_counts = [0; 55];
25338        for (index, count) in counts.iter().enumerate() {
25339            if count.role != index as u64 + 1 {
25340                return Err(SemanticTransitionError::ObservationMismatch);
25341            }
25342            role_counts[index] = count.count;
25343        }
25344        let terminals = if storage.terminals.is_empty() {
25345            Vec::new()
25346        } else {
25347            self.publication_read(storage.terminals.view())?
25348        };
25349        let mut ranges = Vec::with_capacity(lease.directory.len());
25350        let mut model_allocations = Vec::with_capacity(storage.model_slots.len());
25351        for (allocation_index, slots) in storage.model_slots.iter().enumerate() {
25352            let mut selected_slot = None;
25353            for range in lease
25354                .directory
25355                .iter()
25356                .filter(|range| matches!(range.role, 18..=25))
25357            {
25358                let (owner, _) = storage.model_memory.location(range.role, range.index)?;
25359                if owner == allocation_index
25360                    && selected_slot
25361                        .replace(range.storage_slot as usize)
25362                        .is_some_and(|prior| prior != range.storage_slot as usize)
25363                {
25364                    return Err(SemanticTransitionError::ObservationMismatch);
25365                }
25366            }
25367            let slot = selected_slot.unwrap_or(slots[(lease.identity.word & 1) as usize]);
25368            if !slots.contains(&slot) {
25369                return Err(SemanticTransitionError::ObservationMismatch);
25370            }
25371            let allocation = &storage.allocations[slot];
25372            model_allocations.push(if allocation.is_empty() {
25373                Vec::new()
25374            } else {
25375                self.publication_read(allocation.view())?
25376            });
25377        }
25378        for range in &lease.directory {
25379            if matches!(range.role, 18..=25) {
25380                let (allocation, offset) =
25381                    storage.model_memory.location(range.role, range.index)?;
25382                let end = usize::try_from(range.length_bytes)
25383                    .ok()
25384                    .and_then(|bytes| offset.checked_add(bytes))
25385                    .ok_or(SemanticTransitionError::ObservationMismatch)?;
25386                let bytes = model_allocations[allocation]
25387                    .get(offset..end)
25388                    .ok_or(SemanticTransitionError::ObservationMismatch)?
25389                    .to_vec();
25390                ranges.push(PublicationMaterialRange {
25391                    range: *range,
25392                    capacity: model_allocations[allocation].len() - offset,
25393                    bytes,
25394                });
25395            } else {
25396                ranges.push(self.read_published_material_range(lease, range.role, range.index)?);
25397            }
25398        }
25399        let mut contract = storage.contract_value;
25400        // Device addresses and owner handles are relocated from fresh actual
25401        // allocations. They can never be imported as executable pointers.
25402        contract.terminal_tokens = 0;
25403        contract.role_counts = 0;
25404        contract.semantic_owner = 0;
25405        PublicationMaterial {
25406            bank,
25407            contract,
25408            role_counts,
25409            terminals,
25410            layouts: storage.layouts.clone(),
25411            model_memory: storage.model_memory.clone(),
25412            model_allocations,
25413            ranges,
25414            graph,
25415            learning_phases: self.learning_phases.clone(),
25416        }
25417        .encode()
25418    }
25419
25420    /// Cold export of native evidence from two genuinely held adjacent
25421    /// publications. Only the successor identity and its six publication-only
25422    /// records enter the evidence; the successor's full state is not exported.
25423    /// The application must freeze further writers and register all consumer
25424    /// streams before this call. Both later release rosters must include one.
25425    pub fn published_replay_evidence(
25426        &mut self,
25427        predecessor: &SemanticPublishedLease,
25428        successor: &SemanticPublishedLease,
25429    ) -> Result<Vec<u8>, SemanticTransitionError> {
25430        self.guard_replay_publications(predecessor, successor)?;
25431        let predecessor =
25432            PublicationMaterial::decode(&self.published_state_material(predecessor)?)?;
25433        self.read_replay_evidence(&predecessor, successor)?.encode()
25434    }
25435
25436    /// Cold export of the original authority envelope and actual successor
25437    /// continuation decision from held adjacent publications. The execution
25438    /// carrier stores this as its reconstruction provenance root, not evidence
25439    /// of current rights and not a second copy of the complete predecessor.
25440    /// Further writers must be frozen and every consumer stream registered;
25441    /// both later release rosters must include the guard's stream one.
25442    pub fn published_replay_provenance(
25443        &mut self,
25444        predecessor: &SemanticPublishedLease,
25445        successor: &SemanticPublishedLease,
25446    ) -> Result<Vec<u8>, SemanticTransitionError> {
25447        self.guard_replay_publications(predecessor, successor)?;
25448        let identity = predecessor.identity;
25449        let predecessor =
25450            PublicationMaterial::decode(&self.published_state_material(predecessor)?)?;
25451        self.read_replay_evidence(&predecessor, successor)?;
25452        let authority = predecessor
25453            .ranges
25454            .iter()
25455            .find(|item| item.range.role == 38 && item.range.index == 0)
25456            .ok_or(SemanticTransitionError::ObservationMismatch)?
25457            .clone();
25458        let decision = self.read_published_material_range(successor, 39, 0)?;
25459        let provenance = PublicationReplayProvenance {
25460            predecessor: identity,
25461            authority,
25462            decision,
25463        };
25464        provenance.validate(&predecessor)?;
25465        provenance.encode()
25466    }
25467
25468    /// Restore already-decoded complete predecessor material through the sole
25469    /// native cold restoration path. Current use authority remains external.
25470    pub fn restore_replay_material(
25471        &mut self,
25472        material: &SemanticReplayMaterial,
25473    ) -> Result<SemanticPublishedIdentity, SemanticTransitionError> {
25474        self.restore_state_material(&material.predecessor.encode()?)
25475    }
25476
25477    /// Compare a genuine rerun with the expected complete logical/state hashes
25478    /// and normalized publication records. Runtime instance/word coordinates
25479    /// differ after restoration and are checked as new lineage, not byte-equal.
25480    /// This cold check neither issues a use grant nor proves historical origin.
25481    /// It guards every actual range of both held readers before cold readback;
25482    /// cached seals alone cannot detect writes through shared tensor aliases.
25483    /// The method owns consumer stream one for both readers. Their later release
25484    /// rosters must include one as well as every application consumer stream.
25485    pub fn verify_replay_publication(
25486        &mut self,
25487        material: &SemanticReplayMaterial,
25488        predecessor: &SemanticPublishedLease,
25489        successor: &SemanticPublishedLease,
25490    ) -> Result<(), SemanticTransitionError> {
25491        self.guard_replay_publications(predecessor, successor)?;
25492        // The following ordinary cold reads wait for both guards on the native
25493        // stream and propagate a fatal integrity error before accepting bytes.
25494        let actual_predecessor =
25495            PublicationMaterial::decode(&self.published_state_material(predecessor)?)?;
25496        let header = actual_predecessor.bank.header;
25497        let expected = material.predecessor_identity();
25498        if header.instance == expected.instance
25499            || header.recovered_instance != expected.instance
25500            || header.publication_word != 0
25501            || header.logical_digest != expected.logical_digest
25502            || header.state_digest != expected.state_digest
25503        {
25504            return Err(publication_input_error(
25505                "replay comparison requires the freshly restored complete predecessor",
25506            ));
25507        }
25508        let actual = self.read_replay_evidence(&actual_predecessor, successor)?;
25509        if actual.successor.logical_digest != material.evidence.successor.logical_digest
25510            || actual.successor.state_digest != material.evidence.successor.state_digest
25511        {
25512            return Err(publication_input_error(
25513                "genuine replay successor differs from the expected complete native state",
25514            ));
25515        }
25516        for (actual, expected) in actual.ranges.iter().zip(&material.evidence.ranges) {
25517            if actual.logical_record_digest()? != expected.logical_record_digest()? {
25518                return Err(publication_input_error(
25519                    "genuine replay differs from the expected normalized publication records",
25520                ));
25521            }
25522        }
25523        Ok(())
25524    }
25525
25526    // Fence all registered writer/consumer prefixes before hashing either bank.
25527    // This does not retire the original graph's aliases or witnesses and cannot
25528    // fence future writes; the controlling application freezes those separately.
25529    fn guard_replay_publications(
25530        &mut self,
25531        predecessor: &SemanticPublishedLease,
25532        successor: &SemanticPublishedLease,
25533    ) -> Result<(), SemanticTransitionError> {
25534        for lease in [predecessor, successor] {
25535            let streams = self
25536                .checked_reader(lease)?
25537                .consumer_streams
25538                .iter()
25539                .chain(&self.checked_step(lease)?.consumer_streams)
25540                .copied()
25541                .collect::<BTreeSet<_>>()
25542                .into_iter()
25543                .collect::<Vec<_>>();
25544            self.complete_step_consumers(lease, &streams)?;
25545        }
25546        let predecessor_ranges = self.published_range_keys(predecessor)?;
25547        let successor_ranges = self.published_range_keys(successor)?;
25548        self.guard_published_content(predecessor, &predecessor_ranges, 1)?;
25549        self.guard_published_content(successor, &successor_ranges, 1)
25550    }
25551
25552    fn read_replay_evidence(
25553        &mut self,
25554        predecessor: &PublicationMaterial,
25555        successor: &SemanticPublishedLease,
25556    ) -> Result<PublicationReplayEvidence, SemanticTransitionError> {
25557        let bank = self.read_published_bank(successor)?;
25558        let mut ranges = Vec::with_capacity(REPLAY_EVIDENCE_ROLES.len());
25559        for role in REPLAY_EVIDENCE_ROLES {
25560            ranges.push(self.read_published_material_range(successor, role, 0)?);
25561        }
25562        let evidence = PublicationReplayEvidence {
25563            successor: successor.identity,
25564            ranges,
25565        };
25566        let coverage = self.read_published_material_range(successor, 14, 0)?;
25567        let codebook = self.read_published_material_range(successor, 48, 0)?;
25568        evidence.validate_observed(predecessor, &bank, &coverage, &codebook)?;
25569        Ok(evidence)
25570    }
25571
25572    fn read_published_bank(
25573        &mut self,
25574        lease: &SemanticPublishedLease,
25575    ) -> Result<PublicationBank, SemanticTransitionError> {
25576        self.checked_reader(lease)?;
25577        let storage = Arc::clone(
25578            self.publication
25579                .as_ref()
25580                .ok_or(SemanticTransitionError::NotBound)?,
25581        );
25582        let bank =
25583            self.publication_read(storage.banks[(lease.identity.word & 1) as usize].view())?[0];
25584        if publication_abi_bytes(&[bank.header]) != publication_abi_bytes(&[lease.header])
25585            || publication_abi_bytes(&bank.source) != publication_abi_bytes(&lease.source)
25586        {
25587            return Err(SemanticTransitionError::ObservationMismatch);
25588        }
25589        Ok(bank)
25590    }
25591
25592    fn read_published_material_range(
25593        &mut self,
25594        lease: &SemanticPublishedLease,
25595        role: u64,
25596        index: u64,
25597    ) -> Result<PublicationMaterialRange, SemanticTransitionError> {
25598        self.checked_reader(lease)?;
25599        let storage = Arc::clone(
25600            self.publication
25601                .as_ref()
25602                .ok_or(SemanticTransitionError::NotBound)?,
25603        );
25604        let range = lease
25605            .directory
25606            .iter()
25607            .find(|range| (range.role, range.index) == (role, index))
25608            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25609        let owner = storage
25610            .allocations
25611            .get(
25612                usize::try_from(range.storage_slot)
25613                    .map_err(|_| SemanticTransitionError::ObservationMismatch)?,
25614            )
25615            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25616        let begin = usize::try_from(range.offset_bytes)
25617            .map_err(|_| SemanticTransitionError::ObservationMismatch)?;
25618        let end = usize::try_from(range.length_bytes)
25619            .ok()
25620            .and_then(|n| begin.checked_add(n))
25621            .filter(|&end| end <= owner.len())
25622            .ok_or(SemanticTransitionError::ObservationMismatch)?;
25623        if range.generation != 1 {
25624            return Err(SemanticTransitionError::ObservationMismatch);
25625        }
25626        let bytes = if begin == end {
25627            Vec::new()
25628        } else {
25629            self.publication_read(owner.view().slice(begin..end))?
25630        };
25631        Ok(PublicationMaterialRange {
25632            range: *range,
25633            capacity: owner.len() - begin,
25634            bytes,
25635        })
25636    }
25637
25638    fn read_published_record_bytes(
25639        &mut self,
25640        lease: &SemanticPublishedLease,
25641        role: SemanticStateRole,
25642    ) -> Result<Vec<u8>, SemanticTransitionError> {
25643        Ok(self
25644            .read_published_material_range(lease, role as u64, 0)?
25645            .bytes)
25646    }
25647
25648    /// Export the actual bytes of one acquired non-tensor owner, including native
25649    /// raw feedback. This performs no host tensor-value read or numeric cast.
25650    pub fn published_record(
25651        &mut self,
25652        lease: &SemanticPublishedLease,
25653        role: SemanticStateRole,
25654        index: u64,
25655        consumer_stream: u64,
25656    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25657        self.checked_reader(lease)?;
25658        if is_tensor_role(role as u64) {
25659            return Err(publication_input_error(
25660                "tensor roles require their exact model layout export",
25661            ));
25662        }
25663        let range = *lease
25664            .directory
25665            .iter()
25666            .find(|range| range.role == role as u64 && range.index == index)
25667            .ok_or_else(|| publication_input_error("acquired record range is absent"))?;
25668        self.export_publication_range(
25669            lease,
25670            range,
25671            publication_record_layout(&range),
25672            consumer_stream,
25673        )
25674    }
25675
25676    /// Encode the exact acquired raw slots and current lineage on the device,
25677    /// without packing or status/validity readback. The projection kernel traps
25678    /// on invalid provenance before the consumer event can become ready.
25679    /// All six outputs receive their original private content seals before
25680    /// export. Later tensor-content capture verifies those seals, not a new
25681    /// baseline made from potentially modified consumer aliases.
25682    pub fn published_feedback(
25683        &mut self,
25684        lease: &SemanticPublishedLease,
25685        consumer_stream: u64,
25686    ) -> Result<SemanticFeedback, SemanticTransitionError> {
25687        self.checked_reader(lease)?;
25688        dlpack_consumer_stream(consumer_stream)?;
25689        if self
25690            .admitted_transition
25691            .is_none_or(|(token, word, _)| token != lease.token || word != lease.identity.word)
25692        {
25693            return Err(publication_input_error(
25694                "feedback encoding requires this acquired parent's admitted segment",
25695            ));
25696        }
25697        // Keep the complete ordinary call outside capture, including the gaps
25698        // between allocation, producer launches, original seals and exports.
25699        // The private prepared enqueue remains usable by the segment builder.
25700        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
25701            .map_err(|error| runtime_error("feedback stream admission", error))?;
25702        let schema = SemanticFeedbackSchema::new(self.feedback_statement_bytes()?)?;
25703        let storage = Arc::clone(
25704            self.publication
25705                .as_ref()
25706                .ok_or(SemanticTransitionError::NotBound)?,
25707        );
25708        let descriptor = self.descriptor();
25709        let buffers = FeedbackBuffers::allocate(
25710            &self.provider,
25711            schema,
25712            storage.contract_value.feedback_capacity,
25713            descriptor.arena[4],
25714        )?;
25715        let schema = buffers.schema.clone();
25716        let slots = buffers.slots;
25717        let support_capacity = buffers.support_capacity;
25718        let offset_cells = buffers.support_offsets.len();
25719        // Install the permanent step owner before any kernel or export can
25720        // enqueue. A later error or unwind cannot replace/drop unfinished
25721        // outputs through a subsequent feedback call.
25722        let reader = self
25723            .steps
25724            .get_mut(&lease.token)
25725            .expect("validated feedback step");
25726        let output_index = reader.feedback.len();
25727        reader.feedback.push(buffers);
25728        let result = (|| {
25729            let reader = self
25730                .readers
25731                .get(&lease.token)
25732                .expect("validated native reader");
25733            let buffers = &self.steps[&lease.token].feedback[output_index];
25734            buffers.enqueue(
25735                &self.domain,
25736                &mut self.poisoned,
25737                &self.graph,
25738                &storage,
25739                &self
25740                    .task
25741                    .as_ref()
25742                    .ok_or(SemanticTransitionError::InvalidTaskBank)?
25743                    .1,
25744                &reader.device,
25745                descriptor,
25746            )?;
25747            // SAFETY: f32 has a padding-free byte representation. The returned
25748            // view retains the complete original tracked feature allocation.
25749            let features = unsafe { buffers.features.view().cast::<u8>() }
25750                .ok_or(SemanticTransitionError::ObservationMismatch)?;
25751            let device_validity = buffers.validity.view();
25752            let queries = buffers.query_receipts.view();
25753            let originals = buffers.original_statements.view();
25754            let offsets = buffers.support_offsets.view();
25755            let support_rows = buffers.supports.view();
25756            let features = self.export_step_view(
25757                lease,
25758                features,
25759                vec![slots as i64, schema.feature_width as i64],
25760                vec![schema.feature_width as i64, 1],
25761                (2, 32),
25762                consumer_stream,
25763            )?;
25764            let device_validity = self.export_step_view(
25765                lease,
25766                device_validity,
25767                vec![slots as i64],
25768                vec![1],
25769                (6, 8),
25770                consumer_stream,
25771            )?;
25772            let mut export_words =
25773                |view: DeviceMemoryView<u64>, shape: Vec<i64>, strides: Vec<i64>| {
25774                    // SAFETY: u64 has no padding; the complete tracked owner stays
25775                    // attached to each byte view and acquired-reader export.
25776                    let bytes = unsafe { view.cast::<u8>() }
25777                        .ok_or(SemanticTransitionError::ObservationMismatch)?;
25778                    self.export_step_view(lease, bytes, shape, strides, (1, 64), consumer_stream)
25779                };
25780            let query_receipts = export_words(queries, vec![slots as i64, 42], vec![42, 1])?;
25781            let original_statements = export_words(originals, vec![slots as i64], vec![1])?;
25782            let support_offsets = export_words(offsets, vec![offset_cells as i64], vec![1])?;
25783            let supports =
25784                export_words(support_rows, vec![support_capacity as i64, 12], vec![12, 1])?;
25785            Ok(SemanticFeedback {
25786                parent: lease.identity,
25787                schema,
25788                features,
25789                device_validity,
25790                query_receipts,
25791                original_statements,
25792                support_offsets,
25793                supports,
25794            })
25795        })();
25796        if result.is_err() {
25797            self.poisoned = true;
25798        }
25799        result
25800    }
25801
25802    fn publication_tensor_view(
25803        &mut self,
25804        lease: &SemanticPublishedLease,
25805        range: PublicationRange,
25806        layout: SemanticTensorLayout,
25807    ) -> Result<DeviceMemoryView<u8>, SemanticTransitionError> {
25808        self.checked_reader(lease)?;
25809        let view = if matches!(range.role, 1 | 3..=13 | 18..=25) {
25810            let inputs = self.ensure_step_inputs(lease)?;
25811            let view = inputs
25812                .views
25813                .get((lease.header.publication_word & 1) as usize)
25814                .expect("two publication input banks")
25815                .get(&(range.role, range.index))
25816                .ok_or(SemanticTransitionError::ObservationMismatch)?;
25817            let local = PublicationRange {
25818                offset_bytes: 0,
25819                ..range
25820            };
25821            view.slice(publication_export_span(&local, &layout, view.len())?)
25822        } else {
25823            let storage = Arc::clone(
25824                self.publication
25825                    .as_ref()
25826                    .ok_or(SemanticTransitionError::NotBound)?,
25827            );
25828            let allocation = storage
25829                .allocations
25830                .get(range.storage_slot as usize)
25831                .ok_or(SemanticTransitionError::ObservationMismatch)?;
25832            allocation
25833                .view()
25834                .slice(publication_export_span(&range, &layout, allocation.len())?)
25835        };
25836        Ok(view)
25837    }
25838
25839    fn export_publication_range(
25840        &mut self,
25841        lease: &SemanticPublishedLease,
25842        range: PublicationRange,
25843        layout: SemanticTensorLayout,
25844        consumer_stream: u64,
25845    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25846        dlpack_consumer_stream(consumer_stream)?;
25847        let view = self.publication_tensor_view(lease, range, layout)?;
25848        let shape = layout.dimensions[..layout.rank as usize]
25849            .iter()
25850            .map(|&n| {
25851                i64::try_from(n)
25852                    .map_err(|_| publication_input_error("DLPack shape exceeds signed extent"))
25853            })
25854            .collect::<Result<Vec<_>, _>>()?;
25855        let strides = layout.strides_bytes[..layout.rank as usize]
25856            .iter()
25857            .map(|&n| {
25858                i64::try_from(n / layout.element_bytes)
25859                    .map_err(|_| publication_input_error("DLPack stride exceeds signed extent"))
25860            })
25861            .collect::<Result<Vec<_>, _>>()?;
25862        let dtype = match layout.scalar_type {
25863            1 => (1, 8),
25864            2 => (1, 32),
25865            3 => (1, 64),
25866            4 => (2, 16),
25867            5 => (4, 16),
25868            6 => (2, 32),
25869            7 => (0, 64),
25870            8 => (6, 8),
25871            9 => (2, 64),
25872            _ => return Err(SemanticTransitionError::ObservationMismatch),
25873        };
25874        self.export_publication_tensor_view(
25875            lease,
25876            range.role,
25877            view,
25878            shape,
25879            strides,
25880            dtype,
25881            consumer_stream,
25882        )
25883    }
25884
25885    #[expect(
25886        clippy::too_many_arguments,
25887        reason = "publication export keeps authenticated role and DLPack geometry explicit"
25888    )]
25889    fn export_publication_tensor_view(
25890        &mut self,
25891        lease: &SemanticPublishedLease,
25892        role: u64,
25893        view: DeviceMemoryView<u8>,
25894        shape: Vec<i64>,
25895        strides: Vec<i64>,
25896        dtype: (u8, u8),
25897        consumer_stream: u64,
25898    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25899        if matches!(role, 3 | 6..=13 | 18..=25) {
25900            self.export_step_view(lease, view, shape, strides, dtype, consumer_stream)
25901        } else {
25902            self.export_reader_view(lease, view, shape, strides, dtype, consumer_stream)
25903        }
25904    }
25905
25906    fn export_publication_bank_field(
25907        &mut self,
25908        lease: &SemanticPublishedLease,
25909        field: PublicationBankField,
25910        consumer_stream: u64,
25911    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25912        dlpack_consumer_stream(consumer_stream)?;
25913        let inputs = self.ensure_step_inputs(lease)?;
25914        let (_, shape, strides) = field.layout();
25915        self.export_step_view(
25916            lease,
25917            inputs.field_view(field)?,
25918            shape,
25919            strides,
25920            (1, 64),
25921            consumer_stream,
25922        )
25923    }
25924
25925    fn export_reader_view(
25926        &mut self,
25927        lease: &SemanticPublishedLease,
25928        view: DeviceMemoryView<u8>,
25929        shape: Vec<i64>,
25930        strides: Vec<i64>,
25931        dtype: (u8, u8),
25932        consumer_stream: u64,
25933    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25934        dlpack_consumer_stream(consumer_stream)?;
25935        let guard = Arc::clone(&self.checked_reader(lease)?.aliases);
25936        self.readers
25937            .get_mut(&lease.token)
25938            .expect("validated native reader")
25939            .consumer_streams
25940            .insert(consumer_stream);
25941        self.export_owned_view(view, shape, strides, dtype, guard, consumer_stream)
25942    }
25943
25944    fn export_step_view(
25945        &mut self,
25946        lease: &SemanticPublishedLease,
25947        view: DeviceMemoryView<u8>,
25948        shape: Vec<i64>,
25949        strides: Vec<i64>,
25950        dtype: (u8, u8),
25951        consumer_stream: u64,
25952    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25953        dlpack_consumer_stream(consumer_stream)?;
25954        let guard = Arc::clone(&self.checked_step(lease)?.aliases);
25955        self.steps
25956            .get_mut(&lease.token)
25957            .expect("validated output step")
25958            .consumer_streams
25959            .insert(consumer_stream);
25960        self.export_owned_view(view, shape, strides, dtype, guard, consumer_stream)
25961    }
25962
25963    fn export_owned_view(
25964        &mut self,
25965        view: DeviceMemoryView<u8>,
25966        shape: Vec<i64>,
25967        strides: Vec<i64>,
25968        dtype: (u8, u8),
25969        guard: Arc<()>,
25970        consumer_stream: u64,
25971    ) -> Result<DlpackManagedTensor, SemanticTransitionError> {
25972        let storage = Arc::clone(
25973            self.publication
25974                .as_ref()
25975                .ok_or(SemanticTransitionError::NotBound)?,
25976        );
25977        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
25978            .map_err(|error| runtime_error("owned export stream admission", error))?;
25979        // The actual bank or step has retained this stream before enqueue.
25980        // Its final retirement joins use even if the capsule was deleted early.
25981        if let Err(error) = self.order_content_consumers(consumer_stream) {
25982            self.poisoned = true;
25983            return Err(error);
25984        }
25985        Ok(export_owned_allocation(
25986            view,
25987            shape,
25988            strides,
25989            dtype,
25990            self.provider.device().ordinal() as i32,
25991            guard,
25992            storage,
25993            None,
25994            None,
25995        ))
25996    }
25997
25998    // Shared cold completion for export, final comparison and release. It joins
25999    // submitted work only, without dropping content, aliases or the native lease.
26000    fn complete_step_consumers(
26001        &mut self,
26002        lease: &SemanticPublishedLease,
26003        consumer_streams: &[u64],
26004    ) -> Result<(), SemanticTransitionError> {
26005        self.checked_step(lease)?;
26006        self.complete_step_consumers_by_token(lease.token, consumer_streams)
26007    }
26008
26009    fn complete_step_consumers_by_token(
26010        &mut self,
26011        token: u64,
26012        consumer_streams: &[u64],
26013    ) -> Result<(), SemanticTransitionError> {
26014        let streams = self.step_consumer_streams(token, consumer_streams)?;
26015        let result = (|| {
26016            self.stream
26017                .context()
26018                .bind_to_thread()
26019                .map_err(|error| runtime_error("release context binding", error))?;
26020            for stream in streams {
26021                let event = self
26022                    .stream
26023                    .context()
26024                    .new_event(None)
26025                    .map_err(|error| runtime_error("consumer completion event", error))?;
26026                self.release_events.push(event);
26027                let event = self.release_events.last().expect("retained consumer event");
26028                // SAFETY: trusted consumer supplied its actual stream on this
26029                // device; the driver validates it. Record after the last use.
26030                unsafe {
26031                    cudarc::driver::result::event::record(
26032                        event.cu_event(),
26033                        dlpack_consumer_stream(stream)?,
26034                    )
26035                }
26036                .map_err(|error| runtime_error("consumer final event record", error))?;
26037                self.stream
26038                    .wait(event)
26039                    .map_err(|error| runtime_error("consumer final event join", error))?;
26040            }
26041            wait_on_stream(
26042                &self.stream,
26043                &mut self.poisoned,
26044                &mut self.stream_waits,
26045                "published reader consumer completion",
26046                CudaStream::synchronize,
26047            )?;
26048            Ok(())
26049        })();
26050        if result.is_err() {
26051            self.poisoned = true;
26052        } else {
26053            // Every retained event's recorded work and native-stream wait has
26054            // completed. Retire them here, even when export keeps readers live;
26055            // CudaEvent::drop binds its retained context before destruction.
26056            self.release_events.clear();
26057        }
26058        result
26059    }
26060
26061    fn step_consumer_streams(
26062        &self,
26063        token: u64,
26064        consumer_streams: &[u64],
26065    ) -> Result<BTreeSet<u64>, SemanticTransitionError> {
26066        let step = self
26067            .steps
26068            .get(&token)
26069            .ok_or_else(|| publication_input_error("original step has been fully released"))?;
26070        let mut streams = consumer_streams.iter().copied().collect::<BTreeSet<_>>();
26071        if !step.consumer_streams.is_subset(&streams)
26072            || self
26073                .readers
26074                .get(&token)
26075                .is_some_and(|reader| !reader.consumer_streams.is_subset(&streams))
26076        {
26077            return Err(publication_input_error(
26078                "release omits a consumer stream that received a published alias",
26079            ));
26080        }
26081        for &stream in &streams {
26082            dlpack_consumer_stream(stream)?;
26083        }
26084        // Managed tensor producers negotiated readiness onto the legacy default
26085        // stream. Join it even when validation rejected a handoff before hashing.
26086        if !step.content.is_empty() {
26087            streams.insert(1);
26088        }
26089        Ok(streams)
26090    }
26091
26092    /// Retire all aliases and their final consumer use while keeping the actual
26093    /// native reader acquired. This cold boundary performs the same completion
26094    /// checks as release, but no native decrement. It permits final guarded
26095    /// comparison after callbacks have relinquished their writable aliases.
26096    pub fn quiesce_published_reader(
26097        &mut self,
26098        lease: &SemanticPublishedLease,
26099        consumer_streams: &[u64],
26100    ) -> Result<(), SemanticTransitionError> {
26101        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
26102            .map_err(|error| runtime_error("reader quiescence stream admission", error))?;
26103        self.checked_reader(lease)?;
26104        self.quiesce_step_content(lease, consumer_streams)
26105    }
26106
26107    fn quiesce_step_content(
26108        &mut self,
26109        lease: &SemanticPublishedLease,
26110        consumer_streams: &[u64],
26111    ) -> Result<(), SemanticTransitionError> {
26112        let step = self.checked_step(lease)?;
26113        if Arc::strong_count(&step.content_witnesses) != 1 {
26114            return Err(publication_input_error(
26115                "content witnesses still retain this step",
26116            ));
26117        }
26118        if step.content.is_empty()
26119            && (Arc::strong_count(&step.aliases) != 1
26120                || self
26121                    .readers
26122                    .get(&lease.token)
26123                    .is_some_and(|reader| Arc::strong_count(&reader.aliases) != 1))
26124        {
26125            return Err(publication_input_error(
26126                "published tensor aliases still retain this reader",
26127            ));
26128        }
26129        self.complete_step_consumers(lease, consumer_streams)?;
26130        // Captured producers may themselves be exports of this same parent.
26131        // Retire those internal aliases only after their final device use and
26132        // after all witnesses are gone; then distinguish real external aliases.
26133        let step = self
26134            .steps
26135            .get_mut(&lease.token)
26136            .expect("completed content step");
26137        step.content.clear();
26138        if Arc::strong_count(&step.aliases) != 1 {
26139            return Err(publication_input_error(
26140                "output aliases still retain this step",
26141            ));
26142        }
26143        if self
26144            .readers
26145            .get(&lease.token)
26146            .is_some_and(|reader| Arc::strong_count(&reader.aliases) != 1)
26147        {
26148            return Err(publication_input_error(
26149                "published tensor aliases still retain this reader",
26150            ));
26151        }
26152        Ok(())
26153    }
26154
26155    /// Retire only the actual publication reader after final bank use. Original
26156    /// numerical content, producer seals and policy outputs retain this step.
26157    /// A live bank alias still prevents reuse; no retained content is discarded.
26158    pub fn release_published_reader(
26159        &mut self,
26160        lease: &mut SemanticPublishedLease,
26161        consumer_streams: &[u64],
26162    ) -> Result<(), SemanticTransitionError> {
26163        #[cfg(feature = "semantic-policy")]
26164        self.require_closed_evaluations()?;
26165        // This public cold boundary waits and reads completion metadata. Keep
26166        // the entire call outside capture, including the final bank decrement.
26167        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
26168            .map_err(|error| runtime_error("reader retirement stream admission", error))?;
26169        self.checked_step(lease)?;
26170        let reader = self.checked_reader(lease)?;
26171        if Arc::strong_count(&reader.aliases) != 1
26172            || self
26173                .admitted_transition
26174                .is_some_and(|(token, _, _)| token == lease.token)
26175        {
26176            return Err(publication_input_error(
26177                "publication reader still owns aliases or an admitted transition",
26178            ));
26179        }
26180        self.complete_step_consumers(lease, consumer_streams)?;
26181        self.retire_published_reader(lease)
26182    }
26183
26184    fn retire_published_reader(
26185        &mut self,
26186        lease: &mut SemanticPublishedLease,
26187    ) -> Result<(), SemanticTransitionError> {
26188        let reader = self.checked_reader(lease)?;
26189        if Arc::strong_count(&reader.aliases) != 1
26190            || (self
26191                .admitted_transition
26192                .is_some_and(|(token, _, _)| token == lease.token)
26193                && (self.continuation_base.is_some() || self.text_binding.is_some()))
26194        {
26195            return Err(publication_input_error(
26196                "publication reader still owns aliases or an unfinished transition",
26197            ));
26198        }
26199        let result = (|| {
26200            self.publication_command(3, Some(lease.token))?;
26201            let result = self.publication_read(self.readers[&lease.token].device.view())?[0];
26202            if result.status != 0
26203                || result.active != 0
26204                || result.instance != lease.identity.instance
26205                || result.word != lease.identity.word
26206            {
26207                return Err(SemanticTransitionError::PublicationRefused {
26208                    status: result.status,
26209                });
26210            }
26211            Ok(())
26212        })();
26213        if result.is_err() {
26214            self.poisoned = true;
26215            return result;
26216        }
26217        lease.active = false;
26218        self.readers.remove(&lease.token);
26219        if self
26220            .admitted_transition
26221            .is_some_and(|(token, _, _)| token == lease.token)
26222        {
26223            self.admitted_transition = None;
26224        }
26225        Ok(())
26226    }
26227
26228    /// All aliases must have returned their managed owners. Completion events
26229    /// are recorded after final consumer use, joined, and completed before the
26230    /// sole native reader decrement, unless that reader has already retired.
26231    /// Failure retains the original step and every unfinished owner.
26232    pub fn release(
26233        &mut self,
26234        lease: &mut SemanticPublishedLease,
26235        consumer_streams: &[u64],
26236    ) -> Result<(), SemanticTransitionError> {
26237        #[cfg(feature = "semantic-policy")]
26238        self.require_closed_evaluations()?;
26239        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
26240            .map_err(|error| runtime_error("step retirement stream admission", error))?;
26241        self.quiesce_step_content(lease, consumer_streams)?;
26242        if lease.active {
26243            self.retire_published_reader(lease)?;
26244        }
26245        self.steps.remove(&lease.token);
26246        self.release_events.clear();
26247        Ok(())
26248    }
26249
26250    /// Join final consumers and retire one actually completed prepared owner.
26251    /// The device reader was released by its recorded body; this cold operation
26252    /// never issues a second decrement or replaces its original private seals.
26253    pub fn release_prepared_step(
26254        &mut self,
26255        step: &SemanticPreparedStep,
26256        consumer_streams: &[u64],
26257    ) -> Result<(), SemanticTransitionError> {
26258        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
26259            .map_err(|error| runtime_error("prepared step retirement stream admission", error))?;
26260        self.quiesce_prepared_step(step, consumer_streams)?;
26261        let owner = self
26262            .steps
26263            .get_mut(&step.token)
26264            .expect("completed prepared step");
26265        let prepared = owner.prepared.as_mut().expect("prepared owner");
26266        // These are internal handles, not outstanding consumer witnesses.
26267        // Actual tensor owners remain in content until the final checks below.
26268        for branch in &mut prepared.branches {
26269            branch.continuation = None;
26270            #[cfg(feature = "semantic-policy")]
26271            {
26272                branch.policy_witness = None;
26273                branch.policy = None;
26274                branch.policy_sources.clear();
26275            }
26276        }
26277        if Arc::strong_count(&owner.content_witnesses) != 1 {
26278            return Err(publication_input_error(
26279                "content witnesses still retain this prepared step",
26280            ));
26281        }
26282        owner.content.clear();
26283        if Arc::strong_count(&owner.aliases) != 1 {
26284            return Err(publication_input_error(
26285                "output aliases still retain this prepared step",
26286            ));
26287        }
26288        self.steps.remove(&step.token);
26289        Ok(())
26290    }
26291
26292    /// Establish final device use without discarding the producer owners. This
26293    /// permits the caller to retire callback-owned aliases outside its mutex.
26294    pub fn quiesce_prepared_step(
26295        &mut self,
26296        step: &SemanticPreparedStep,
26297        consumer_streams: &[u64],
26298    ) -> Result<(), SemanticTransitionError> {
26299        self.checked_prepared_step(step, false)?;
26300        if !self
26301            .prepared_segment
26302            .as_ref()
26303            .expect("checked prepared scope")
26304            .completed
26305        {
26306            return Err(publication_input_error(
26307                "prepared step cannot retire before actual segment completion",
26308            ));
26309        }
26310        #[cfg(feature = "semantic-policy")]
26311        if self
26312            .policy_tapes
26313            .iter()
26314            .any(|tape| tape.policy.text_binding._witness.reader_token == step.token)
26315        {
26316            return Err(SemanticTransitionError::UnconsumedPolicyTape);
26317        }
26318        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
26319            .map_err(|error| runtime_error("prepared step quiescence stream admission", error))?;
26320        self.complete_step_consumers_by_token(step.token, consumer_streams)
26321    }
26322
26323    pub fn admit_transition(
26324        &mut self,
26325        lease: &SemanticPublishedLease,
26326        kind: SemanticTransitionKind,
26327    ) -> Result<(), SemanticTransitionError> {
26328        #[cfg(feature = "semantic-policy")]
26329        self.require_closed_evaluations()?;
26330        self.checked_reader(lease)?;
26331        if kind == SemanticTransitionKind::Update {
26332            return Err(publication_input_error(
26333                "updates require a prepared step with native training and pending-output owners",
26334            ));
26335        }
26336        if self.admitted_transition.is_some() || self.continuation_base.is_some() {
26337            return Err(publication_input_error(
26338                "an admitted transition already owns the pending invocation",
26339            ));
26340        }
26341        let control = Arc::clone(
26342            self.publication
26343                .as_ref()
26344                .ok_or(SemanticTransitionError::NotBound)?,
26345        );
26346        let current = self.publication_read(control.control.view())?[0];
26347        if current.instance != lease.identity.instance || current.word != lease.identity.word {
26348            return Err(publication_input_error(
26349                "transition requires the current acquired parent, not an older retained reader",
26350            ));
26351        }
26352        if lease.header.terminal == 2 {
26353            return Err(publication_input_error(
26354                "final publication admits reads, not another transition",
26355            ));
26356        }
26357        let reserve = if matches!(
26358            kind,
26359            SemanticTransitionKind::Proposal | SemanticTransitionKind::Drain
26360        ) {
26361            2
26362        } else {
26363            1
26364        };
26365        if lease.header.fuel < reserve {
26366            return Err(publication_input_error(
26367                "acquired publication has insufficient transition fuel",
26368            ));
26369        }
26370        if (lease.header.terminal == 1) != (kind == SemanticTransitionKind::Drain) {
26371            return Err(SemanticTransitionError::PublicationRefused { status: 4 });
26372        }
26373        self.admitted_transition = Some((lease.token, lease.identity.word, kind));
26374        Ok(())
26375    }
26376
26377    /// Snapshot original forward outputs against this exact admitted reader.
26378    /// Completion records and outputs must come from the forward that consumed
26379    /// the acquired parent; metadata alone never grants use authority.
26380    pub fn bind_continuation(
26381        &mut self,
26382        lease: &SemanticPublishedLease,
26383        continuation: SemanticContinuationInput,
26384        witness: &SemanticTensorContentWitness,
26385        consumer_stream: u64,
26386    ) -> Result<(), SemanticTransitionError> {
26387        let mut handoff = RetainedTensorAdmission {
26388            inputs: Some(vec![continuation]),
26389            stream: Arc::clone(self.provider.device().inner().stream()),
26390            ready: false,
26391        };
26392        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
26393            .map_err(|error| runtime_error("continuation stream admission", error))?;
26394        self.checked_reader(lease)?;
26395        self.ensure_rebindable()?;
26396        self.checked_content_witness(lease, witness)?;
26397        dlpack_consumer_stream(consumer_stream)?;
26398        let (_, base_word, kind) = self
26399            .admitted_transition
26400            .filter(|(token, word, _)| *token == lease.token && *word == lease.identity.word)
26401            .ok_or_else(|| {
26402                publication_input_error(
26403                    "continuation has no admitted invocation for this exact acquired reader",
26404                )
26405            })?;
26406        if self.continuation_base.is_some() {
26407            return Err(publication_input_error(
26408                "an unconsumed continuation already owns the pending bank",
26409            ));
26410        }
26411        if !matches!(
26412            self.steps[&lease.token].content[witness.index].seals,
26413            TensorContentSeals::Captured(_)
26414        ) {
26415            return Err(publication_input_error(
26416                "continuation requires its original transient producer witness",
26417            ));
26418        }
26419        let storage = Arc::clone(
26420            self.publication
26421                .as_ref()
26422                .ok_or(SemanticTransitionError::NotBound)?,
26423        );
26424        let continuation = handoff
26425            .inputs
26426            .as_ref()
26427            .expect("retained continuation")
26428            .first()
26429            .expect("one continuation");
26430        let tensor_count = continuation.tensors.len();
26431        let active_capacity = storage
26432            .contract_value
26433            .feedback_capacity
26434            .checked_add(32)
26435            .ok_or_else(|| publication_input_error("continuation active capacity overflow"))?;
26436        let (physical_blocks, model_schema_digest, model_identity) =
26437            storage.continuation_block_contract(kind, continuation, false)?;
26438        let service_layouts =
26439            continuation_service_layouts(tensor_count, active_capacity, physical_blocks)?;
26440        if continuation.authority_decisions.is_empty() {
26441            return Err(publication_input_error(
26442                "continuation lacks its actual fresh authority decision snapshot",
26443            ));
26444        }
26445        let continuation = handoff
26446            .inputs
26447            .take()
26448            .expect("retained continuation")
26449            .pop()
26450            .expect("one continuation");
26451        let SemanticContinuationInput {
26452            mut tensors,
26453            authority_decisions,
26454            text_rows,
26455            text_row_count,
26456            selected_text,
26457            active_rows,
26458            active_row_count,
26459            numerical_admissibility,
26460            numerical_blocks,
26461            model_schema_digest: _,
26462            model_identity: _,
26463        } = continuation;
26464        let mut services = vec![
26465            text_rows,
26466            text_row_count,
26467            selected_text,
26468            active_rows,
26469            active_row_count,
26470            numerical_admissibility,
26471        ];
26472        services.extend(numerical_blocks);
26473        tensors.extend(
26474            services
26475                .into_iter()
26476                .zip(service_layouts)
26477                .map(|(tensor, layout)| SemanticTensorInput {
26478                    layout,
26479                    logical_begin: 0,
26480                    logical_end: 0,
26481                    tensor,
26482                    native_allocation: None,
26483                }),
26484        );
26485        // Verify the same roster against its original private digest. This is
26486        // an event-ordered device guard, not a new capture or a host value read.
26487        self.verify_tensor_content(lease, witness, tensors, consumer_stream)?;
26488        let numerical_block_snapshot = if let Some(blocks) = physical_blocks {
26489            let original =
26490                self.steps[&lease.token].content[witness.index].tensors[tensor_count + 6].clone();
26491            let cells = blocks
26492                .checked_mul(6)
26493                .ok_or(SemanticTransitionError::GenerationExhausted)?;
26494            let snapshot = Arc::new(allocate_publication::<f64>(&self.provider, cells)?);
26495            enqueue_numerical_block_snapshot(
26496                &self.domain,
26497                &mut self.poisoned,
26498                &original,
26499                &snapshot,
26500            )?;
26501            Some(snapshot)
26502        } else {
26503            None
26504        };
26505        let original = &self.steps[&lease.token].content[witness.index].tensors;
26506        let services = original[tensor_count..].to_vec();
26507        if services.len() != 6 + usize::from(physical_blocks.is_some()) {
26508            return Err(publication_input_error(
26509                "continuation witness has the wrong original service roster",
26510            ));
26511        }
26512        let text_binding = Arc::new(TextBindingStorage {
26513            inputs: services,
26514            numerical_block_snapshot,
26515            model_contract: None,
26516            physical_blocks: physical_blocks.unwrap_or(0) as u64,
26517            model_schema_digest,
26518            model_identity,
26519            _witness: witness.clone(),
26520            _model_content_witness: None,
26521            consumer_stream,
26522            parent: TextBindingParent::Published {
26523                bank: (lease.identity.word & 1) as usize,
26524                header: lease.header,
26525            },
26526        });
26527        let authority_bytes = authority_decisions.len() as u64;
26528        let (uploads, pending_layouts) = prepare_continuation_payloads(
26529            &storage,
26530            &original[..tensor_count],
26531            &authority_decisions,
26532            kind,
26533        )?;
26534        let prepared = PreparedContinuation::prepare(
26535            &self.provider,
26536            Arc::clone(&storage),
26537            self.checked_reader(lease)?.device.view(),
26538            Arc::clone(&text_binding),
26539            text_binding.continuation_inputs(
26540                kind,
26541                authority_bytes,
26542                0,
26543                ModelUpdateContinuationInputs::default(),
26544            ),
26545            None,
26546            &uploads,
26547            &pending_layouts,
26548        )?;
26549        // Install the same concrete owners before any upload/copy can enqueue.
26550        // On error or unwind, step retirement and Session quarantine retain
26551        // sources, original witness/services, destination storage and the lease.
26552        self.publication_uploads = uploads;
26553        self.text_binding = Some(Arc::clone(&text_binding));
26554        let result = (|| {
26555            for (slot, payload) in &self.publication_uploads {
26556                if let PublicationPayload::Metadata(bytes) = payload {
26557                    if !bytes.is_empty() {
26558                        let mut destination =
26559                            storage.allocations[*slot].view().slice(..bytes.len());
26560                        self.provider
26561                            .htod_launch_metadata_sync_copy_into(bytes, &mut destination)
26562                            .map_err(|error| {
26563                                runtime_error("continuation fresh authority upload", error)
26564                            })?;
26565                    }
26566                }
26567            }
26568            prepared.enqueue(&self.domain, &mut self.poisoned)
26569        })();
26570        if let Err(error) = result {
26571            self.poisoned = true;
26572            return Err(error);
26573        }
26574        if let Err(error) = self.order_content_consumers(consumer_stream) {
26575            self.poisoned = true;
26576            return Err(error);
26577        }
26578        self.publication_uploads.clear();
26579        self.continuation_base = Some(base_word);
26580        #[cfg(feature = "semantic-policy")]
26581        if kind == SemanticTransitionKind::Proposal {
26582            self.attach_policy_continuation()?;
26583        }
26584        if kind != SemanticTransitionKind::Proposal {
26585            let rng = self.continuation_rng(lease)?;
26586            self.captured = None;
26587            self.rng = Some(rng);
26588            self.next_proposal = u64::from(rng.proposal);
26589        }
26590        Ok(())
26591    }
26592
26593    pub fn policy_layout(&self) -> Result<SemanticPolicyLayout, SemanticTransitionError> {
26594        self.ensure_quiescent()?;
26595        SemanticPolicyLayout::from_components(&self.codebooks.components)
26596    }
26597
26598    /// All original category spans in native catalogue order. Inactive TEXT
26599    /// retains its reserved span, but the device emits singleton NULL without
26600    /// reading that span. Selection never changes subsequent category offsets.
26601    pub fn policy_support_layout(
26602        &self,
26603    ) -> Result<(Vec<std::ops::Range<usize>>, usize), SemanticTransitionError> {
26604        self.ensure_quiescent()?;
26605        Ok(self.codebooks.support_layout())
26606    }
26607
26608    pub fn new(
26609        provider: &Arc<CudaKernelProvider>,
26610        domain: &ResidentExecutionDomain,
26611    ) -> Result<Self, SemanticTransitionError> {
26612        let mut graph = provider
26613            .allocate_semantic_hypergraph(
26614                domain,
26615                SemanticHypergraphCapacities::try_new(3, 4, 4, 4)
26616                    .map_err(SemanticTransitionError::Semantic)?,
26617            )
26618            .map_err(SemanticTransitionError::Semantic)?;
26619        let base = graph.empty_root();
26620        graph
26621            .admit_records(
26622                base,
26623                SemanticAdmissionRecords {
26624                    predicates: vec![],
26625                    records: vec![],
26626                    supports: vec![],
26627                },
26628                SemanticAdmissionLimits {
26629                    max_records: 0,
26630                    max_terms: 0,
26631                    max_references: 0,
26632                    max_utf8_bytes: 0,
26633                },
26634            )
26635            .map_err(SemanticTransitionError::Semantic)?;
26636        Self::from_hypergraph(graph)
26637    }
26638
26639    /// Consumes the sole admitted semantic owner. The acquired base, accepted
26640    /// symbol bytes, descriptors and arena remain inseparable for capture/replay.
26641    pub fn from_hypergraph(graph: SemanticHypergraph) -> Result<Self, SemanticTransitionError> {
26642        Self::from_hypergraph_with_program(graph, None)
26643    }
26644
26645    /// Bind the source-derived edit grammar before allocating the resident
26646    /// codebooks and policy buffers. The task observer is bound separately.
26647    pub fn from_hypergraph_with_program(
26648        graph: SemanticHypergraph,
26649        program: Option<&crate::SemanticProgramAdmission>,
26650    ) -> Result<Self, SemanticTransitionError> {
26651        let (provider, domain) = graph
26652            .transition_owner()
26653            .map_err(SemanticTransitionError::Semantic)?;
26654        validate_execution_domain(&provider, &domain)
26655            .map_err(|e| runtime_error("domain validation", e))?;
26656        let execute = provider
26657            .device()
26658            .inner()
26659            .get_func("xlog_semantic_transition", "semantic_transition_execute")
26660            .ok_or_else(|| {
26661                runtime_error("kernel lookup", "semantic transition kernel unavailable")
26662            })?;
26663        let admission = graph
26664            .admission()
26665            .expect("transition owner validated admission");
26666        let root = admission.base();
26667        let base_snapshot = *admission.base_snapshot();
26668        let codebooks = ActionCodebooks::derive(admission, graph.transition_arena()[1], program)?;
26669        let bytes = codebooks.input_cells * (size_of::<f32>() + size_of::<u8>())
26670            + SCRATCH_BYTES
26671            + OBSERVATION_BYTES
26672            + codebooks.words.len() * 8
26673            + COMPONENT_COUNT * size_of::<SemanticComponent>();
26674        let mut reservation = provider
26675            .memory()
26676            .reserve_bytes(bytes as u64)
26677            .map_err(|e| runtime_error("reservation", e))?;
26678        let logits = reservation
26679            .alloc::<f32>(codebooks.input_cells)
26680            .map_err(|e| runtime_error("logits allocation", e))?;
26681        let support = reservation
26682            .alloc::<u8>(codebooks.input_cells)
26683            .map_err(|e| runtime_error("support allocation", e))?;
26684        let scratch = reservation
26685            .alloc::<u64>(SCRATCH_BYTES / 8)
26686            .map_err(|e| runtime_error("scratch allocation", e))?;
26687        let receipts = reservation
26688            .alloc::<SemanticTransitionReceipt>(COMPONENT_COUNT)
26689            .map_err(|e| runtime_error("receipt allocation", e))?;
26690        let state = reservation
26691            .alloc::<DeviceState>(1)
26692            .map_err(|e| runtime_error("state allocation", e))?;
26693        let device_codebooks = reservation
26694            .alloc::<u64>(codebooks.words.len())
26695            .map_err(|e| runtime_error("codebook allocation", e))?;
26696        let device_components = reservation
26697            .alloc::<SemanticComponent>(COMPONENT_COUNT)
26698            .map_err(|e| runtime_error("component allocation", e))?;
26699        debug_assert_eq!(reservation.remaining_bytes(), 0);
26700        let stream = provider
26701            .memory()
26702            .runtime()
26703            .and_then(|r| r.stream_pool().resolve(domain.stream_id()))
26704            .ok_or_else(|| runtime_error("stream resolution", "owned stream is unavailable"))?;
26705        let mut session = Self {
26706            captured: None,
26707            provider,
26708            domain: domain.clone(),
26709            stream: stream.clone(),
26710            graph: std::mem::ManuallyDrop::new(graph),
26711            root,
26712            base_snapshot,
26713            codebooks,
26714            device_codebooks,
26715            device_components,
26716            task: None,
26717            cold_content: None,
26718            initial_prefill: None,
26719            retained_initial_prefill: None,
26720            checkpoint_initial_prefill: None,
26721            training_views: None,
26722            training_origins: None,
26723            task_epoch: 0,
26724            task_observed: false,
26725            publication: None,
26726            learning_phases: Vec::new(),
26727            publication_uploads: Vec::new(),
26728            publication_issuer: Arc::new(()),
26729            readers: BTreeMap::new(),
26730            steps: BTreeMap::new(),
26731            next_reader: 0,
26732            prepared_segment: None,
26733            prepared_resources: Vec::new(),
26734            continuation_base: None,
26735            text_binding: None,
26736            admitted_transition: None,
26737            release_events: Vec::new(),
26738            logits,
26739            support,
26740            scratch,
26741            receipts,
26742            state,
26743            pinned: PinnedObservation::new(stream.clone())?,
26744            execute,
26745            #[cfg(feature = "semantic-policy")]
26746            policy: None,
26747            #[cfg(feature = "semantic-policy")]
26748            pending_policy: None,
26749            #[cfg(feature = "semantic-policy")]
26750            policy_tapes: Vec::new(),
26751            rng: None,
26752            next_proposal: 0,
26753            pending: false,
26754            poisoned: false,
26755            stream_waits: 0,
26756        };
26757        session.validate_ranges()?;
26758        session.upload_cold_codebooks()?;
26759        Ok(session)
26760    }
26761
26762    pub fn is_poisoned(&self) -> bool {
26763        self.poisoned || self.graph.ensure_not_poisoned().is_err()
26764    }
26765
26766    /// Irreversibly close this owner after trusted application validation fails,
26767    /// including a failure discovered after cold parent binding has completed.
26768    /// All existing readers/controllers consult this same poison state before
26769    /// further execution. Repeated aborts are harmless; no resource is freed,
26770    /// no device work is enqueued, and no poisoned CUDA context is reset.
26771    /// Existing recorded retirement/quarantine retains outstanding owners.
26772    /// A fatal CUDA error still requires termination of the isolated process.
26773    pub fn abort(&mut self) {
26774        self.poisoned = true;
26775    }
26776
26777    /// Join the actual cold observer before its fresh, unpublished Session is
26778    /// removed from the Python owner. A failed wait keeps every allocation in
26779    /// that owner and prohibits a restored Session from overlapping it.
26780    pub fn join_observed_cold_release(&mut self) -> Result<(), SemanticTransitionError> {
26781        if self.is_poisoned()
26782            || self.cold_content.is_none()
26783            || self.task.is_some()
26784            || self.task_epoch != 0
26785            || self.task_observed
26786            || self.publication.is_some()
26787            || self.captured.is_some()
26788            || !self.readers.is_empty()
26789            || !self.steps.is_empty()
26790            || self.prepared_segment.is_some()
26791            || self.initial_prefill.is_some()
26792            || self.retained_initial_prefill.is_some()
26793            || self.checkpoint_initial_prefill.is_some()
26794        {
26795            return Err(publication_input_error(
26796                "cold release requires the observed, unpublished fresh task",
26797            ));
26798        }
26799        let result = self
26800            .stream
26801            .context()
26802            .bind_to_thread()
26803            .and_then(|_| self.stream.context().synchronize());
26804        if let Err(error) = result {
26805            self.poisoned = true;
26806            return Err(runtime_error("fresh cold observer completion", error));
26807        }
26808        Ok(())
26809    }
26810
26811    /// Destroy the joined cold owner outside the Python Session mutex, then
26812    /// complete the allocator's real pending deallocations before returning.
26813    pub fn finish_observed_cold_release(self) -> Result<(), SemanticTransitionError> {
26814        let memory = Arc::clone(self.provider.memory());
26815        drop(self);
26816        memory
26817            .reap_pending_deallocations()
26818            .map_err(|error| runtime_error("fresh cold allocation retirement", error))?;
26819        if memory.allocated_bytes() != 0
26820            || memory
26821                .runtime()
26822                .is_some_and(|runtime| runtime.bytes_outstanding() != 0)
26823        {
26824            return Err(publication_input_error(
26825                "fresh cold allocation owners remain after retirement",
26826            ));
26827        }
26828        Ok(())
26829    }
26830
26831    /// Inspect the actual cold root, or a decoded replay predecessor, through
26832    /// the retained native admission before importing its task authority.
26833    /// The selected replay is not restored here, and these records establish
26834    /// neither historical execution nor any current use permission.
26835    pub fn task_observation_roots(
26836        &mut self,
26837        spec: &SemanticTaskEvaluationSpec,
26838        replay: Option<&SemanticReplayMaterial>,
26839    ) -> Result<SemanticTaskObservationRoots, SemanticTransitionError> {
26840        self.ensure_rebindable()?;
26841        if self.publication.is_some() || self.captured.is_some() {
26842            return Err(publication_input_error(
26843                "task observation roots require a cold unpublished Session",
26844            ));
26845        }
26846        let admission = self
26847            .graph
26848            .admission()
26849            .ok_or(SemanticTransitionError::NotBound)?;
26850        spec.validate_records(admission.records())?;
26851        if let Some(replay) = replay {
26852            return replay
26853                .predecessor
26854                .graph
26855                .task_observation_roots(admission, spec.statement_records)
26856                .map_err(SemanticTransitionError::Semantic);
26857        }
26858        let material = self
26859            .graph
26860            .export_transition_root(self.root)
26861            .map_err(SemanticTransitionError::Semantic)?;
26862        let admission = self
26863            .graph
26864            .admission()
26865            .ok_or(SemanticTransitionError::NotBound)?;
26866        material
26867            .task_observation_roots(admission, spec.statement_records)
26868            .map_err(SemanticTransitionError::Semantic)
26869    }
26870
26871    /// Execute the supplied native observer and bind its outputs to this admission.
26872    /// This data binding does not issue publication, inference, or training rights.
26873    /// The trusted controller must independently import those rights before use.
26874    pub fn bind_task_evaluation(
26875        &mut self,
26876        spec: SemanticTaskEvaluationSpec,
26877    ) -> Result<Identity256, SemanticTransitionError> {
26878        self.ensure_rebindable()?;
26879        if self.publication.is_some() {
26880            return Err(publication_input_error(
26881                "task data is immutable after its canonical parent is initialized",
26882            ));
26883        }
26884        let admission = self
26885            .graph
26886            .admission()
26887            .ok_or(SemanticTransitionError::NotBound)?;
26888        let next_epoch = self
26889            .task_epoch
26890            .checked_add(1)
26891            .ok_or(SemanticTransitionError::GenerationExhausted)?;
26892        spec.validate_records(admission.records())?;
26893        if spec
26894            .program
26895            .editable_program()
26896            .map(ActionCodebooks::program_binding)
26897            != self.codebooks.program_binding
26898        {
26899            return Err(publication_input_error(
26900                "task editable program differs from the cold action grammar",
26901            ));
26902        }
26903        let observation = spec
26904            .program
26905            .observe(Arc::clone(&self.provider))
26906            .inspect_err(|_error| {
26907                self.poisoned = true;
26908            })?;
26909        let binding = TaskEvaluationBinding::bind(admission, spec, observation)?;
26910        if self
26911            .cold_content
26912            .is_some_and(|expected| binding.content() != expected)
26913        {
26914            self.poisoned = true;
26915            return Err(publication_input_error(
26916                "final task content differs from the executed cold admission",
26917            ));
26918        }
26919        #[cfg(feature = "semantic-policy")]
26920        {
26921            let material = self
26922                .graph
26923                .export_transition_root(self.root)
26924                .map_err(SemanticTransitionError::Semantic)?;
26925            if material.digest != *self.base_snapshot.digest().as_bytes() {
26926                self.poisoned = true;
26927                return Err(SemanticTransitionError::ObservationMismatch);
26928            }
26929        }
26930        let words = binding.words(self.graph.transition_arena()[1]);
26931        let mut reservation = self
26932            .provider
26933            .memory()
26934            .reserve_bytes((words.len() * size_of::<u64>()) as u64)
26935            .map_err(|error| runtime_error("private task reservation", error))?;
26936        let device = reservation
26937            .alloc::<u64>(words.len())
26938            .map_err(|error| runtime_error("private task allocation", error))?;
26939        // Retain the new owner before the first may-enqueue boundary. A failed
26940        // upload/adoption poisons reuse and keeps its storage until Session drop.
26941        self.captured = None;
26942        let identity = binding.identity();
26943        self.task = Some((binding, device));
26944        let (_, device) = self.task.as_mut().expect("private task installed above");
26945        self.provider
26946            .htod_sync_copy_into_tracked(&words, device)
26947            .map_err(|error| {
26948                self.poisoned = true;
26949                runtime_error("private task upload", error)
26950            })?;
26951        let mut recorder = self.domain.new_strict_recorder();
26952        recorder.read_write(device);
26953        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |_| {
26954            Ok::<(), XlogError>(())
26955        })?;
26956        wait_on_stream(
26957            &self.stream,
26958            &mut self.poisoned,
26959            &mut self.stream_waits,
26960            "private task adoption wait",
26961            CudaStream::synchronize,
26962        )?;
26963        self.validate_ranges()?;
26964        self.task_epoch = next_epoch;
26965        Ok(identity)
26966    }
26967
26968    /// Execute the same native observer before the final task import so a
26969    /// context admission can bind its original task content. This read grants
26970    /// no use authority; final import must reproduce the same content exactly.
26971    pub fn observe_cold_task_content(
26972        &mut self,
26973        statement_records: [u32; 3],
26974        allowed_support_records: &[u32],
26975        program: &dyn SemanticTaskProgram,
26976    ) -> Result<(SemanticTaskContentIdentity, [crate::SemanticTruth; 3]), SemanticTransitionError>
26977    {
26978        self.ensure_rebindable()?;
26979        if self.publication.is_some() || self.task.is_some() || self.cold_content.is_some() {
26980            return Err(publication_input_error(
26981                "cold task content can be observed only once before final import",
26982            ));
26983        }
26984        let admission = self
26985            .graph
26986            .admission()
26987            .ok_or(SemanticTransitionError::NotBound)?;
26988        if program
26989            .editable_program()
26990            .map(ActionCodebooks::program_binding)
26991            != self.codebooks.program_binding
26992        {
26993            return Err(publication_input_error(
26994                "cold task observer differs from the admitted edit grammar",
26995            ));
26996        }
26997        let observation = program
26998            .observe(Arc::clone(&self.provider))
26999            .inspect_err(|_| self.poisoned = true)?;
27000        let content = TaskEvaluationBinding::cold_content(
27001            admission,
27002            statement_records,
27003            allowed_support_records,
27004            program.editable_program(),
27005            observation,
27006        )
27007        .inspect_err(|_| self.poisoned = true)?;
27008        self.cold_content = Some(content);
27009        Ok(content)
27010    }
27011
27012    /// Bind the controller's independently validated goal closure to the native
27013    /// task bank before any publication, capture, or model work may begin.
27014    pub fn bind_task_goal_witness(
27015        &mut self,
27016        witness: SemanticTaskGoalWitness,
27017    ) -> Result<Identity256, SemanticTransitionError> {
27018        self.ensure_rebindable()?;
27019        if self.publication.is_some() || self.captured.is_some() {
27020            return Err(publication_input_error(
27021                "goal authority is immutable after publication or capture",
27022            ));
27023        }
27024        if witness.mandatory_link_count == 0
27025            || witness.constraint_count == 0
27026            || witness
27027                .semantic_root
27028                .as_bytes()
27029                .iter()
27030                .all(|byte| *byte == 0)
27031            || witness
27032                .authority_root
27033                .as_bytes()
27034                .iter()
27035                .all(|byte| *byte == 0)
27036            || witness
27037                .mandatory_links_root
27038                .as_bytes()
27039                .iter()
27040                .all(|byte| *byte == 0)
27041            || witness
27042                .constraints_root
27043                .as_bytes()
27044                .iter()
27045                .all(|byte| *byte == 0)
27046        {
27047            return Err(publication_input_error(
27048                "goal authority requires nonempty independently validated roots and closures",
27049            ));
27050        }
27051        let next_epoch = self
27052            .task_epoch
27053            .checked_add(1)
27054            .ok_or(SemanticTransitionError::GenerationExhausted)?;
27055        let (binding, device) = self.task.as_mut().ok_or_else(|| {
27056            publication_input_error("goal authority requires a bound native task evaluation")
27057        })?;
27058        if binding.goal_witness.is_some() {
27059            return Err(publication_input_error(
27060                "goal authority can be bound only once",
27061            ));
27062        }
27063        binding.goal_witness = Some(witness);
27064        let identity = binding.identity();
27065        let words = binding.words(self.graph.transition_arena()[1]);
27066        self.provider
27067            .htod_sync_copy_into_tracked(&words, device)
27068            .map_err(|error| {
27069                self.poisoned = true;
27070                runtime_error("private goal-authority upload", error)
27071            })?;
27072        let mut recorder = self.domain.new_strict_recorder();
27073        recorder.read_write(device);
27074        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |_| {
27075            Ok::<(), XlogError>(())
27076        })?;
27077        wait_on_stream(
27078            &self.stream,
27079            &mut self.poisoned,
27080            &mut self.stream_waits,
27081            "private goal-authority adoption wait",
27082            CudaStream::synchronize,
27083        )?;
27084        self.validate_ranges()?;
27085        self.task_epoch = next_epoch;
27086        Ok(identity)
27087    }
27088
27089    /// Identity of the immutable task data bank, not a use-authority token.
27090    pub fn task_evaluation_identity(&self) -> Option<Identity256> {
27091        self.task.as_ref().map(|(binding, _)| binding.identity())
27092    }
27093
27094    /// Exact content identities and observed truths of the currently bound
27095    /// task, excluding its controller authority and scoring policy.
27096    pub fn task_content(&self) -> Option<(SemanticTaskContentIdentity, [crate::SemanticTruth; 3])> {
27097        self.task.as_ref().map(|(binding, _)| binding.content())
27098    }
27099
27100    /// Identity of the exact scoring law bound to the current native task.
27101    pub fn task_scoring_law_identity(
27102        &self,
27103    ) -> Result<Option<Identity256>, SemanticTransitionError> {
27104        Ok(self.task.as_ref().map(|(binding, _)| {
27105            checkpoint_scoring_law_identity(
27106                binding.spec.scoring,
27107                binding.content_identity(),
27108                binding.objective_law,
27109                binding.spec.training_domain.as_ref(),
27110            )
27111        }))
27112    }
27113
27114    /// The same cold law used by arena admission and checkpoint identity, with
27115    /// no selected denominators or actor-eligibility grant. No device read occurs.
27116    pub fn task_objective_law(&self) -> Option<SemanticTaskObjectiveLaw> {
27117        self.task.as_ref().map(|(binding, _)| binding.objective_law)
27118    }
27119
27120    /// Immutable pre-action input domain. No device read or use grant occurs.
27121    pub fn task_training_domain(&self) -> Option<&SemanticTrainingDomain> {
27122        self.task
27123            .as_ref()
27124            .and_then(|(binding, _)| binding.spec.training_domain.as_ref())
27125    }
27126
27127    /// Original pre-draw actor/full domains. Reading them grants no execution
27128    /// or training use. The consumer retains all capsules through final use;
27129    /// aliases must not be written while any original consumer remains live.
27130    #[cfg(feature = "semantic-policy")]
27131    pub fn policy_numerical_domains(
27132        &mut self,
27133        parent: &SemanticPublishedLease,
27134        consumer_stream: u64,
27135    ) -> Result<[DlpackManagedTensor; 3], SemanticTransitionError> {
27136        self.checked_reader(parent)?;
27137        dlpack_consumer_stream(consumer_stream)?;
27138        if self.captured.is_some() {
27139            return Err(publication_input_error(
27140                "uniform domains must precede policy capture",
27141            ));
27142        }
27143        let pending = self.pending_policy.as_ref().ok_or_else(|| {
27144            publication_input_error("uniform domains require the nine original policy snapshots")
27145        })?;
27146        if pending
27147            .witness
27148            .as_ref()
27149            .is_none_or(|(witness, _)| witness.reader_token != parent.token)
27150        {
27151            return Err(publication_input_error(
27152                "uniform domains belong to another acquired parent",
27153            ));
27154        }
27155        let publication = Arc::clone(
27156            self.publication
27157                .as_ref()
27158                .ok_or(SemanticTransitionError::NotBound)?,
27159        );
27160        let tensors = export_policy_uniform_domains(
27161            &pending.buffers,
27162            self.codebooks.input_cells,
27163            self.provider.device().ordinal() as i32,
27164            Arc::clone(&self.steps[&parent.token].aliases),
27165            publication,
27166        )?;
27167        self.steps
27168            .get_mut(&parent.token)
27169            .expect("checked original parent")
27170            .consumer_streams
27171            .insert(consumer_stream);
27172        self.order_content_consumers(consumer_stream)?;
27173        Ok(tensors)
27174    }
27175
27176    /// Same producer and formats on a genuine cold-prepared Proposal bank,
27177    /// before its model work is frozen and its continuation is submitted.
27178    #[cfg(feature = "semantic-policy")]
27179    pub fn prepared_policy_numerical_domains(
27180        &mut self,
27181        step: &SemanticPreparedStep,
27182        bank: usize,
27183        consumer_stream: u64,
27184    ) -> Result<[DlpackManagedTensor; 3], SemanticTransitionError> {
27185        self.check_prepared_content_stream(step, consumer_stream)?;
27186        if bank > 1 {
27187            return Err(publication_input_error(
27188                "prepared policy bank must be zero or one",
27189            ));
27190        }
27191        let original = &self.steps[&step.token];
27192        let prepared = original.prepared.as_ref().expect("checked prepared owner");
27193        if prepared.transition_recorded & (1 << bank) != 0 {
27194            return Err(publication_input_error(
27195                "uniform domains must precede policy submission",
27196            ));
27197        }
27198        let branch = &prepared.branches[bank];
27199        if branch.policy_sources.len() != 9 {
27200            return Err(publication_input_error(
27201                "uniform domains require the nine original policy snapshots",
27202            ));
27203        }
27204        let buffers = branch
27205            .policy_buffers
27206            .as_ref()
27207            .or_else(|| branch.policy.as_ref().map(|policy| &policy.buffers))
27208            .ok_or_else(|| publication_input_error("original uniform policy bank is absent"))?;
27209        let tensors = export_policy_uniform_domains(
27210            buffers,
27211            self.codebooks.input_cells,
27212            self.provider.device().ordinal() as i32,
27213            Arc::clone(&original.aliases),
27214            Arc::clone(
27215                self.publication
27216                    .as_ref()
27217                    .ok_or(SemanticTransitionError::NotBound)?,
27218            ),
27219        )?;
27220        self.steps
27221            .get_mut(&step.token)
27222            .expect("checked original step")
27223            .consumer_streams
27224            .insert(consumer_stream);
27225        self.order_content_consumers(consumer_stream)?;
27226        Ok(tensors)
27227    }
27228
27229    /// Semantic root of the validated goal witness bound to the current task.
27230    /// This is the same root retained in its completed task ground.
27231    pub fn task_semantic_goal_root(&self) -> Option<Identity256> {
27232        self.task
27233            .as_ref()
27234            .and_then(|(binding, _)| binding.goal_witness.map(|goal| goal.semantic_root))
27235    }
27236
27237    /// Ordered priority levels from the same immutable native task binding
27238    /// consumed by the device selector and later completed task ground.
27239    pub fn task_priority_levels(&self) -> Option<&[SemanticTaskPriorityLevel]> {
27240        self.task
27241            .as_ref()
27242            .map(|(binding, _)| binding.priority_levels())
27243    }
27244
27245    /// Bind every admitted training view once while the task is still cold.
27246    /// No row is selected here and the arena cannot be replaced after binding.
27247    pub fn bind_training_view_arena(
27248        &mut self,
27249        rows: Vec<SemanticTrainingViewRow>,
27250        objective: SemanticTrainingObjective,
27251    ) -> Result<(), SemanticTransitionError> {
27252        self.ensure_rebindable()?;
27253        if self.publication.is_some() || self.training_views.is_some() || self.task.is_none() {
27254            return Err(publication_input_error(
27255                "training-view arena requires one cold task binding and cannot be replaced",
27256            ));
27257        }
27258        self.task_objective_law()
27259            .expect("checked cold task binding")
27260            .require_objective(&objective)?;
27261        let task_identity = self
27262            .task
27263            .as_ref()
27264            .expect("checked cold task binding")
27265            .0
27266            .identity();
27267        let (task_content, expected_truth) = self
27268            .task
27269            .as_ref()
27270            .expect("checked cold task binding")
27271            .0
27272            .content();
27273        self.training_views = Some(SemanticTrainingViewArena::allocate(
27274            &self.provider,
27275            &self.domain,
27276            rows,
27277            objective,
27278            self.task_training_domain().ok_or_else(|| {
27279                publication_input_error(
27280                    "training arena requires its original pre-action input domain",
27281                )
27282            })?,
27283            task_identity,
27284            task_content,
27285            expected_truth,
27286        )?);
27287        Ok(())
27288    }
27289
27290    /// Exact original admission selections in task query order, not inferred
27291    /// from canonical statement values. Support order and duplicates are kept
27292    /// as supplied to the validated binding. These indices grant no use rights.
27293    pub fn task_evaluation_spec(
27294        &self,
27295    ) -> Result<&SemanticTaskEvaluationSpec, SemanticTransitionError> {
27296        self.ensure_quiescent()?;
27297        let (task, _) = self
27298            .task
27299            .as_ref()
27300            .ok_or(SemanticTransitionError::NotBound)?;
27301        Ok(task.spec())
27302    }
27303
27304    /// Native learned-value projection for the three fixed queries, in query order.
27305    /// Each payload is a length-delimited canonical predicate/arity/argument
27306    /// byte sequence followed by the ordered, length-delimited qualifier values.
27307    /// Encoding-domain and schema-digest service headers are excluded. The
27308    /// original qualified key identity remains separately bound to the task.
27309    /// These schema bytes contain no observer answers or use authority.
27310    pub fn feedback_statement_bytes(&self) -> Result<[&[u8]; 3], SemanticTransitionError> {
27311        let selected = self.task_evaluation_spec()?.statement_records;
27312        let (task, _) = self
27313            .task
27314            .as_ref()
27315            .ok_or(SemanticTransitionError::NotBound)?;
27316        Ok(selected.map(|record| task.statement_bytes[&record].as_slice()))
27317    }
27318
27319    /// Identity of this build's actual native feedback projection source, not
27320    /// any statement value, task identity, observer answer or authority decision.
27321    pub fn feedback_adapter_identity() -> Identity256 {
27322        let mut hash = Sha256::new();
27323        hash.update(b"xlog.native.flat-feedback-adapter.v1\0");
27324        hash.update(include_bytes!("semantic_transition.rs"));
27325        hash.update(include_bytes!("../kernels/semantic_transition.cu"));
27326        hash.update(include_bytes!("../kernels/semantic_feedback_encoding.cuh"));
27327        Identity256::from_bytes(hash.finalize().into())
27328    }
27329
27330    /// Changes on every successful task import, even when data bytes are identical.
27331    pub fn task_evaluation_epoch(&self) -> u64 {
27332        self.task_epoch
27333    }
27334
27335    pub fn binding(&self) -> SemanticCatalogueBinding {
27336        self.codebooks.binding
27337    }
27338    pub fn components(&self) -> &[SemanticComponent] {
27339        &self.codebooks.components
27340    }
27341    pub fn descriptor_meaning(
27342        &self,
27343        field: u32,
27344        category: u32,
27345    ) -> Option<&SemanticActionDescriptor> {
27346        let entries = match field {
27347            2 => &self.codebooks.targets,
27348            3..=10 => &self.codebooks.operands,
27349            11 => &self.codebooks.qualifiers,
27350            17 => &self.codebooks.leaves,
27351            _ => return None,
27352        };
27353        entries.get(category.checked_sub(1)? as usize)
27354    }
27355
27356    pub fn host_io_stats(&self) -> SemanticTransitionHostIoStats {
27357        let io = self.provider.host_transfer_stats();
27358        let metadata = self.provider.host_launch_metadata_transfer_stats();
27359        let observation = self.provider.final_observation_transfer_stats();
27360        SemanticTransitionHostIoStats {
27361            htod_bytes: io.htod_bytes,
27362            dtoh_bytes: io.dtoh_bytes,
27363            htod_calls: io.htod_calls,
27364            dtoh_calls: io.dtoh_calls,
27365            launch_metadata_bytes: metadata.htod_bytes,
27366            launch_metadata_calls: metadata.htod_calls,
27367            metadata_dtoh_calls: self.provider.untracked_metadata_dtoh_count(),
27368            observation_bytes: observation.dtoh_bytes,
27369            observation_calls: observation.dtoh_calls,
27370            session_stream_waits: self.stream_waits,
27371        }
27372    }
27373
27374    pub fn root_snapshot(&mut self) -> Result<SemanticRootSnapshot, SemanticTransitionError> {
27375        self.ensure_quiescent()?;
27376        Ok(self.base_snapshot)
27377    }
27378
27379    /// Validates the entire binding before touching resident state. The cold owner
27380    /// supplies a globally unique stream namespace and the acquired proposal. This
27381    /// is reconstruction of pending state, not publication or advancement of the
27382    /// canonical RNG. Rebinding after observation keeps the captured addresses.
27383    pub fn bind_inputs(
27384        &mut self,
27385        binding: SemanticCatalogueBinding,
27386        rng: SemanticRngBinding,
27387        inputs: &[SemanticComponentInput],
27388    ) -> Result<(), SemanticTransitionError> {
27389        self.ensure_rebindable()?;
27390        if binding != self.binding() {
27391            return Err(SemanticTransitionError::CatalogueMismatch);
27392        }
27393        validate_bound_inputs(&self.codebooks.components, rng, inputs)?;
27394        self.validate_ranges()?;
27395        let logits: Vec<f32> = inputs
27396            .iter()
27397            .flat_map(|r| r.logits.iter().copied())
27398            .collect();
27399        let support: Vec<u8> = inputs
27400            .iter()
27401            .flat_map(|r| r.product_support.iter().copied())
27402            .collect();
27403        #[cfg(feature = "semantic-policy")]
27404        if self.pending_policy.is_some() {
27405            return Err(publication_input_error(
27406                "original policy snapshots cannot be replaced by raw inputs",
27407            ));
27408        }
27409        #[cfg(feature = "semantic-policy")]
27410        if self.policy.is_some() {
27411            self.captured = None;
27412            self.policy = None;
27413        }
27414        // The provider's synchronous uploader uses its setup stream. Complete it
27415        // before adopting allocations onto the distinct resident execution stream.
27416        let upload = (|| {
27417            self.provider
27418                .htod_sync_copy_into_tracked(&logits, &mut self.logits)?;
27419            self.provider
27420                .htod_sync_copy_into_tracked(&support, &mut self.support)?;
27421            Ok::<(), XlogError>(())
27422        })();
27423        upload.map_err(|e| {
27424            self.poisoned = true;
27425            runtime_error("input upload", e)
27426        })?;
27427        self.upload_rng_state(binding, rng)?;
27428        let mut recorder = self.domain.new_strict_recorder();
27429        recorder.read_write(&self.logits);
27430        recorder.read_write(&self.support);
27431        recorder.read_write(&self.state);
27432        recorder.write(&self.scratch);
27433        recorder.write(&self.receipts);
27434        recorder.read(&self.device_codebooks);
27435        recorder.read(&self.device_components);
27436        // SAFETY: completed setup copies precede this ownership adoption. No work
27437        // escapes the supplied stream, and no output payload is initialized here.
27438        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |_| {
27439            Ok::<(), XlogError>(())
27440        })?;
27441        self.stream_waits += 1;
27442        self.stream.synchronize().map_err(|e| {
27443            self.poisoned = true;
27444            runtime_error("input adoption wait", e)
27445        })?;
27446        self.rng = Some(rng);
27447        self.next_proposal = u64::from(rng.proposal);
27448        Ok(())
27449    }
27450
27451    /// Takes independent device snapshots of the exact proposal's model inputs.
27452    /// Text logits retain all 32 rows of the original MASK matrix;
27453    /// both lanes read the same original row. Structural scores are
27454    /// produced by the pinned numerical policy inside the component loop.
27455    ///
27456    /// Parameters use `policy_layout()`. Source allocations must be tracked in
27457    /// this execution domain; the recorder joins their producer streams before
27458    /// copying. No caller-owned parameter buffer is used by subsequent replay.
27459    /// The five original FP64 arrays, in order, are parameter/baseline
27460    /// ordinary-underflow envelopes followed by parameter/text/baseline
27461    /// magnitude-ordinary-underflow-independent-ideal domains. They share the
27462    /// same snapshot; pointwise E is not replaced by domain O/U.
27463    /// The original cold task supplies the law for pre-draw uniform domains;
27464    /// an absent prospective training domain has no admissible training groups.
27465    #[cfg(feature = "semantic-policy")]
27466    #[expect(
27467        clippy::too_many_arguments,
27468        reason = "all nine original policy operands share one snapshot"
27469    )]
27470    pub fn bind_policy(
27471        &mut self,
27472        binding: SemanticCatalogueBinding,
27473        rng: SemanticRngBinding,
27474        text_logits: &TrackedCudaSlice<f32>,
27475        product_support: &TrackedCudaSlice<u8>,
27476        parameters: &TrackedCudaSlice<f32>,
27477        component_baselines: &TrackedCudaSlice<f32>,
27478        numerical: [&TrackedCudaSlice<f64>; 5],
27479    ) -> Result<(), SemanticTransitionError> {
27480        self.bind_policy_views(
27481            binding,
27482            rng,
27483            text_logits.view(),
27484            product_support.view(),
27485            parameters.view(),
27486            component_baselines.view(),
27487            numerical.map(TrackedCudaSlice::view),
27488            None,
27489        )
27490    }
27491
27492    /// Import genuine DLPack owners and snapshot one proposal's policy inputs.
27493    ///
27494    /// All tensors are contiguous CUDA storage on this session's device:
27495    /// F32 `[32, text_cardinality()]`, Bool8 `[policy_support_layout().1]`,
27496    /// F32 `[policy_layout().parameter_cells]`, and FP32 `[1, 136]` component
27497    /// baselines, followed by FP64 envelopes `[P,2]`, `[1,136,2]` and FP64
27498    /// domains `[P,4]`, `[32,V,4]`, `[1,136,4]` in `(M,O,U,I)` order, where P
27499    /// is the parameter extent and V is the text vocabulary. Pointwise E is
27500    /// distinct from domain O/U; I is independently derived on the ideal
27501    /// formula, never M+O+U. One original content witness
27502    /// authenticates all nine operands in that order. The snapshots may precede
27503    /// continuation binding; capture remains unavailable until both stages join.
27504    /// Both lanes share the original
27505    /// mapped MASK rows; unused capacity is not a categorical factor.
27506    /// Support contains only active TEXT and the structural rows in roster order;
27507    /// inactive TEXT has no address. The roster itself still has 136 factors.
27508    ///
27509    /// The canonical importer joins the explicit original consumer stream and
27510    /// checks the acquired parent's witness before the recorded device-to-device
27511    /// snapshot. No tensor value is read or reconstructed on the host.
27512    /// The caller must meet `DlpackManagedTensor::from_raw`'s producer-readiness
27513    /// and external-access contract; these handles confer no task/use authority.
27514    /// Original model/autograd owners remain the caller's separate responsibility.
27515    #[cfg(feature = "semantic-policy")]
27516    #[expect(
27517        clippy::too_many_arguments,
27518        reason = "the complete original witness and operand owners are explicit"
27519    )]
27520    pub fn bind_policy_dlpack(
27521        &mut self,
27522        lease: &SemanticPublishedLease,
27523        binding: SemanticCatalogueBinding,
27524        rng: SemanticRngBinding,
27525        text_logits: DlpackManagedTensor,
27526        product_support: DlpackManagedTensor,
27527        parameters: DlpackManagedTensor,
27528        component_baselines: DlpackManagedTensor,
27529        numerical: [DlpackManagedTensor; 5],
27530        witness: &SemanticTensorContentWitness,
27531        consumer_stream: u64,
27532    ) -> Result<(), SemanticTransitionError> {
27533        // Own all actual producers before the first fallible binding/shape check.
27534        // A failed handoff retains the entire set through canonical retirement.
27535        let mut handoff = RetainedTensorAdmission {
27536            inputs: Some(
27537                vec![
27538                    text_logits,
27539                    product_support,
27540                    parameters,
27541                    component_baselines,
27542                ]
27543                .into_iter()
27544                .chain(numerical)
27545                .collect(),
27546            ),
27547            stream: Arc::clone(self.provider.device().inner().stream()),
27548            ready: false,
27549        };
27550        self.ensure_rebindable()?;
27551        self.checked_reader(lease)?;
27552        self.checked_content_witness(lease, witness)?;
27553        if rng != self.admitted_policy_rng(lease)? {
27554            return Err(publication_input_error(
27555                "policy invocation differs from its actual acquired parent",
27556            ));
27557        }
27558        if binding != self.binding() {
27559            return Err(SemanticTransitionError::CatalogueMismatch);
27560        }
27561        if rng.stream_serial >= (1u64 << 56) {
27562            return Err(SemanticTransitionError::InvalidInput {
27563                detail: "policy stream namespace does not match the native catalogue".into(),
27564            });
27565        }
27566        let layout = self.policy_layout()?;
27567        let layouts =
27568            policy_numerical_producer_layouts(self.codebooks.input_cells, layout.parameter_cells)?;
27569        // Preserve the actual rank-two MASK matrix and each producer owner.
27570        // The typed importer validates original metadata; no column adapter,
27571        // compacted rows or replacement managed tensor is manufactured.
27572        let inputs = handoff
27573            .inputs
27574            .take()
27575            .expect("retained policy producers")
27576            .into_iter()
27577            .zip(layouts)
27578            .map(|(tensor, layout)| SemanticTensorInput {
27579                layout,
27580                logical_begin: 0,
27581                logical_end: 0,
27582                tensor,
27583                native_allocation: None,
27584            })
27585            .collect();
27586        self.verify_tensor_content(lease, witness, inputs, consumer_stream)?;
27587        let original =
27588            policy_source_views(&self.steps[&lease.token].content[witness.index].tensors)?;
27589        self.bind_policy_views(
27590            binding,
27591            rng,
27592            original.text_logits,
27593            original.product_support,
27594            original.parameters,
27595            original.component_baselines,
27596            original.numerical,
27597            Some((witness.clone(), consumer_stream)),
27598        )
27599    }
27600
27601    #[cfg(feature = "semantic-policy")]
27602    fn allocate_policy_buffers(&self) -> Result<PolicyBuffers, SemanticTransitionError> {
27603        let layout = self.policy_layout()?;
27604        let mut reservation = self
27605            .provider
27606            .memory()
27607            .reserve_bytes(policy_buffer_bytes(&layout, self.codebooks.input_cells)? as u64)
27608            .map_err(|error| runtime_error("policy reservation", error))?;
27609        self.allocate_policy_buffers_reserved(&mut reservation)
27610    }
27611
27612    #[cfg(feature = "semantic-policy")]
27613    fn allocate_policy_buffers_reserved(
27614        &self,
27615        reservation: &mut GpuMemoryReservation,
27616    ) -> Result<PolicyBuffers, SemanticTransitionError> {
27617        let layout = self.policy_layout()?;
27618        let law = self.task_objective_law().ok_or_else(|| {
27619            publication_input_error("uniform policy domains require the original cold task law")
27620        })?;
27621        let text_cells = 32 * TEXT_CARDINALITY;
27622        let pwl_cells = reservation
27623            .alloc::<SemanticPolicyPwlCell>(COMPONENT_COUNT)
27624            .map_err(|error| runtime_error("retained PWL cell allocation", error))?;
27625        let selected_score_vjps = reservation
27626            .alloc::<SemanticPolicySelectedScoreVjp>(COMPONENT_COUNT)
27627            .map_err(|error| runtime_error("retained selected-score VJP allocation", error))?;
27628        let mut allocate_adjoints = || {
27629            let mut allocate_numerical = |cells: usize| {
27630                reservation
27631                    .alloc::<f64>(cells)
27632                    .map_err(|error| runtime_error("policy adjoint numerical allocation", error))
27633            };
27634            let numerical = Arc::new(PolicyAdjointNumerical {
27635                roots: [
27636                    allocate_numerical(
27637                        layout
27638                            .parameter_cells
27639                            .checked_mul(2)
27640                            .ok_or(SemanticTransitionError::GenerationExhausted)?,
27641                    )?,
27642                    allocate_numerical(text_cells * 2)?,
27643                    allocate_numerical(COMPONENT_COUNT * 2)?,
27644                    allocate_numerical(
27645                        layout
27646                            .parameter_cells
27647                            .checked_mul(8)
27648                            .ok_or(SemanticTransitionError::GenerationExhausted)?,
27649                    )?,
27650                    allocate_numerical(text_cells * 8)?,
27651                    allocate_numerical(COMPONENT_COUNT * 8)?,
27652                ],
27653                recurrent_errors: allocate_numerical(layout.recurrent_cells() * 8)?,
27654                score_errors: allocate_numerical(layout.score_cells() * 8)?,
27655                coefficient_errors: allocate_numerical(COMPONENT_COUNT * 8)?,
27656                root_cotangents: [
27657                    allocate_numerical(
27658                        layout
27659                            .parameter_cells
27660                            .checked_mul(8)
27661                            .ok_or(SemanticTransitionError::GenerationExhausted)?,
27662                    )?,
27663                    allocate_numerical(text_cells * 8)?,
27664                    allocate_numerical(COMPONENT_COUNT * 8)?,
27665                ],
27666            });
27667            Ok::<_, SemanticTransitionError>(PolicyAdjointBuffers {
27668                numerical,
27669                parameters: reservation
27670                    .alloc::<f32>(layout.parameter_cells)
27671                    .map_err(|error| runtime_error("parameter adjoint allocation", error))?,
27672                text_logits: reservation
27673                    .alloc::<f32>(text_cells)
27674                    .map_err(|error| runtime_error("text adjoint allocation", error))?,
27675                component_baselines: reservation
27676                    .alloc::<f32>(COMPONENT_COUNT)
27677                    .map_err(|error| runtime_error("baseline adjoint allocation", error))?,
27678                recurrent: reservation
27679                    .alloc::<f32>(layout.recurrent_cells())
27680                    .map_err(|error| runtime_error("recurrent adjoint allocation", error))?,
27681                scores: reservation
27682                    .alloc::<f32>(layout.score_cells())
27683                    .map_err(|error| runtime_error("score adjoint allocation", error))?,
27684                coefficients: reservation
27685                    .alloc::<f64>(COMPONENT_COUNT)
27686                    .map_err(|error| runtime_error("cotangent snapshot allocation", error))?,
27687                status: reservation
27688                    .alloc::<u64>(1)
27689                    .map_err(|error| runtime_error("policy backward status allocation", error))?,
27690            })
27691        };
27692        let adjoints = allocate_adjoints()?;
27693        let temporal_adjoints = Arc::new(allocate_adjoints()?);
27694        let mut allocate_uniform = |cells: usize| {
27695            reservation
27696                .alloc::<f64>(cells)
27697                .map_err(|error| runtime_error("uniform policy domain allocation", error))
27698        };
27699        let root_cells = [layout.parameter_cells, text_cells, COMPONENT_COUNT];
27700        let mut roots = Vec::with_capacity(3);
27701        let mut outputs = Vec::with_capacity(3);
27702        for cells in root_cells {
27703            let cells = cells
27704                .checked_mul(8)
27705                .ok_or(SemanticTransitionError::GenerationExhausted)?;
27706            outputs.push(allocate_uniform(cells)?);
27707        }
27708        for cells in [layout.parameter_cells, TEXT_CARDINALITY, COMPONENT_COUNT] {
27709            roots.push(allocate_uniform(
27710                cells
27711                    .checked_mul(8)
27712                    .ok_or(SemanticTransitionError::GenerationExhausted)?,
27713            )?);
27714        }
27715        let roots: [_; 3] = roots
27716            .try_into()
27717            .unwrap_or_else(|_| unreachable!("three policy roots"));
27718        let outputs: [_; 3] = outputs
27719            .try_into()
27720            .unwrap_or_else(|_| unreachable!("three policy outputs"));
27721        let scratch = [
27722            allocate_uniform(layout.recurrent_cells() * 4)?,
27723            allocate_uniform(128 * 4)?,
27724            allocate_uniform(layout.score_cells() * 4)?,
27725            allocate_uniform(layout.recurrent_cells() * 8)?,
27726            allocate_uniform(layout.score_cells() * 8)?,
27727            allocate_uniform(COMPONENT_COUNT * 8)?,
27728        ];
27729        let status = reservation
27730            .alloc::<u64>(1)
27731            .map_err(|error| runtime_error("uniform policy status allocation", error))?;
27732        let work = reservation
27733            .alloc::<u64>(11)
27734            .map_err(|error| runtime_error("uniform policy work allocation", error))?;
27735        let descriptor = reservation
27736            .alloc::<PolicyUniformDescriptor>(1)
27737            .map_err(|error| runtime_error("uniform policy descriptor allocation", error))?;
27738        let initial_descriptor = PolicyUniformDescriptor {
27739            outputs: outputs.each_ref().map(TrackedCudaSlice::device_ptr_value),
27740            roots: roots.each_ref().map(TrackedCudaSlice::device_ptr_value),
27741            recurrent: scratch[0].device_ptr_value(),
27742            hidden: scratch[1].device_ptr_value(),
27743            scores: scratch[2].device_ptr_value(),
27744            recurrent_cotangents: scratch[3].device_ptr_value(),
27745            score_cotangents: scratch[4].device_ptr_value(),
27746            score_roots: scratch[5].device_ptr_value(),
27747            status: status.device_ptr_value(),
27748            work: work.device_ptr_value(),
27749            training_rows: self
27750                .task_training_domain()
27751                .map_or(0, SemanticTrainingDomain::record_limit),
27752            return_bound: law.return_bound as u64,
27753            loss_coefficients: [3, 6, 7, 8].map(|index| f64::from(law.coefficients[index])),
27754        };
27755        let uniform = Arc::new(PolicyUniformBuffers {
27756            descriptor,
27757            initial_descriptor,
27758            roots,
27759            outputs,
27760            scratch,
27761            status,
27762            work,
27763            execute: self
27764                .provider
27765                .device()
27766                .inner()
27767                .get_func(
27768                    "xlog_semantic_transition",
27769                    "semantic_policy_uniform_domains",
27770                )
27771                .ok_or_else(|| {
27772                    runtime_error("kernel lookup", "uniform policy domains unavailable")
27773                })?,
27774        });
27775        let mut allocate_numerical = |cells: usize| {
27776            reservation
27777                .alloc::<f64>(cells)
27778                .map_err(|error| runtime_error("policy numerical allocation", error))
27779        };
27780        let numerical = PolicyNumericalBuffers {
27781            uniform,
27782            parameter_errors: allocate_numerical(
27783                layout
27784                    .parameter_cells
27785                    .checked_mul(2)
27786                    .ok_or(SemanticTransitionError::GenerationExhausted)?,
27787            )?,
27788            baseline_errors: allocate_numerical(COMPONENT_COUNT * 2)?,
27789            parameter_domains: allocate_numerical(
27790                layout
27791                    .parameter_cells
27792                    .checked_mul(4)
27793                    .ok_or(SemanticTransitionError::GenerationExhausted)?,
27794            )?,
27795            text_domains: allocate_numerical(text_cells * 4)?,
27796            baseline_domains: allocate_numerical(COMPONENT_COUNT * 4)?,
27797            hidden_errors: allocate_numerical(128 * 3)?,
27798            score_errors: allocate_numerical(layout.score_cells() * 3)?,
27799            recurrent_errors: allocate_numerical(layout.recurrent_cells() * 3)?,
27800            parameter_envelopes: allocate_numerical(
27801                layout
27802                    .parameter_cells
27803                    .checked_mul(3)
27804                    .ok_or(SemanticTransitionError::GenerationExhausted)?,
27805            )?,
27806            baseline_envelopes: allocate_numerical(COMPONENT_COUNT * 3)?,
27807        };
27808        Ok(PolicyBuffers {
27809            numerical,
27810            parameters: reservation
27811                .alloc::<f32>(layout.parameter_cells)
27812                .map_err(|error| runtime_error("policy parameter allocation", error))?,
27813            hidden: reservation
27814                .alloc::<f32>(128)
27815                .map_err(|error| runtime_error("policy hidden allocation", error))?,
27816            scores: reservation
27817                .alloc::<f32>(layout.score_cells())
27818                .map_err(|error| runtime_error("policy score allocation", error))?,
27819            retained_scores: reservation
27820                .alloc::<f32>(layout.retained_score_cells())
27821                .map_err(|error| runtime_error("retained policy score allocation", error))?,
27822            final_masks: reservation
27823                .alloc::<u8>(self.codebooks.input_cells)
27824                .map_err(|error| runtime_error("retained final mask allocation", error))?,
27825            active_sets: reservation
27826                .alloc::<u8>(self.codebooks.input_cells)
27827                .map_err(|error| runtime_error("retained active set allocation", error))?,
27828            pwl_cells,
27829            selected_score_vjps,
27830            recurrent: reservation
27831                .alloc::<f32>(layout.recurrent_cells())
27832                .map_err(|error| runtime_error("policy recurrent allocation", error))?,
27833            text_logits: reservation
27834                .alloc::<f32>(text_cells)
27835                .map_err(|error| runtime_error("original text snapshot allocation", error))?,
27836            component_baselines: reservation
27837                .alloc::<f32>(COMPONENT_COUNT)
27838                .map_err(|error| runtime_error("component baseline snapshot allocation", error))?,
27839            adjoints: Some(adjoints),
27840            temporal_adjoints,
27841            layout,
27842        })
27843    }
27844
27845    #[cfg(feature = "semantic-policy")]
27846    fn prepare_step_policy_storage(
27847        &self,
27848        reservation: &mut GpuMemoryReservation,
27849    ) -> Result<PreparedPolicyStorage, SemanticTransitionError> {
27850        let buffers = self.allocate_policy_buffers_reserved(reservation)?;
27851        let support = reservation
27852            .alloc(self.codebooks.input_cells)
27853            .map_err(|error| runtime_error("prepared support allocation", error))?;
27854        let receipts = reservation
27855            .alloc(COMPONENT_COUNT)
27856            .map_err(|error| runtime_error("prepared receipt allocation", error))?;
27857        let state = reservation
27858            .alloc(1)
27859            .map_err(|error| runtime_error("prepared state allocation", error))?;
27860        Ok((buffers, support, receipts, state))
27861    }
27862
27863    /// Retain and snapshot the original policy producers in their already
27864    /// reserved native branch. The snapshots are available before continuation
27865    /// binding on the same bank execution retains. Neither binding creates a
27866    /// draw; execution requires both original owners.
27867    #[cfg(feature = "semantic-policy")]
27868    #[expect(
27869        clippy::too_many_arguments,
27870        reason = "prepared policy binding retains each typed producer and witness explicitly"
27871    )]
27872    pub fn bind_prepared_policy(
27873        &mut self,
27874        step: &SemanticPreparedStep,
27875        bank: usize,
27876        binding: SemanticCatalogueBinding,
27877        text_logits: DlpackManagedTensor,
27878        product_support: DlpackManagedTensor,
27879        parameters: DlpackManagedTensor,
27880        component_baselines: DlpackManagedTensor,
27881        numerical: [DlpackManagedTensor; 5],
27882        witness: &SemanticTensorContentWitness,
27883        consumer_stream: u64,
27884    ) -> Result<(), SemanticTransitionError> {
27885        self.check_prepared_content_stream(step, consumer_stream)?;
27886        if bank > 1 {
27887            return Err(publication_input_error(
27888                "prepared policy bank must be zero or one",
27889            ));
27890        }
27891        if self.prepared_transition_kind(step)? != SemanticTransitionKind::Proposal {
27892            return Err(publication_input_error(
27893                "only a proposal step binds a learned policy",
27894            ));
27895        }
27896        if binding != self.binding() {
27897            return Err(SemanticTransitionError::CatalogueMismatch);
27898        }
27899        let layouts = policy_numerical_producer_layouts(
27900            self.codebooks.input_cells,
27901            self.policy_layout()?.parameter_cells,
27902        )?;
27903        let tensors = [
27904            text_logits,
27905            product_support,
27906            parameters,
27907            component_baselines,
27908        ]
27909        .into_iter()
27910        .chain(numerical)
27911        .zip(layouts)
27912        .map(|(tensor, layout)| SemanticTensorInput {
27913            layout,
27914            logical_begin: 0,
27915            logical_end: 0,
27916            tensor,
27917            native_allocation: None,
27918        })
27919        .collect();
27920        self.verify_prepared_tensor_content(step, witness, tensors, consumer_stream)?;
27921        let sources = self.steps[&step.token].content[witness.index]
27922            .tensors
27923            .clone();
27924        let owner = self
27925            .steps
27926            .get_mut(&step.token)
27927            .expect("checked original step");
27928        let prepared = owner.prepared.as_mut().expect("prepared policy owner");
27929        let branch = &mut prepared.branches[bank];
27930        if branch.policy.is_some() || !branch.policy_sources.is_empty() {
27931            return Err(publication_input_error(
27932                "prepared policy already owns its original invocation",
27933            ));
27934        }
27935        if branch.policy_buffers.is_none() {
27936            return Err(publication_input_error(
27937                "prepared policy has no unused cold allocation",
27938            ));
27939        }
27940        branch.policy_sources = sources;
27941        branch.policy_witness = Some(witness.clone());
27942        let sources = policy_source_views(&branch.policy_sources)?;
27943        enqueue_policy_snapshots(
27944            &self.domain,
27945            &mut self.poisoned,
27946            branch
27947                .policy_buffers
27948                .as_ref()
27949                .expect("checked original cold policy bank"),
27950            branch.support.as_ref().expect("original support bank"),
27951            &sources,
27952        )?;
27953        enqueue_policy_uniform_domains(
27954            &self.domain,
27955            &mut self.poisoned,
27956            branch
27957                .policy_buffers
27958                .as_ref()
27959                .expect("original policy domain bank"),
27960            &self.device_components,
27961            branch.support.as_ref().expect("original support bank"),
27962        )?;
27963        self.attach_prepared_policy_continuation(step, bank)
27964    }
27965
27966    /// Join two independently admitted stages without allocating or replacing
27967    /// either original producer. Before the join, sources and cold banks remain
27968    /// owned by the branch and cannot be executed as a policy tape.
27969    #[cfg(feature = "semantic-policy")]
27970    fn attach_prepared_policy_continuation(
27971        &mut self,
27972        step: &SemanticPreparedStep,
27973        bank: usize,
27974    ) -> Result<(), SemanticTransitionError> {
27975        let branch = &mut self
27976            .steps
27977            .get_mut(&step.token)
27978            .expect("checked original step")
27979            .prepared
27980            .as_mut()
27981            .expect("prepared policy owner")
27982            .branches[bank];
27983        if branch.policy.is_some() || branch.policy_sources.is_empty() {
27984            return Ok(());
27985        }
27986        let Some(continuation) = branch.continuation.as_ref() else {
27987            return Ok(());
27988        };
27989        let text_binding = Arc::clone(&continuation.text_binding);
27990        if text_binding._witness.reader_token != step.token {
27991            return Err(publication_input_error(
27992                "prepared policy and continuation belong to different original steps",
27993            ));
27994        }
27995        let buffers = branch.policy_buffers.take().ok_or_else(|| {
27996            publication_input_error("prepared policy has no unused cold allocation")
27997        })?;
27998        branch.policy = Some(PolicyStorage {
27999            buffers,
28000            text_binding,
28001            _policy_witness: branch.policy_witness.clone(),
28002            replacement: None,
28003            tape_live: false,
28004            temporal_vjp_recorded: BTreeSet::new(),
28005        });
28006        Ok(())
28007    }
28008
28009    /// Consume the original numerical body through the canonical policy,
28010    /// resolver and publication kernel, with this step's distinct late tape.
28011    #[cfg(feature = "semantic-policy")]
28012    pub fn enqueue_prepared_transition(
28013        &mut self,
28014        step: &SemanticPreparedStep,
28015        bank: usize,
28016    ) -> Result<(), SemanticTransitionError> {
28017        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
28018        if bank > 1 {
28019            return Err(publication_input_error(
28020                "prepared transition bank must be zero or one",
28021            ));
28022        }
28023        let kind = self.prepared_transition_kind(step)?;
28024        let finish = self
28025            .steps
28026            .get_mut(&step.token)
28027            .expect("checked original step")
28028            .prepared
28029            .as_mut()
28030            .expect("prepared owner")
28031            .model_work
28032            .as_mut()
28033            .ok_or_else(|| {
28034                publication_input_error("prepared transition requires original model work")
28035            })
28036            .and_then(|work| work.finish_capture(bank).map_err(publication_input_error));
28037        if let Err(error) = finish {
28038            self.poisoned = true;
28039            return Err(error);
28040        }
28041        let owner = &self.steps[&step.token];
28042        let prepared = owner.prepared.as_ref().expect("prepared transition owner");
28043        let branch = &prepared.branches[bank];
28044        if prepared.transition_recorded & (1 << bank) != 0
28045            || prepared.model_content_recorded & (1 << bank) == 0
28046            || branch.continuation.is_none()
28047            || (kind == SemanticTransitionKind::Proposal && branch.policy.is_none())
28048            || (kind != SemanticTransitionKind::Proposal && branch.policy.is_some())
28049            || (kind == SemanticTransitionKind::Update
28050                && branch
28051                    .model_update
28052                    .as_ref()
28053                    .is_none_or(|update| update.output.is_none()))
28054        {
28055            return Err(publication_input_error("prepared transition requires recorded branch model content, its unused original continuation, a policy only for proposals, and a bound model output for updates"));
28056        }
28057        let policy_witness = if kind == SemanticTransitionKind::Proposal {
28058            Some(branch.policy_witness.clone().ok_or_else(|| {
28059                publication_input_error("prepared transition has no original policy content")
28060            })?)
28061        } else {
28062            None
28063        };
28064        let continuation_witness = branch
28065            .continuation
28066            .as_ref()
28067            .expect("checked continuation")
28068            .text_binding
28069            ._witness
28070            .clone();
28071        if let Some(witness) = &policy_witness {
28072            self.record_prepared_tensor_content(step, witness, true)?;
28073        }
28074        self.record_prepared_tensor_content(step, &continuation_witness, true)?;
28075        let result = (|| {
28076            let prepared = self.steps[&step.token]
28077                .prepared
28078                .as_ref()
28079                .expect("retained original step");
28080            let branch = &prepared.branches[bank];
28081            branch
28082                .continuation
28083                .as_ref()
28084                .expect("checked original continuation")
28085                .enqueue(&self.domain, &mut self.poisoned)?;
28086            if let Some(update) = &branch.model_update {
28087                let training_view = prepared.training_view.as_ref().ok_or_else(|| {
28088                    publication_input_error("prepared update has no native training view")
28089                })?;
28090                update.enqueue_copy(
28091                    &self.domain,
28092                    &mut self.poisoned,
28093                    self.publication.as_ref().expect("prepared publication"),
28094                    &prepared.reader,
28095                    training_view,
28096                    &self.task.as_ref().expect("prepared task binding").1,
28097                    prepared
28098                        .model_work
28099                        .as_ref()
28100                        .expect("prepared model work frozen above"),
28101                )?;
28102            }
28103            let io = self.prepared_kernel_io(step, bank)?;
28104            self.validate_ranges_with(&io)?;
28105            let descriptor = self.descriptor_with(&io);
28106            let recorder = self.kernel_recorder_with(&io);
28107            let execute = self.execute.clone();
28108            enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
28109                // SAFETY: the same selected original buffers define both the
28110                // kernel arguments and every retained recorder allocation.
28111                unsafe {
28112                    execute.launch_in(
28113                        enqueue,
28114                        LaunchConfig {
28115                            grid_dim: (1, 1, 1),
28116                            block_dim: (256, 1, 1),
28117                            shared_mem_bytes: 0,
28118                        },
28119                        (descriptor,),
28120                    )
28121                }
28122                .map_err(|error| XlogError::Kernel(error.to_string()))
28123            })
28124        })();
28125        if result.is_err() {
28126            self.poisoned = true;
28127            return result;
28128        }
28129        let prepared = self
28130            .steps
28131            .get_mut(&step.token)
28132            .expect("retained original step")
28133            .prepared
28134            .as_mut()
28135            .expect("retained original prepared step");
28136        prepared.transition_recorded |= 1 << bank;
28137        Ok(())
28138    }
28139
28140    /// Record the device-selected terminal drain without executing the model,
28141    /// continuation producer, optimizer, or training-output path.
28142    #[cfg(feature = "semantic-policy")]
28143    pub fn enqueue_prepared_drain(
28144        &mut self,
28145        step: &SemanticPreparedStep,
28146    ) -> Result<(), SemanticTransitionError> {
28147        self.check_prepared_content_stream(step, self.stream.cu_stream() as u64)?;
28148        let prepared = self.steps[&step.token]
28149            .prepared
28150            .as_ref()
28151            .expect("prepared drain owner");
28152        if prepared.transition_recorded != PREPARED_TRANSITION_BANKS || prepared.drain_recorded {
28153            return Err(publication_input_error(
28154                "prepared drain requires its recorded requested branch and unused drain branch",
28155            ));
28156        }
28157        let publication = self.publication.as_ref().expect("prepared publication");
28158        let mut recorder = self.domain.new_strict_recorder();
28159        publication.record(&mut recorder);
28160        recorder.read(&prepared.reader);
28161        let arguments = (
28162            publication.control.device_ptr_value(),
28163            prepared.reader.device_ptr_value(),
28164        );
28165        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
28166            // SAFETY: the device-selected drain uses the same acquired lease and
28167            // publication owner as the following canonical transition kernel.
28168            unsafe {
28169                prepared.drain_prepare.clone().launch_in(
28170                    enqueue,
28171                    LaunchConfig {
28172                        grid_dim: (1, 1, 1),
28173                        block_dim: (1, 1, 1),
28174                        shared_mem_bytes: 0,
28175                    },
28176                    arguments,
28177                )
28178            }
28179            .map_err(|error| XlogError::Kernel(error.to_string()))
28180        })?;
28181        let io = self.prepared_drain_kernel_io(step)?;
28182        self.validate_ranges_with(&io)?;
28183        let descriptor = self.descriptor_with(&io);
28184        let recorder = self.kernel_recorder_with(&io);
28185        let execute = self.execute.clone();
28186        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
28187            // SAFETY: the drain descriptor retains the canonical publication,
28188            // task, graph arena, result, and lease owners but no model outputs.
28189            unsafe {
28190                execute.launch_in(
28191                    enqueue,
28192                    LaunchConfig {
28193                        grid_dim: (1, 1, 1),
28194                        block_dim: (256, 1, 1),
28195                        shared_mem_bytes: 0,
28196                    },
28197                    (descriptor,),
28198                )
28199            }
28200            .map_err(|error| XlogError::Kernel(error.to_string()))
28201        })?;
28202        self.steps
28203            .get_mut(&step.token)
28204            .expect("prepared drain owner")
28205            .prepared
28206            .as_mut()
28207            .expect("prepared drain storage")
28208            .drain_recorded = true;
28209        Ok(())
28210    }
28211
28212    /// Move an actually observed proposal's original banks into late backward
28213    /// ownership. The caller supplies coordinates from its saved native header.
28214    #[cfg(feature = "semantic-policy")]
28215    fn take_prepared_policy_tape(
28216        &mut self,
28217        step: &SemanticPreparedStep,
28218        bank: usize,
28219        invocation: SemanticRngBinding,
28220        refusal: Option<SemanticTransitionRefusal>,
28221    ) -> Result<(), SemanticTransitionError> {
28222        if !Arc::ptr_eq(&step.issuer, &self.publication_issuer)
28223            || self
28224                .policy_tapes
28225                .iter()
28226                .any(|tape| tape.invocation == invocation)
28227        {
28228            return Err(publication_input_error(
28229                "observed prepared policy differs from its original Session or invocation",
28230            ));
28231        }
28232        let binding = self.binding();
28233        let prepared = self
28234            .steps
28235            .get_mut(&step.token)
28236            .and_then(|owner| owner.prepared.as_mut())
28237            .ok_or_else(|| {
28238                publication_input_error("observed prepared policy has no retained original step")
28239            })?;
28240        let transition_recorded = prepared.transition_recorded;
28241        let branch = prepared
28242            .branches
28243            .get_mut(bank)
28244            .ok_or(SemanticTransitionError::ObservationMismatch)?;
28245        if transition_recorded != PREPARED_TRANSITION_BANKS
28246            || branch.policy.is_none()
28247            || branch.support.is_none()
28248            || branch.receipts.is_none()
28249        {
28250            return Err(publication_input_error(
28251                "observed prepared policy was not recorded or has already retired",
28252            ));
28253        }
28254        // A captured nominal proposal may be skipped or forced to drain. Only
28255        // actual proposal completion creates this original backward obligation.
28256        branch
28257            .policy
28258            .as_mut()
28259            .expect("checked original policy")
28260            .tape_live = true;
28261        self.policy_tapes.push(PolicyTape {
28262            invocation,
28263            refusal,
28264            binding,
28265            policy: branch.policy.take().expect("checked original policy"),
28266            support: branch.support.take().expect("checked original support"),
28267            receipts: branch.receipts.take().expect("checked original receipts"),
28268            prepared_bank: Some(bank),
28269            origin_state: None,
28270            components: self.device_components.view(),
28271            codebooks: self.device_codebooks.view(),
28272        });
28273        Ok(())
28274    }
28275
28276    #[cfg(feature = "semantic-policy")]
28277    #[expect(
28278        clippy::too_many_arguments,
28279        reason = "one original policy snapshot carries all values and numerical owners"
28280    )]
28281    fn bind_policy_views(
28282        &mut self,
28283        binding: SemanticCatalogueBinding,
28284        rng: SemanticRngBinding,
28285        text_logits: DeviceMemoryView<f32>,
28286        product_support: DeviceMemoryView<u8>,
28287        parameters: DeviceMemoryView<f32>,
28288        component_baselines: DeviceMemoryView<f32>,
28289        numerical: [DeviceMemoryView<f64>; 5],
28290        policy_witness: Option<(SemanticTensorContentWitness, u64)>,
28291    ) -> Result<(), SemanticTransitionError> {
28292        self.ensure_rebindable()?;
28293        if binding != self.binding() {
28294            return Err(SemanticTransitionError::CatalogueMismatch);
28295        }
28296        let layout = self.policy_layout()?;
28297        if self.pending_policy.is_some() {
28298            return Err(publication_input_error(
28299                "policy already owns its original snapshots",
28300            ));
28301        }
28302        match (self.text_binding.as_ref(), policy_witness.as_ref()) {
28303            (Some(binding), _) if self.continuation_base.is_some() => {
28304                if rng != binding.published_parent()?.1.rng_binding()? {
28305                    return Err(publication_input_error(
28306                        "policy invocation differs from its actual acquired parent",
28307                    ));
28308                }
28309            }
28310            (None, Some((witness, _)))
28311                if self.admitted_transition.is_some_and(|(token, _, kind)| {
28312                    token == witness.reader_token && kind == SemanticTransitionKind::Proposal
28313                }) => {}
28314            _ => {
28315                return Err(publication_input_error(
28316                    "policy snapshots require their original parent witness or continuation",
28317                ));
28318            }
28319        }
28320        let text_cells = 32 * TEXT_CARDINALITY;
28321        let support_cells = self.codebooks.input_cells;
28322        if self
28323            .admitted_transition
28324            .is_none_or(|(_, _, kind)| kind != SemanticTransitionKind::Proposal)
28325            || self.policy_tapes.iter().any(|tape| tape.invocation == rng)
28326        {
28327            return Err(publication_input_error(
28328                "policy binding requires a fresh admitted proposal invocation",
28329            ));
28330        }
28331        if rng.stream_serial >= (1u64 << 56)
28332            || text_logits.len() != text_cells
28333            || product_support.len() != support_cells
28334            || parameters.len() != layout.parameter_cells
28335            || component_baselines.len() != COMPONENT_COUNT
28336        {
28337            return Err(SemanticTransitionError::InvalidInput {
28338                detail:
28339                    "policy input shape or stream namespace does not match the native catalogue"
28340                        .into(),
28341            });
28342        }
28343        let policy = PendingPolicyStorage {
28344            witness: policy_witness,
28345            // Reserve the next working banks before the proposal may publish.
28346            // Successful observation moves, rather than overwrites, all exact
28347            // original buffers into its late tape without fallible allocation.
28348            replacement: PolicyReplacement {
28349                support: allocate_publication(&self.provider, self.codebooks.input_cells)?,
28350                receipts: allocate_publication(&self.provider, COMPONENT_COUNT)?,
28351                state: allocate_publication(&self.provider, 1)?,
28352            },
28353            buffers: self.allocate_policy_buffers()?,
28354            invocation: rng,
28355        };
28356        // Changing captured pointer arguments invalidates the old executable.
28357        // All previous work is quiescent and no unconsumed tape can reach here.
28358        self.captured = None;
28359        self.rng = None;
28360        self.pending_policy = Some(policy);
28361        let policy = self
28362            .pending_policy
28363            .as_ref()
28364            .expect("policy storage installed above");
28365        enqueue_policy_snapshots(
28366            &self.domain,
28367            &mut self.poisoned,
28368            &policy.buffers,
28369            &self.support,
28370            &PolicyProducerViews {
28371                text_logits,
28372                product_support,
28373                parameters,
28374                component_baselines,
28375                numerical,
28376            },
28377        )?;
28378        enqueue_policy_uniform_domains(
28379            &self.domain,
28380            &mut self.poisoned,
28381            &policy.buffers,
28382            &self.device_components,
28383            &self.support,
28384        )?;
28385        let consumer_stream = policy.witness.as_ref().map(|(_, stream)| *stream);
28386        if let Some(stream) = consumer_stream {
28387            if let Err(error) = self.order_content_consumers(stream) {
28388                self.poisoned = true;
28389                return Err(error);
28390            }
28391        }
28392        self.attach_policy_continuation()
28393    }
28394
28395    #[cfg(feature = "semantic-policy")]
28396    fn attach_policy_continuation(&mut self) -> Result<(), SemanticTransitionError> {
28397        let Some(snapshot) = self.pending_policy.as_ref() else {
28398            return Ok(());
28399        };
28400        let Some(original) = self
28401            .text_binding
28402            .as_ref()
28403            .filter(|_| self.continuation_base.is_some())
28404            .map(Arc::clone)
28405        else {
28406            return Ok(());
28407        };
28408        let rng = snapshot.invocation;
28409        if rng != original.published_parent()?.1.rng_binding()?
28410            || snapshot
28411                .witness
28412                .as_ref()
28413                .is_some_and(|(witness, _)| witness.reader_token != original._witness.reader_token)
28414        {
28415            return Err(publication_input_error(
28416                "policy snapshots and continuation belong to different original parents",
28417            ));
28418        }
28419        // Callback-owned originals may have changed since the early snapshot.
28420        // Recheck their original seal without overwriting any snapshot bytes.
28421        let witness = snapshot.witness.clone();
28422        if let Some((witness, stream)) = &witness {
28423            self.enqueue_content_witness(witness, *stream, true)?;
28424        }
28425        self.guard_continuation_content(&original)?;
28426        let snapshot = self
28427            .pending_policy
28428            .take()
28429            .expect("checked original policy snapshots");
28430        self.policy = Some(PolicyStorage {
28431            buffers: snapshot.buffers,
28432            replacement: Some(snapshot.replacement),
28433            _policy_witness: witness.map(|(witness, _)| witness),
28434            text_binding: Arc::clone(&original),
28435            tape_live: false,
28436            temporal_vjp_recorded: BTreeSet::new(),
28437        });
28438        self.validate_ranges()?;
28439        if let Err(error) = self.order_content_consumers(original.consumer_stream) {
28440            self.poisoned = true;
28441            return Err(error);
28442        }
28443        self.rng = Some(rng);
28444        self.next_proposal = u64::from(rng.proposal);
28445        Ok(())
28446    }
28447
28448    /// Differentiates the selected scores after successful observation. The
28449    /// caller supplies one FP64 scalar cotangent per original component;
28450    /// advantages and importance weights are not recomputed or differentiated
28451    /// here. The owned FP64 snapshot stays at that precision until the selected
28452    /// logit adjoints enter the existing FP32 model backward.
28453    ///
28454    /// This is a terminal device operation, not another transition: forward
28455    /// receipts, recurrent values, semantic state and RNG are only read. The
28456    /// original tape's preallocated outputs cannot be overwritten by a later
28457    /// proposal; backward neither reserves nor allocates device memory.
28458    #[cfg(feature = "semantic-policy")]
28459    pub fn backward_policy(
28460        &mut self,
28461        invocation: SemanticRngBinding,
28462        score_cotangents: &TrackedCudaSlice<f64>,
28463    ) -> Result<SemanticPolicyGradients, SemanticTransitionError> {
28464        self.backward_policy_view(invocation, score_cotangents.view(), 1)
28465    }
28466
28467    /// Consume the actual original loss's 136 FP64 selected-score cotangents.
28468    /// The DLPack producer is joined before validation and retained on failures;
28469    /// no Python-selected scores or replacement autograd leaf are introduced.
28470    #[cfg(feature = "semantic-policy")]
28471    pub fn backward_policy_dlpack(
28472        &mut self,
28473        invocation: SemanticRngBinding,
28474        score_cotangents: DlpackManagedTensor,
28475        consumer_stream: u64,
28476    ) -> Result<SemanticPolicyGradients, SemanticTransitionError> {
28477        let mut handoff = RetainedTensorAdmission {
28478            inputs: Some(vec![score_cotangents]),
28479            stream: Arc::clone(self.provider.device().inner().stream()),
28480            ready: false,
28481        };
28482        dlpack_consumer_stream(consumer_stream)?;
28483        let pointer = handoff
28484            .inputs
28485            .as_ref()
28486            .expect("retained cotangent producer")[0]
28487            .as_ptr();
28488        if pointer.is_null() {
28489            return Err(publication_input_error(
28490                "selected-score cotangent managed owner is null",
28491            ));
28492        }
28493        // SAFETY: the genuine managed owner retains the original descriptor and
28494        // shape/stride arrays throughout this metadata-only admission.
28495        let (data, bytes) = unsafe {
28496            policy_score_cotangent_metadata(
28497                &(*pointer).dl_tensor,
28498                self.provider.device().ordinal() as i32,
28499            )
28500        }?;
28501        handoff.ready = true;
28502        let tensor = handoff
28503            .inputs
28504            .take()
28505            .expect("retained cotangent producer")
28506            .pop()
28507            .expect("one cotangent");
28508        // SAFETY: canonical metadata validates the exact original span. The
28509        // column transfers, rather than replaces, its retained producer owner.
28510        let bytes = unsafe { CudaColumn::dlpack(data, bytes, Arc::clone(&handoff.stream), tensor) }
28511            .device_view();
28512        // SAFETY: original metadata proves the full contiguous F64 roster.
28513        // The continuation guard orders producer events before its device use.
28514        let values = unsafe { bytes.cast::<f64>() }.ok_or_else(|| {
28515            publication_input_error("selected-score cotangent span is not aligned F64 storage")
28516        })?;
28517        self.backward_policy_view(invocation, values, consumer_stream)
28518    }
28519
28520    #[cfg(feature = "semantic-policy")]
28521    fn checked_prepared_policy_tape(
28522        &self,
28523        step: &SemanticPreparedStep,
28524        invocation: SemanticRngBinding,
28525    ) -> Result<usize, SemanticTransitionError> {
28526        let owner = self.checked_prepared_step(step, false)?;
28527        if !self
28528            .prepared_segment
28529            .as_ref()
28530            .is_some_and(|build| build.completed)
28531            || !owner
28532                .prepared
28533                .as_ref()
28534                .is_some_and(|prepared| prepared.observed)
28535        {
28536            return Err(publication_input_error(
28537                "prepared policy requires its actual completed native outcome",
28538            ));
28539        }
28540        self.policy_tapes
28541            .iter()
28542            .position(|tape| {
28543                tape.invocation == invocation
28544                    && tape.policy.text_binding._witness.reader_token == step.token
28545            })
28546            .ok_or_else(|| {
28547                publication_input_error(
28548                    "prepared policy has no unconsumed original tape for this step",
28549                )
28550            })
28551    }
28552
28553    /// Completion moves the executed policy out of branch storage into its
28554    /// original tape. Cold observations must follow that same one-use owner.
28555    #[cfg(feature = "semantic-policy")]
28556    fn completed_prepared_policy_tape(
28557        &mut self,
28558        step: &SemanticPreparedStep,
28559    ) -> Result<usize, SemanticTransitionError> {
28560        let header_view = self
28561            .checked_prepared_step(step, false)?
28562            .inputs
28563            .as_ref()
28564            .ok_or(SemanticTransitionError::ObservationMismatch)?
28565            .header
28566            .view();
28567        let parent = self.publication_read(header_view)?[0];
28568        let index = self.checked_prepared_policy_tape(step, parent.rng_binding()?)?;
28569        let tape = &self.policy_tapes[index];
28570        // Publication banks select recorded branches. Model-weight banks
28571        // advance only on Update and are not the original branch selector.
28572        if tape.prepared_bank != Some((parent.publication_word & 1) as usize)
28573            || tape.refusal.is_some()
28574        {
28575            return Err(SemanticTransitionError::ObservationMismatch);
28576        }
28577        Ok(index)
28578    }
28579
28580    /// Authenticate the actual completed step and its unconsumed original tape
28581    /// before a binding exposes this invocation to its numerical producer.
28582    #[cfg(feature = "semantic-policy")]
28583    pub fn require_prepared_policy_invocation(
28584        &self,
28585        step: &SemanticPreparedStep,
28586        invocation: SemanticRngBinding,
28587    ) -> Result<usize, SemanticTransitionError> {
28588        let index = self.checked_prepared_policy_tape(step, invocation)?;
28589        self.policy_tapes[index]
28590            .prepared_bank
28591            .ok_or(SemanticTransitionError::ObservationMismatch)
28592    }
28593
28594    /// Differentiate the original tape of this actually completed native step.
28595    #[cfg(feature = "semantic-policy")]
28596    pub fn backward_prepared_policy_dlpack(
28597        &mut self,
28598        step: &SemanticPreparedStep,
28599        invocation: SemanticRngBinding,
28600        score_cotangents: DlpackManagedTensor,
28601        consumer_stream: u64,
28602    ) -> Result<SemanticPolicyGradients, SemanticTransitionError> {
28603        self.checked_prepared_policy_tape(step, invocation)?;
28604        self.backward_policy_dlpack(invocation, score_cotangents, consumer_stream)
28605    }
28606
28607    /// Differentiate one original prepared proposal from the Update step's
28608    /// resident actor/critic/cost objective. Call this once for every proposal
28609    /// invocation in the frozen segment. The kernel compares the proposal's
28610    /// schedule ordinal to the selected origin candidate, so all unselected
28611    /// invocations return graph-connected zero adjoints without host readback.
28612    #[cfg(feature = "semantic-policy")]
28613    pub fn backward_selected_prepared_policy(
28614        &mut self,
28615        step: &SemanticPreparedStep,
28616        update_step: &SemanticPreparedStep,
28617        invocation: SemanticRngBinding,
28618        consumer_stream: u64,
28619    ) -> Result<SemanticSelectedPolicyGradients, SemanticTransitionError> {
28620        self.ensure_quiescent()?;
28621        dlpack_consumer_stream(consumer_stream)?;
28622        let tape_index = self.checked_prepared_policy_tape(step, invocation)?;
28623        if let Some(refusal) = self.policy_tapes[tape_index].refusal {
28624            return Err(refusal.into_error());
28625        }
28626        let update_owner = self.checked_prepared_step(update_step, false)?;
28627        let build = self
28628            .prepared_segment
28629            .as_ref()
28630            .expect("checked prepared segment");
28631        if !build.completed
28632            || !update_owner
28633                .prepared
28634                .as_ref()
28635                .is_some_and(|prepared| prepared.observed)
28636        {
28637            return Err(publication_input_error(
28638                "selected policy backward requires the actual completed Update step",
28639            ));
28640        }
28641        if build.requested_kind(update_step, &self.publication_issuer)?
28642            != SemanticTransitionKind::Update
28643        {
28644            return Err(publication_input_error(
28645                "selected policy backward requires a prepared Update step",
28646            ));
28647        }
28648        let origin_candidate = build
28649            .tokens
28650            .iter()
28651            .position(|token| *token == step.token)
28652            .ok_or(SemanticTransitionError::ObservationMismatch)?;
28653        let update_ordinal = build
28654            .tokens
28655            .iter()
28656            .position(|token| *token == update_step.token)
28657            .ok_or(SemanticTransitionError::ObservationMismatch)?;
28658        if origin_candidate >= update_ordinal {
28659            return Err(publication_input_error(
28660                "selected policy backward requires a preceding proposal candidate",
28661            ));
28662        }
28663        let origin_candidate = u64::try_from(origin_candidate)
28664            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
28665        let original = Arc::clone(&self.policy_tapes[tape_index].policy.text_binding);
28666        self.guard_continuation_content(&original)?;
28667        if let Err(error) =
28668            self.order_step_content_inputs(original._witness.reader_token, consumer_stream)
28669        {
28670            self.poisoned = true;
28671            return Err(error);
28672        }
28673        let publication = Arc::clone(
28674            self.publication
28675                .as_ref()
28676                .ok_or(SemanticTransitionError::NotBound)?,
28677        );
28678        let step_aliases = Arc::clone(&self.steps[&original._witness.reader_token].aliases);
28679        let tape = &self.policy_tapes[tape_index];
28680        let policy = &tape.policy;
28681        let state = tape.prepared_bank.map_or(&self.state, |bank| {
28682            &self.steps[&original._witness.reader_token]
28683                .prepared
28684                .as_ref()
28685                .expect("checked prepared policy owner")
28686                .branches[bank]
28687                .state
28688        });
28689        let training = self.steps[&update_step.token]
28690            .prepared
28691            .as_ref()
28692            .expect("checked prepared Update owner")
28693            .training_view
28694            .as_ref()
28695            .ok_or_else(|| {
28696                publication_input_error(
28697                    "selected policy backward requires the Update training-view owner",
28698                )
28699            })?;
28700        let origin_bank = tape.prepared_bank.ok_or_else(|| {
28701            publication_input_error("selected policy backward requires a prepared policy bank")
28702        })?;
28703        let origin_lease = &self.steps[&original._witness.reader_token]
28704            .prepared
28705            .as_ref()
28706            .expect("checked prepared policy owner")
28707            .reader;
28708        let PolicyVjpRecording {
28709            descriptor,
28710            recorder,
28711        } = self.prepare_policy_vjp_recording(
28712            policy,
28713            policy.buffers.adjoints.as_ref().ok_or_else(|| {
28714                publication_input_error("original policy adjoint banks have already been consumed")
28715            })?,
28716            &tape.support,
28717            &tape.receipts,
28718            state,
28719            &tape.components,
28720            &tape.codebooks,
28721            PolicyVjpInput::UpdateObjective {
28722                training,
28723                origin_candidate,
28724                origin_lease,
28725                origin_bank,
28726            },
28727        )?;
28728        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
28729            .map_err(|error| runtime_error("selected policy backward stream admission", error))?;
28730        let execute = self.execute.clone();
28731        let layout = policy.layout.clone();
28732        let binding = tape.binding;
28733        let support_cells = tape.support.len();
28734        let baseline_snapshot = policy.component_baselines.view();
28735        let PolicyAdjointBuffers {
28736            parameters,
28737            text_logits,
28738            component_baselines,
28739            recurrent,
28740            scores,
28741            coefficients,
28742            status,
28743            numerical,
28744        } = self.policy_tapes[tape_index]
28745            .policy
28746            .buffers
28747            .adjoints
28748            .take()
28749            .expect("checked original adjoint banks");
28750        let vjp_workspace = Arc::new(PolicyVjpWorkspace {
28751            _numerical: Arc::clone(&numerical),
28752            _component_baselines: None,
28753            _recurrent: recurrent,
28754            _scores: scores,
28755            coefficients,
28756            _status: status,
28757            score_cotangents: None,
28758        });
28759        let output_views = [&parameters, &text_logits, &component_baselines]
28760            .into_iter()
28761            .map(|buffer| {
28762                // SAFETY: F32 storage has an exact, aligned byte representation.
28763                unsafe { buffer.view().cast::<u8>() }.expect("F32 adjoint byte view")
28764            });
28765        let step_owner = self
28766            .steps
28767            .get_mut(&original._witness.reader_token)
28768            .expect("retained original step");
28769        step_owner.adjoints.extend(output_views);
28770        step_owner
28771            .policy_vjp_workspaces
28772            .push(Arc::clone(&vjp_workspace));
28773        record_policy_vjp(
28774            &self.domain,
28775            &mut self.poisoned,
28776            recorder,
28777            execute,
28778            descriptor,
28779            &vjp_workspace.coefficients,
28780            None,
28781            Some(&baseline_snapshot),
28782        )?;
28783        if let Err(error) = self.order_content_consumers(consumer_stream) {
28784            self.poisoned = true;
28785            return Err(error);
28786        }
28787        self.policy_tapes.remove(tape_index);
28788        Ok(SemanticSelectedPolicyGradients {
28789            numerical,
28790            binding,
28791            invocation,
28792            layout,
28793            parameters,
28794            text_logits,
28795            component_baselines,
28796            provider: Arc::clone(&self.provider),
28797            step_aliases,
28798            publication,
28799            continuation: original,
28800            vjp_workspace,
28801            support_cells,
28802        })
28803    }
28804
28805    #[cfg(feature = "semantic-policy")]
28806    /// Record one original proposal tape's complete policy contribution to the
28807    /// Update objective. Actor/critic/cost and supervised-edit coefficients
28808    /// are combined only when their authenticated rows name this exact tape.
28809    pub fn record_prepared_update_policy_vjp(
28810        &mut self,
28811        step: &SemanticPreparedStep,
28812        bank: usize,
28813        update_step: &SemanticPreparedStep,
28814        consumer_stream: u64,
28815    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
28816        self.record_prepared_policy_vjp(step, bank, update_step, None, false, consumer_stream)
28817    }
28818
28819    /// Record the original prepared Proposal named by one exact frozen actor
28820    /// row. Unlike the single-selected compatibility path this contributes to
28821    /// the complete group and reserves its critic reduction slot.
28822    #[cfg(feature = "semantic-policy")]
28823    pub fn record_prepared_group_member_policy_vjp(
28824        &mut self,
28825        step: &SemanticPreparedStep,
28826        bank: usize,
28827        update_step: &SemanticPreparedStep,
28828        member_ordinal: u64,
28829        member_row: &SemanticTrainingViewRow,
28830        consumer_stream: u64,
28831    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
28832        self.record_prepared_policy_vjp(
28833            step,
28834            bank,
28835            update_step,
28836            Some((member_ordinal, member_row)),
28837            false,
28838            consumer_stream,
28839        )
28840    }
28841
28842    /// Route a frozen row by native objective-group membership, never by a
28843    /// caller's duplicate actor/edit classification.
28844    #[cfg(feature = "semantic-policy")]
28845    pub fn record_prepared_policy_group_vjp(
28846        &mut self,
28847        step: &SemanticPreparedStep,
28848        bank: usize,
28849        update_step: &SemanticPreparedStep,
28850        member_ordinal: u64,
28851        member_row: &SemanticTrainingViewRow,
28852        consumer_stream: u64,
28853    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
28854        let actor_member = self
28855            .steps
28856            .get(&update_step.token)
28857            .and_then(|step| step.prepared.as_ref())
28858            .and_then(|step| step.training_view.as_ref())
28859            .ok_or_else(|| publication_input_error("Update has no selected training view"))?
28860            .actor_group_members()
28861            .iter()
28862            .any(|member| member.ordinal == member_ordinal);
28863        if actor_member {
28864            self.record_prepared_group_member_policy_vjp(
28865                step,
28866                bank,
28867                update_step,
28868                member_ordinal,
28869                member_row,
28870                consumer_stream,
28871            )
28872        } else {
28873            self.record_prepared_edit_member_policy_vjp(
28874                step,
28875                bank,
28876                update_step,
28877                member_ordinal,
28878                member_row,
28879                consumer_stream,
28880            )
28881        }
28882    }
28883
28884    /// Record one genuine supervised-edit row outside the actor group. Actor,
28885    /// critic and cost terms cannot be smuggled through this edit-only path.
28886    #[cfg(feature = "semantic-policy")]
28887    pub fn record_prepared_edit_member_policy_vjp(
28888        &mut self,
28889        step: &SemanticPreparedStep,
28890        bank: usize,
28891        update_step: &SemanticPreparedStep,
28892        member_ordinal: u64,
28893        member_row: &SemanticTrainingViewRow,
28894        consumer_stream: u64,
28895    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
28896        self.record_prepared_policy_vjp(
28897            step,
28898            bank,
28899            update_step,
28900            Some((member_ordinal, member_row)),
28901            true,
28902            consumer_stream,
28903        )
28904    }
28905
28906    #[cfg(feature = "semantic-policy")]
28907    fn record_prepared_policy_vjp(
28908        &mut self,
28909        step: &SemanticPreparedStep,
28910        bank: usize,
28911        update_step: &SemanticPreparedStep,
28912        member: Option<(u64, &SemanticTrainingViewRow)>,
28913        edit_only: bool,
28914        consumer_stream: u64,
28915    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
28916        dlpack_consumer_stream(consumer_stream)?;
28917        self.check_prepared_content_stream(update_step, consumer_stream)?;
28918        if bank > 1 {
28919            return Err(publication_input_error(
28920                "temporal policy backward requires proposal bank zero or one",
28921            ));
28922        }
28923        let build = self
28924            .prepared_segment
28925            .as_ref()
28926            .ok_or_else(|| publication_input_error("no prepared segment is being recorded"))?;
28927        if build.completed
28928            || build.requested_kind(step, &self.publication_issuer)?
28929                != SemanticTransitionKind::Proposal
28930            || build.requested_kind(update_step, &self.publication_issuer)?
28931                != SemanticTransitionKind::Update
28932        {
28933            return Err(publication_input_error(
28934                "temporal policy backward requires a preceding Proposal and the recording Update",
28935            ));
28936        }
28937        let origin_candidate = build
28938            .tokens
28939            .iter()
28940            .position(|token| *token == step.token)
28941            .ok_or(SemanticTransitionError::ObservationMismatch)?;
28942        let update_ordinal = build
28943            .tokens
28944            .iter()
28945            .position(|token| *token == update_step.token)
28946            .ok_or(SemanticTransitionError::ObservationMismatch)?;
28947        if origin_candidate >= update_ordinal {
28948            return Err(publication_input_error(
28949                "temporal policy backward requires a preceding proposal candidate",
28950            ));
28951        }
28952        let origin_candidate = u64::try_from(origin_candidate)
28953            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
28954        let update = self.steps[&update_step.token]
28955            .prepared
28956            .as_ref()
28957            .expect("checked prepared Update owner");
28958        let update_capture_bank = update
28959            .model_work
28960            .as_ref()
28961            .and_then(|work| work.capture_bank)
28962            .ok_or_else(|| {
28963                publication_input_error(
28964                    "temporal policy backward requires an active Update bank capture",
28965                )
28966            })?;
28967        if update_capture_bank > 1 {
28968            return Err(publication_input_error(
28969                "temporal policy backward has an invalid Update capture bank",
28970            ));
28971        }
28972        let training = update.training_view.as_ref().ok_or_else(|| {
28973            publication_input_error("prepared Update has no selected training-view owner")
28974        })?;
28975        let member_index = if edit_only {
28976            None
28977        } else {
28978            member
28979                .map(|(ordinal, row)| training.actor_group_member_index(ordinal, row))
28980                .transpose()?
28981        };
28982        let edit_member = member
28983            .map(|(ordinal, row)| training.edit_group_member_index(ordinal, row))
28984            .transpose()?
28985            .flatten()
28986            .is_some();
28987        if let Some((ordinal, _)) = member {
28988            if edit_only
28989                && (!edit_member
28990                    || training
28991                        .actor_group_members()
28992                        .iter()
28993                        .any(|row| row.ordinal == ordinal))
28994            {
28995                return Err(publication_input_error(
28996                    "edit-only VJP requires a frozen edit row outside the actor group",
28997                ));
28998            }
28999            if update.group_critic_recorded & (1 << update_capture_bank) != 0
29000                || (edit_only && update.group_edit_members[update_capture_bank].contains(&ordinal))
29001                || (!edit_only && update.group_vjp_members[update_capture_bank].contains(&ordinal))
29002            {
29003                return Err(publication_input_error(
29004                    "prepared actor group member already contributed to this Update bank",
29005                ));
29006            }
29007        }
29008        let critic_term = member_index.map(|index| training.critic_term(index));
29009        let proposal = self.steps[&step.token]
29010            .prepared
29011            .as_ref()
29012            .expect("checked prepared Proposal owner");
29013        if proposal.transition_recorded & (1 << bank) == 0 {
29014            return Err(publication_input_error(
29015                "temporal policy backward requires the recorded original Proposal branch",
29016            ));
29017        }
29018        let branch = &proposal.branches[bank];
29019        let policy = branch.policy.as_ref().ok_or_else(|| {
29020            publication_input_error("prepared Proposal bank has no bound policy tape")
29021        })?;
29022        let update_capture = (update_step.token, update_capture_bank);
29023        if policy.temporal_vjp_recorded.contains(&update_capture) {
29024            return Err(publication_input_error(
29025                "prepared Proposal bank already recorded this Update capture's policy VJP",
29026            ));
29027        }
29028        let support = branch.support.as_ref().ok_or_else(|| {
29029            publication_input_error("prepared Proposal bank has no policy support")
29030        })?;
29031        let receipts = branch.receipts.as_ref().ok_or_else(|| {
29032            publication_input_error("prepared Proposal bank has no policy receipts")
29033        })?;
29034        let components = self.device_components.view();
29035        let codebooks = self.device_codebooks.view();
29036        let owner = Arc::clone(&policy.buffers.temporal_adjoints);
29037        let PolicyVjpRecording {
29038            descriptor,
29039            recorder,
29040        } = self.prepare_policy_vjp_recording(
29041            policy,
29042            &owner,
29043            support,
29044            receipts,
29045            &branch.state,
29046            &components,
29047            &codebooks,
29048            if let (Some((member_ordinal, _)), true) = (member, edit_only) {
29049                PolicyVjpInput::EditMember {
29050                    training,
29051                    member_ordinal,
29052                    origin_candidate,
29053                    origin_lease: &proposal.reader,
29054                    origin_bank: bank,
29055                }
29056            } else if let (Some((member_ordinal, _)), Some(critic_term)) = (member, &critic_term) {
29057                PolicyVjpInput::GroupMember {
29058                    training,
29059                    member_ordinal,
29060                    origin_candidate,
29061                    origin_lease: &proposal.reader,
29062                    origin_bank: bank,
29063                    critic_term,
29064                }
29065            } else {
29066                PolicyVjpInput::UpdateObjective {
29067                    training,
29068                    origin_candidate,
29069                    origin_lease: &proposal.reader,
29070                    origin_bank: bank,
29071                }
29072            },
29073        )?;
29074        let baseline_snapshot = policy.component_baselines.view();
29075        let layout = policy.layout.clone();
29076        let continuation = Arc::clone(&policy.text_binding);
29077        let support_cells = support.len();
29078        let parameters = owner.parameters.view();
29079        let text_logits = owner.text_logits.view();
29080        let component_baselines = owner.component_baselines.view();
29081        let step_aliases = Arc::clone(&self.steps[&step.token].aliases);
29082        let publication = Arc::clone(
29083            self.publication
29084                .as_ref()
29085                .ok_or(SemanticTransitionError::NotBound)?,
29086        );
29087        record_policy_vjp(
29088            &self.domain,
29089            &mut self.poisoned,
29090            recorder,
29091            self.execute.clone(),
29092            descriptor,
29093            &owner.coefficients,
29094            None,
29095            Some(&baseline_snapshot),
29096        )?;
29097        self.steps
29098            .get_mut(&step.token)
29099            .expect("checked prepared Proposal owner")
29100            .prepared
29101            .as_mut()
29102            .expect("checked prepared Proposal")
29103            .branches[bank]
29104            .policy
29105            .as_mut()
29106            .expect("checked prepared policy tape")
29107            .temporal_vjp_recorded
29108            .insert(update_capture);
29109        if let Some((member_ordinal, _)) = member {
29110            let update = self
29111                .steps
29112                .get_mut(&update_step.token)
29113                .expect("checked prepared Update owner")
29114                .prepared
29115                .as_mut()
29116                .expect("checked prepared Update");
29117            if !edit_only {
29118                update.group_vjp_members[update_capture_bank].insert(member_ordinal);
29119            }
29120            if edit_member {
29121                update.group_edit_members[update_capture_bank].insert(member_ordinal);
29122            }
29123        }
29124        Ok(SemanticPreparedPolicyGradients {
29125            layout,
29126            parameters,
29127            text_logits,
29128            component_baselines,
29129            provider: Arc::clone(&self.provider),
29130            step_aliases,
29131            publication,
29132            continuation,
29133            owner,
29134            support_cells,
29135        })
29136    }
29137
29138    /// Close one captured Update bank only after every frozen actor-group row
29139    /// contributed its original policy VJP. The device reduction reads those
29140    /// normalized member terms in the admitted group order, then applies the
29141    /// original frozen coefficient once and produces one FP32[1] scalar.
29142    #[cfg(feature = "semantic-policy")]
29143    pub fn record_prepared_group_critic(
29144        &mut self,
29145        update_step: &SemanticPreparedStep,
29146        bank: usize,
29147        consumer_stream: u64,
29148    ) -> Result<SemanticPreparedGroupCritic, SemanticTransitionError> {
29149        dlpack_consumer_stream(consumer_stream)?;
29150        self.check_prepared_content_stream(update_step, consumer_stream)?;
29151        if bank > 1 {
29152            return Err(publication_input_error(
29153                "group critic requires bank zero or one",
29154            ));
29155        }
29156        let build = self
29157            .prepared_segment
29158            .as_ref()
29159            .ok_or_else(|| publication_input_error("group critic requires a prepared segment"))?;
29160        if build.completed
29161            || build.requested_kind(update_step, &self.publication_issuer)?
29162                != SemanticTransitionKind::Update
29163        {
29164            return Err(publication_input_error(
29165                "group critic requires the recording Update step",
29166            ));
29167        }
29168        let prepared = self.steps[&update_step.token]
29169            .prepared
29170            .as_ref()
29171            .expect("checked prepared Update owner");
29172        if prepared
29173            .model_work
29174            .as_ref()
29175            .and_then(|work| work.capture_bank)
29176            != Some(bank)
29177            || prepared.group_critic_recorded & (1 << bank) != 0
29178        {
29179            return Err(publication_input_error(
29180                "group critic requires one active, not yet reduced Update bank",
29181            ));
29182        }
29183        let training = prepared.training_view.as_ref().ok_or_else(|| {
29184            publication_input_error("prepared Update has no selected training-view owner")
29185        })?;
29186        let actor_members = training
29187            .actor_group_members()
29188            .iter()
29189            .map(|member| member.ordinal)
29190            .collect::<BTreeSet<_>>();
29191        if prepared.group_vjp_members[bank] != actor_members {
29192            return Err(publication_input_error(
29193                "group critic requires every frozen actor member exactly once",
29194            ));
29195        }
29196        let edit_members = training
29197            .edit_group_members()
29198            .iter()
29199            .map(|member| member.ordinal)
29200            .collect::<BTreeSet<_>>();
29201        if prepared.group_edit_members[bank] != edit_members {
29202            return Err(publication_input_error(
29203                "group critic requires every frozen edit member exactly once",
29204            ));
29205        }
29206        let terms = training.critic_terms();
29207        let total = training.critic_total();
29208        let objective = training.objective();
29209        let count = u64::try_from(training.actor_group_members().len())
29210            .map_err(|_| SemanticTransitionError::GenerationExhausted)?;
29211        let reduce = self
29212            .provider
29213            .device()
29214            .inner()
29215            .get_func("xlog_semantic_transition", "semantic_group_critic_reduce")
29216            .ok_or_else(|| publication_input_error("group critic reducer is unavailable"))?;
29217        let mut recorder = self.domain.new_strict_recorder();
29218        recorder.read(&terms);
29219        recorder.read(&objective);
29220        recorder.write(&total);
29221        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
29222            // SAFETY: strict recording retains the exact group allocation and
29223            // the native one-cell result until the captured bank is retired.
29224            unsafe {
29225                reduce
29226                    .launch_in(
29227                        enqueue,
29228                        LaunchConfig {
29229                            grid_dim: (1, 1, 1),
29230                            block_dim: (1, 1, 1),
29231                            shared_mem_bytes: 0,
29232                        },
29233                        (
29234                            *terms.device_ptr(),
29235                            *total.device_ptr(),
29236                            count,
29237                            *objective.device_ptr(),
29238                        ),
29239                    )
29240                    .map_err(|error| XlogError::Kernel(format!("group critic reduction: {error}")))
29241            }
29242        })?;
29243        self.steps
29244            .get_mut(&update_step.token)
29245            .expect("checked prepared Update owner")
29246            .prepared
29247            .as_mut()
29248            .expect("checked prepared Update")
29249            .group_critic_recorded |= 1 << bank;
29250        Ok(SemanticPreparedGroupCritic {
29251            value: total,
29252            provider: Arc::clone(&self.provider),
29253            step_aliases: Arc::clone(&self.steps[&update_step.token].aliases),
29254            publication: Arc::clone(
29255                self.publication
29256                    .as_ref()
29257                    .ok_or(SemanticTransitionError::NotBound)?,
29258            ),
29259        })
29260    }
29261
29262    #[cfg(feature = "semantic-policy")]
29263    pub fn require_recorded_group_critic(
29264        &self,
29265        update_step: &SemanticPreparedStep,
29266    ) -> Result<(), SemanticTransitionError> {
29267        if self.is_poisoned() {
29268            return Err(SemanticTransitionError::Poisoned);
29269        }
29270        let step = self.checked_prepared_step(update_step, false)?;
29271        let prepared = step.prepared.as_ref().expect("checked prepared owner");
29272        if !self
29273            .prepared_segment
29274            .as_ref()
29275            .is_some_and(|build| build.completed)
29276            || prepared.training_view.is_none()
29277            || prepared.group_critic_recorded != 0b11
29278            || !prepared.group_update_published
29279        {
29280            return Err(publication_input_error(
29281                "retained group member requires completed execution of both full-group Update banks",
29282            ));
29283        }
29284        Ok(())
29285    }
29286
29287    /// Prove that a captured Update has completed without publication. A
29288    /// retained source tape may then be retired without claiming a policy VJP.
29289    #[cfg(feature = "semantic-policy")]
29290    pub fn require_completed_unpublished_group_update(
29291        &self,
29292        update_step: &SemanticPreparedStep,
29293    ) -> Result<(), SemanticTransitionError> {
29294        if self.is_poisoned() {
29295            return Err(SemanticTransitionError::Poisoned);
29296        }
29297        let step = self.checked_prepared_step(update_step, false)?;
29298        let build = self
29299            .prepared_segment
29300            .as_ref()
29301            .ok_or(SemanticTransitionError::NotBound)?;
29302        if !build.completed
29303            || build.requested_kind(update_step, &self.publication_issuer)?
29304                != SemanticTransitionKind::Update
29305            || step
29306                .prepared
29307                .as_ref()
29308                .expect("checked prepared owner")
29309                .group_update_published
29310        {
29311            return Err(publication_input_error(
29312                "retained replay requires a completed Update that did not publish",
29313            ));
29314        }
29315        Ok(())
29316    }
29317
29318    /// Prove that the target executable and every prepared step owner have
29319    /// retired. A retained source graph cannot be released merely because the
29320    /// target's one-shot launch completed: the executable still holds its
29321    /// captured pointers until full segment retirement.
29322    #[cfg(feature = "semantic-policy")]
29323    pub fn require_retired_prepared_step(
29324        &self,
29325        step: &SemanticPreparedStep,
29326    ) -> Result<(), SemanticTransitionError> {
29327        if self.is_poisoned() {
29328            return Err(SemanticTransitionError::Poisoned);
29329        }
29330        if !Arc::ptr_eq(&step.issuer, &self.publication_issuer)
29331            || self.prepared_segment.is_some()
29332            || self.captured.is_some()
29333            || self.pending
29334            || !self.prepared_resources.is_empty()
29335            || self.steps.contains_key(&step.token)
29336        {
29337            return Err(publication_input_error(
29338                "retained source requires completed retirement of its target segment",
29339            ));
29340        }
29341        Ok(())
29342    }
29343
29344    /// Differentiate one independently restored original Proposal into this
29345    /// Update's graph. The child Session retains its published reader, tape,
29346    /// model outputs and original allocations through both captured banks.
29347    #[cfg(feature = "semantic-policy")]
29348    #[expect(
29349        clippy::too_many_arguments,
29350        reason = "the frozen target and original published invocation have distinct owners"
29351    )]
29352    pub fn record_imported_group_member_policy_vjp(
29353        &mut self,
29354        update_step: &SemanticPreparedStep,
29355        bank: usize,
29356        source: &mut SemanticTransitionSession,
29357        source_lease: &SemanticPublishedLease,
29358        invocation: SemanticRngBinding,
29359        member_ordinal: u64,
29360        member_row: &SemanticTrainingViewRow,
29361        consumer_stream: u64,
29362    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
29363        self.record_imported_policy_vjp(
29364            update_step,
29365            bank,
29366            source,
29367            source_lease,
29368            invocation,
29369            member_ordinal,
29370            member_row,
29371            false,
29372            consumer_stream,
29373        )
29374    }
29375
29376    /// Dispatch an independently restored row through the exact frozen native
29377    /// actor/edit membership; a nonmember cannot acquire a gradient root.
29378    #[cfg(feature = "semantic-policy")]
29379    #[expect(
29380        clippy::too_many_arguments,
29381        reason = "the frozen target and original published invocation have distinct owners"
29382    )]
29383    pub fn record_imported_policy_group_vjp(
29384        &mut self,
29385        update_step: &SemanticPreparedStep,
29386        bank: usize,
29387        source: &mut SemanticTransitionSession,
29388        source_lease: &SemanticPublishedLease,
29389        invocation: SemanticRngBinding,
29390        member_ordinal: u64,
29391        member_row: &SemanticTrainingViewRow,
29392        consumer_stream: u64,
29393    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
29394        let actor_member = self
29395            .steps
29396            .get(&update_step.token)
29397            .and_then(|step| step.prepared.as_ref())
29398            .and_then(|step| step.training_view.as_ref())
29399            .ok_or_else(|| publication_input_error("Update has no selected training view"))?
29400            .actor_group_members()
29401            .iter()
29402            .any(|member| member.ordinal == member_ordinal);
29403        if actor_member {
29404            self.record_imported_group_member_policy_vjp(
29405                update_step,
29406                bank,
29407                source,
29408                source_lease,
29409                invocation,
29410                member_ordinal,
29411                member_row,
29412                consumer_stream,
29413            )
29414        } else {
29415            self.record_imported_edit_member_policy_vjp(
29416                update_step,
29417                bank,
29418                source,
29419                source_lease,
29420                invocation,
29421                member_ordinal,
29422                member_row,
29423                consumer_stream,
29424            )
29425        }
29426    }
29427
29428    /// Record a historical supervised-edit row that is not an actor member.
29429    #[cfg(feature = "semantic-policy")]
29430    #[expect(
29431        clippy::too_many_arguments,
29432        reason = "the frozen target and original published invocation have distinct owners"
29433    )]
29434    pub fn record_imported_edit_member_policy_vjp(
29435        &mut self,
29436        update_step: &SemanticPreparedStep,
29437        bank: usize,
29438        source: &mut SemanticTransitionSession,
29439        source_lease: &SemanticPublishedLease,
29440        invocation: SemanticRngBinding,
29441        member_ordinal: u64,
29442        member_row: &SemanticTrainingViewRow,
29443        consumer_stream: u64,
29444    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
29445        self.record_imported_policy_vjp(
29446            update_step,
29447            bank,
29448            source,
29449            source_lease,
29450            invocation,
29451            member_ordinal,
29452            member_row,
29453            true,
29454            consumer_stream,
29455        )
29456    }
29457
29458    #[cfg(feature = "semantic-policy")]
29459    #[expect(
29460        clippy::too_many_arguments,
29461        reason = "the frozen target, original invocation and exact row are independent owners"
29462    )]
29463    fn record_imported_policy_vjp(
29464        &mut self,
29465        update_step: &SemanticPreparedStep,
29466        bank: usize,
29467        source: &mut SemanticTransitionSession,
29468        source_lease: &SemanticPublishedLease,
29469        invocation: SemanticRngBinding,
29470        member_ordinal: u64,
29471        member_row: &SemanticTrainingViewRow,
29472        edit_only: bool,
29473        consumer_stream: u64,
29474    ) -> Result<SemanticPreparedPolicyGradients, SemanticTransitionError> {
29475        dlpack_consumer_stream(consumer_stream)?;
29476        self.check_prepared_content_stream(update_step, consumer_stream)?;
29477        source.ensure_quiescent()?;
29478        if bank > 1
29479            || Arc::ptr_eq(&self.publication_issuer, &source.publication_issuer)
29480            || self.provider.device().ordinal() != source.provider.device().ordinal()
29481            || self.task_content() != source.task_content()
29482            || self.task_content().is_none()
29483            || self.task_scoring_law_identity()? != source.task_scoring_law_identity()?
29484        {
29485            return Err(publication_input_error(
29486                "imported group member requires a distinct original Session on the same bound task and device",
29487            ));
29488        }
29489        let build = self.prepared_segment.as_ref().ok_or_else(|| {
29490            publication_input_error("imported group member requires a prepared segment")
29491        })?;
29492        if build.completed
29493            || build.requested_kind(update_step, &self.publication_issuer)?
29494                != SemanticTransitionKind::Update
29495        {
29496            return Err(publication_input_error(
29497                "imported group member requires the recording Update step",
29498            ));
29499        }
29500        let prepared = self.steps[&update_step.token]
29501            .prepared
29502            .as_ref()
29503            .expect("checked prepared Update owner");
29504        if prepared
29505            .model_work
29506            .as_ref()
29507            .and_then(|work| work.capture_bank)
29508            != Some(bank)
29509            || prepared.group_critic_recorded & (1 << bank) != 0
29510            || (edit_only && prepared.group_edit_members[bank].contains(&member_ordinal))
29511            || (!edit_only && prepared.group_vjp_members[bank].contains(&member_ordinal))
29512        {
29513            return Err(publication_input_error(
29514                "imported group member requires an unused active Update bank slot",
29515            ));
29516        }
29517        let training = prepared.training_view.as_ref().ok_or_else(|| {
29518            publication_input_error("prepared Update has no selected training-view owner")
29519        })?;
29520        let member_index = if edit_only {
29521            None
29522        } else {
29523            Some(training.actor_group_member_index(member_ordinal, member_row)?)
29524        };
29525        let edit_member = training
29526            .edit_group_member_index(member_ordinal, member_row)?
29527            .is_some();
29528        if edit_only
29529            && (!edit_member
29530                || training
29531                    .actor_group_members()
29532                    .iter()
29533                    .any(|row| row.ordinal == member_ordinal))
29534        {
29535            return Err(publication_input_error(
29536                "edit-only VJP requires a frozen edit row outside the actor group",
29537            ));
29538        }
29539        let critic_term = member_index.map(|index| training.critic_term(index));
29540        let source_index = source
29541            .policy_tapes
29542            .iter()
29543            .position(|tape| tape.invocation == invocation)
29544            .ok_or(SemanticTransitionError::ObservationMismatch)?;
29545        let continuation = Arc::clone(&source.policy_tapes[source_index].policy.text_binding);
29546        source.checked_content_witness(source_lease, &continuation._witness)?;
29547        source.guard_continuation_content(&continuation)?;
29548        let reader = source.checked_reader(source_lease)?;
29549        let tape = &source.policy_tapes[source_index];
29550        if tape.refusal.is_some() || tape.prepared_bank.is_some() {
29551            return Err(publication_input_error(
29552                "imported group member requires its successful published policy tape",
29553            ));
29554        }
29555        let state = tape.origin_state.as_ref().ok_or_else(|| {
29556            publication_input_error("imported group member has no original published state")
29557        })?;
29558        let owner = Arc::clone(&tape.policy.buffers.temporal_adjoints);
29559        let PolicyVjpRecording {
29560            descriptor,
29561            recorder,
29562        } = self.prepare_policy_vjp_recording(
29563            &tape.policy,
29564            &owner,
29565            &tape.support,
29566            &tape.receipts,
29567            state,
29568            &tape.components,
29569            &tape.codebooks,
29570            if let Some(critic_term) = &critic_term {
29571                PolicyVjpInput::GroupMember {
29572                    training,
29573                    member_ordinal,
29574                    origin_candidate: u64::MAX,
29575                    origin_lease: &reader.device,
29576                    origin_bank: (source_lease.header.publication_word & 1) as usize,
29577                    critic_term,
29578                }
29579            } else {
29580                PolicyVjpInput::EditMember {
29581                    training,
29582                    member_ordinal,
29583                    origin_candidate: u64::MAX,
29584                    origin_lease: &reader.device,
29585                    origin_bank: (source_lease.header.publication_word & 1) as usize,
29586                }
29587            },
29588        )?;
29589        let baseline_snapshot = tape.policy.component_baselines.view();
29590        let layout = tape.policy.layout.clone();
29591        let continuation = Arc::clone(&tape.policy.text_binding);
29592        let support_cells = tape.support.len();
29593        let parameters = owner.parameters.view();
29594        let text_logits = owner.text_logits.view();
29595        let component_baselines = owner.component_baselines.view();
29596        let step_aliases = Arc::clone(&source.steps[&source_lease.token].aliases);
29597        let publication = Arc::clone(
29598            source
29599                .publication
29600                .as_ref()
29601                .ok_or(SemanticTransitionError::NotBound)?,
29602        );
29603        record_policy_vjp(
29604            &self.domain,
29605            &mut self.poisoned,
29606            recorder,
29607            self.execute.clone(),
29608            descriptor,
29609            &owner.coefficients,
29610            None,
29611            Some(&baseline_snapshot),
29612        )?;
29613        let update = self
29614            .steps
29615            .get_mut(&update_step.token)
29616            .expect("checked prepared Update owner")
29617            .prepared
29618            .as_mut()
29619            .expect("checked prepared Update");
29620        if !edit_only {
29621            update.group_vjp_members[bank].insert(member_ordinal);
29622        }
29623        if edit_member {
29624            update.group_edit_members[bank].insert(member_ordinal);
29625        }
29626        update.group_imported_vjp_members[bank].insert(member_ordinal);
29627        Ok(SemanticPreparedPolicyGradients {
29628            layout,
29629            parameters,
29630            text_logits,
29631            component_baselines,
29632            provider: Arc::clone(&source.provider),
29633            step_aliases,
29634            publication,
29635            continuation,
29636            owner,
29637            support_cells,
29638        })
29639    }
29640
29641    #[cfg(feature = "semantic-policy")]
29642    pub fn finish_prepared_policy_invocation(
29643        &mut self,
29644        step: &SemanticPreparedStep,
29645        invocation: SemanticRngBinding,
29646        consumer_stream: u64,
29647    ) -> Result<(), SemanticTransitionError> {
29648        let index = self.checked_prepared_policy_tape(step, invocation)?;
29649        self.finish_policy_tape(index, consumer_stream)
29650    }
29651
29652    /// Retire a completed published training invocation whose original policy
29653    /// tape was already differentiated inside both branches of this exact
29654    /// prepared Update capture. This never records or launches another VJP.
29655    #[cfg(feature = "semantic-policy")]
29656    pub fn finish_recorded_training_policy_invocation(
29657        &mut self,
29658        step: &SemanticPreparedStep,
29659        update_step: &SemanticPreparedStep,
29660        invocation: SemanticRngBinding,
29661        consumer_stream: u64,
29662    ) -> Result<(), SemanticTransitionError> {
29663        let index = self.checked_prepared_policy_tape(step, invocation)?;
29664        let update_owner = self.checked_prepared_step(update_step, false)?;
29665        let build = self
29666            .prepared_segment
29667            .as_ref()
29668            .expect("checked prepared segment");
29669        if !build.completed
29670            || !update_owner
29671                .prepared
29672                .as_ref()
29673                .is_some_and(|prepared| prepared.observed)
29674            || build.requested_kind(update_step, &self.publication_issuer)?
29675                != SemanticTransitionKind::Update
29676        {
29677            return Err(publication_input_error(
29678                "recorded training completion requires its actual completed Update step",
29679            ));
29680        }
29681        let proposal_ordinal = build
29682            .tokens
29683            .iter()
29684            .position(|token| *token == step.token)
29685            .ok_or(SemanticTransitionError::ObservationMismatch)?;
29686        let update_ordinal = build
29687            .tokens
29688            .iter()
29689            .position(|token| *token == update_step.token)
29690            .ok_or(SemanticTransitionError::ObservationMismatch)?;
29691        if proposal_ordinal >= update_ordinal {
29692            return Err(publication_input_error(
29693                "recorded training completion requires a preceding Proposal step",
29694            ));
29695        }
29696        let tape = &self.policy_tapes[index];
29697        if tape.refusal.is_some()
29698            || !(0..2).all(|bank| {
29699                tape.policy
29700                    .temporal_vjp_recorded
29701                    .contains(&(update_step.token, bank))
29702            })
29703        {
29704            return Err(publication_input_error(
29705                "published training completion requires the exact Update VJP in both captured banks",
29706            ));
29707        }
29708        self.finish_policy_tape(index, consumer_stream)
29709    }
29710
29711    /// Retire a published local Proposal that did not contribute a VJP to the
29712    /// complete frozen Update group. Both critic reductions prove that every
29713    /// frozen actor and edit member was accounted for by its actual tape.
29714    #[cfg(feature = "semantic-policy")]
29715    pub fn finish_unselected_recorded_training_policy_invocation(
29716        &mut self,
29717        step: &SemanticPreparedStep,
29718        update_step: &SemanticPreparedStep,
29719        invocation: SemanticRngBinding,
29720        consumer_stream: u64,
29721    ) -> Result<(), SemanticTransitionError> {
29722        let update_published = self
29723            .checked_prepared_step(update_step, false)?
29724            .prepared
29725            .as_ref()
29726            .expect("checked prepared owner")
29727            .group_update_published;
29728        if update_published {
29729            self.require_recorded_group_critic(update_step)?;
29730        } else {
29731            self.require_completed_unpublished_group_update(update_step)?;
29732        }
29733        let index = self.checked_prepared_policy_tape(step, invocation)?;
29734        let build = self
29735            .prepared_segment
29736            .as_ref()
29737            .expect("checked completed prepared segment");
29738        if build.requested_kind(step, &self.publication_issuer)? != SemanticTransitionKind::Proposal
29739            || build.requested_kind(update_step, &self.publication_issuer)?
29740                != SemanticTransitionKind::Update
29741        {
29742            return Err(publication_input_error(
29743                "unselected training completion requires its actual Proposal and Update steps",
29744            ));
29745        }
29746        let proposal_ordinal = build
29747            .tokens
29748            .iter()
29749            .position(|token| *token == step.token)
29750            .ok_or(SemanticTransitionError::ObservationMismatch)?;
29751        let update_ordinal = build
29752            .tokens
29753            .iter()
29754            .position(|token| *token == update_step.token)
29755            .ok_or(SemanticTransitionError::ObservationMismatch)?;
29756        if proposal_ordinal >= update_ordinal
29757            || self.policy_tapes[index].refusal.is_some()
29758            || !self.policy_tapes[index]
29759                .policy
29760                .temporal_vjp_recorded
29761                .is_empty()
29762        {
29763            return Err(publication_input_error(
29764                "unselected training completion requires an earlier published Proposal with no recorded Update VJP",
29765            ));
29766        }
29767        self.finish_policy_tape(index, consumer_stream)
29768    }
29769
29770    /// Retire an exact values-only invocation after the caller's final device
29771    /// use. This does not differentiate, reacquire a parent, or release readers.
29772    /// Final step release remains the cold completion boundary.
29773    #[cfg(feature = "semantic-policy")]
29774    pub fn finish_policy_invocation(
29775        &mut self,
29776        lease: &SemanticPublishedLease,
29777        invocation: SemanticRngBinding,
29778        consumer_stream: u64,
29779    ) -> Result<(), SemanticTransitionError> {
29780        self.ensure_quiescent()?;
29781        self.checked_step(lease)?;
29782        dlpack_consumer_stream(consumer_stream)?;
29783        let index = self
29784            .policy_tapes
29785            .iter()
29786            .position(|tape| tape.invocation == invocation)
29787            .ok_or(SemanticTransitionError::ObservationMismatch)?;
29788        let original = Arc::clone(&self.policy_tapes[index].policy.text_binding);
29789        self.checked_content_witness(lease, &original._witness)?;
29790        self.finish_policy_tape(index, consumer_stream)
29791    }
29792
29793    #[cfg(feature = "semantic-policy")]
29794    fn finish_policy_tape(
29795        &mut self,
29796        index: usize,
29797        consumer_stream: u64,
29798    ) -> Result<(), SemanticTransitionError> {
29799        self.ensure_quiescent()?;
29800        dlpack_consumer_stream(consumer_stream)?;
29801        let original = Arc::clone(&self.policy_tapes[index].policy.text_binding);
29802        let result = (|| {
29803            self.order_step_content_inputs(original._witness.reader_token, consumer_stream)?;
29804            self.guard_continuation_content(&original)?;
29805            self.order_content_consumers(consumer_stream)
29806        })();
29807        if let Err(error) = result {
29808            self.poisoned = true;
29809            return Err(error);
29810        }
29811        self.policy_tapes.remove(index);
29812        Ok(())
29813    }
29814
29815    #[cfg(feature = "semantic-policy")]
29816    #[expect(
29817        clippy::too_many_arguments,
29818        reason = "policy VJP recording retains each native owner explicitly"
29819    )]
29820    fn prepare_policy_vjp_recording(
29821        &self,
29822        policy: &PolicyStorage,
29823        adjoints: &PolicyAdjointBuffers,
29824        support: &TrackedCudaSlice<u8>,
29825        receipts: &TrackedCudaSlice<SemanticTransitionReceipt>,
29826        state: &TrackedCudaSlice<DeviceState>,
29827        components: &DeviceMemoryView<SemanticComponent>,
29828        codebooks: &DeviceMemoryView<u64>,
29829        input: PolicyVjpInput<'_>,
29830    ) -> Result<PolicyVjpRecording, SemanticTransitionError> {
29831        if let PolicyVjpInput::External(score_cotangents) = input {
29832            if score_cotangents.len() != COMPONENT_COUNT {
29833                return Err(SemanticTransitionError::InvalidInput {
29834                    detail: "selected-score cotangents must follow the complete component roster"
29835                        .into(),
29836                });
29837            }
29838        }
29839        let PolicyAdjointBuffers {
29840            parameters,
29841            text_logits,
29842            component_baselines,
29843            recurrent,
29844            scores,
29845            coefficients,
29846            status,
29847            numerical,
29848        } = adjoints;
29849        let io = TransitionKernelIo {
29850            logits: &policy.text_logits,
29851            support,
29852            receipts,
29853            state,
29854            policy: Some(policy),
29855            text: Some(&policy.text_binding),
29856            lease: None,
29857            model_work: None,
29858            model_update: None,
29859            replay_custody: None,
29860            training_selection: None,
29861        };
29862        let task = match input {
29863            PolicyVjpInput::External(_) => None,
29864            PolicyVjpInput::UpdateObjective { training, .. }
29865            | PolicyVjpInput::GroupMember { training, .. }
29866            | PolicyVjpInput::EditMember { training, .. } => {
29867                if matches!(input, PolicyVjpInput::UpdateObjective { .. })
29868                    && training.actor_group_member_count() != 1
29869                {
29870                    return Err(publication_input_error(
29871                        "single-proposal policy backward cannot represent the complete actor group",
29872                    ));
29873                }
29874                let (binding, device) = self.task.as_ref().ok_or_else(|| {
29875                    publication_input_error(
29876                        "Update policy backward requires the bound semantic task ground",
29877                    )
29878                })?;
29879                if binding.goal_witness().is_none() {
29880                    return Err(publication_input_error(
29881                        "Update policy backward requires the bound semantic goal closure",
29882                    ));
29883                }
29884                Some(device)
29885            }
29886        };
29887        let mut descriptor = self.descriptor_with(&io);
29888        descriptor.components = *components.device_ptr();
29889        descriptor.codebooks = *codebooks.device_ptr();
29890        descriptor.publication = PublicationCommand::default();
29891        let (
29892            selection,
29893            objective,
29894            objective_groups,
29895            objective_group_members,
29896            roster_rows,
29897            origin_candidate,
29898            origin_lease,
29899            origin_bank,
29900            mode,
29901            member_ordinal,
29902            critic_term,
29903        ) = match input {
29904            PolicyVjpInput::External(_) => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
29905            PolicyVjpInput::UpdateObjective {
29906                training,
29907                origin_candidate,
29908                origin_lease,
29909                origin_bank,
29910            } => (
29911                *training.selection().device_ptr(),
29912                *training.objective().device_ptr(),
29913                *training.objective_groups().device_ptr(),
29914                *training.objective_group_members().device_ptr(),
29915                *training.roster_rows().device_ptr(),
29916                origin_candidate,
29917                origin_lease.device_ptr_value(),
29918                origin_bank as u64,
29919                1,
29920                0,
29921                0,
29922            ),
29923            PolicyVjpInput::GroupMember {
29924                training,
29925                member_ordinal,
29926                origin_candidate,
29927                origin_lease,
29928                origin_bank,
29929                critic_term,
29930            } => (
29931                *training.selection().device_ptr(),
29932                *training.objective().device_ptr(),
29933                *training.objective_groups().device_ptr(),
29934                *training.objective_group_members().device_ptr(),
29935                *training.roster_rows().device_ptr(),
29936                origin_candidate,
29937                origin_lease.device_ptr_value(),
29938                origin_bank as u64,
29939                2,
29940                member_ordinal,
29941                *critic_term.device_ptr(),
29942            ),
29943            PolicyVjpInput::EditMember {
29944                training,
29945                member_ordinal,
29946                origin_candidate,
29947                origin_lease,
29948                origin_bank,
29949            } => (
29950                *training.selection().device_ptr(),
29951                *training.objective().device_ptr(),
29952                *training.objective_groups().device_ptr(),
29953                *training.objective_group_members().device_ptr(),
29954                *training.roster_rows().device_ptr(),
29955                origin_candidate,
29956                origin_lease.device_ptr_value(),
29957                origin_bank as u64,
29958                3,
29959                member_ordinal,
29960                0,
29961            ),
29962        };
29963        descriptor.backward = PolicyBackward {
29964            numerical: numerical.descriptor(),
29965            cotangents: coefficients.device_ptr_value(),
29966            parameters: parameters.device_ptr_value(),
29967            text: text_logits.device_ptr_value(),
29968            baselines: component_baselines.device_ptr_value(),
29969            recurrent: recurrent.device_ptr_value(),
29970            scores: scores.device_ptr_value(),
29971            status: status.device_ptr_value(),
29972            parameter_cells: policy.layout.parameter_cells as u64,
29973            text_cells: policy.text_logits.len() as u64,
29974            selection,
29975            objective,
29976            objective_groups,
29977            objective_group_members,
29978            roster_rows,
29979            origin_candidate,
29980            origin_lease,
29981            origin_bank,
29982            mode,
29983            member_ordinal,
29984            critic_term,
29985        };
29986        self.validate_ranges_with(&io)?;
29987        let mut recorder = self.domain.new_strict_recorder();
29988        recorder.read(support);
29989        recorder.read(receipts);
29990        recorder.read(codebooks);
29991        recorder.read(components);
29992        recorder.read(&policy.parameters);
29993        recorder.read(&policy.recurrent);
29994        recorder.read(&policy.text_logits);
29995        recorder.read(&policy.component_baselines);
29996        policy.numerical.record(&mut recorder);
29997        policy.text_binding.record(&mut recorder);
29998        match input {
29999            PolicyVjpInput::External(score_cotangents) => {
30000                recorder.read(score_cotangents);
30001            }
30002            PolicyVjpInput::UpdateObjective {
30003                training,
30004                origin_lease,
30005                ..
30006            }
30007            | PolicyVjpInput::GroupMember {
30008                training,
30009                origin_lease,
30010                ..
30011            }
30012            | PolicyVjpInput::EditMember {
30013                training,
30014                origin_lease,
30015                ..
30016            } => {
30017                recorder.read(&training.selection());
30018                recorder.read(&training.objective());
30019                recorder.read(&training.objective_groups());
30020                recorder.read(&training.objective_group_members());
30021                recorder.read(&training.roster_rows());
30022                recorder.read(state);
30023                recorder.read(origin_lease);
30024                recorder.read(task.expect("validated Update task ground"));
30025            }
30026        }
30027        if let PolicyVjpInput::GroupMember { critic_term, .. } = input {
30028            recorder.write(critic_term);
30029        }
30030        recorder.write(&self.scratch);
30031        recorder.write(&policy.hidden);
30032        recorder.write(&policy.scores);
30033        for buffer in [
30034            parameters,
30035            text_logits,
30036            component_baselines,
30037            recurrent,
30038            scores,
30039        ] {
30040            recorder.write(buffer);
30041        }
30042        recorder.write(coefficients);
30043        recorder.write(status);
30044        for buffer in numerical.buffers() {
30045            recorder.write(buffer);
30046        }
30047        Ok(PolicyVjpRecording {
30048            descriptor,
30049            recorder,
30050        })
30051    }
30052
30053    #[cfg(feature = "semantic-policy")]
30054    fn backward_policy_view(
30055        &mut self,
30056        invocation: SemanticRngBinding,
30057        score_cotangents: DeviceMemoryView<f64>,
30058        consumer_stream: u64,
30059    ) -> Result<SemanticPolicyGradients, SemanticTransitionError> {
30060        self.ensure_quiescent()?;
30061        dlpack_consumer_stream(consumer_stream)?;
30062        let tape_index = self
30063            .policy_tapes
30064            .iter()
30065            .position(|tape| tape.invocation == invocation)
30066            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30067        if let Some(refusal) = self.policy_tapes[tape_index].refusal {
30068            return Err(refusal.into_error());
30069        }
30070        let original = Arc::clone(&self.policy_tapes[tape_index].policy.text_binding);
30071        self.guard_continuation_content(&original)?;
30072        if let Err(error) =
30073            self.order_step_content_inputs(original._witness.reader_token, consumer_stream)
30074        {
30075            self.poisoned = true;
30076            return Err(error);
30077        }
30078        let publication = Arc::clone(
30079            self.publication
30080                .as_ref()
30081                .ok_or(SemanticTransitionError::NotBound)?,
30082        );
30083        let step_aliases = Arc::clone(&self.steps[&original._witness.reader_token].aliases);
30084        let tape = &self.policy_tapes[tape_index];
30085        let policy = &tape.policy;
30086        let state = if let Some(bank) = tape.prepared_bank {
30087            &self.steps[&original._witness.reader_token]
30088                .prepared
30089                .as_ref()
30090                .expect("retained prepared policy step")
30091                .branches[bank]
30092                .state
30093        } else {
30094            tape.origin_state
30095                .as_ref()
30096                .expect("ordinary policy tape retains its original state")
30097        };
30098        let PolicyVjpRecording {
30099            descriptor,
30100            recorder,
30101        } = self.prepare_policy_vjp_recording(
30102            policy,
30103            policy.buffers.adjoints.as_ref().ok_or_else(|| {
30104                publication_input_error("original policy adjoint banks have already been consumed")
30105            })?,
30106            &tape.support,
30107            &tape.receipts,
30108            state,
30109            &tape.components,
30110            &tape.codebooks,
30111            PolicyVjpInput::External(&score_cotangents),
30112        )?;
30113        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
30114            .map_err(|e| runtime_error("policy backward stream admission", e))?;
30115        let execute = self.execute.clone();
30116        let layout = policy.layout.clone();
30117        let binding = tape.binding;
30118        let support_cells = tape.support.len();
30119        // Consume only after every fallible admission check. The recorder owns
30120        // the scratch banks through execution; exported outputs retain their
30121        // original step until the final consumer-stream join.
30122        let PolicyAdjointBuffers {
30123            parameters,
30124            text_logits,
30125            component_baselines,
30126            recurrent,
30127            scores,
30128            coefficients,
30129            status,
30130            numerical,
30131        } = self.policy_tapes[tape_index]
30132            .policy
30133            .buffers
30134            .adjoints
30135            .take()
30136            .expect("checked original adjoint banks");
30137        let vjp_workspace = Arc::new(PolicyVjpWorkspace {
30138            _component_baselines: None,
30139            _numerical: Arc::clone(&numerical),
30140            _recurrent: recurrent,
30141            _scores: scores,
30142            coefficients,
30143            _status: status,
30144            score_cotangents: Some(score_cotangents),
30145        });
30146        // A capsule can be deleted before its consumer finishes. The original
30147        // step keeps the actual outputs until its final consumer-stream join,
30148        // without keeping a witness (which would create a release cycle).
30149        let output_views = [&parameters, &text_logits, &component_baselines]
30150            .into_iter()
30151            .map(|buffer| {
30152                // SAFETY: F32 storage has an exact, aligned byte representation.
30153                unsafe { buffer.view().cast::<u8>() }.expect("F32 adjoint byte view")
30154            });
30155        let step_owner = self
30156            .steps
30157            .get_mut(&original._witness.reader_token)
30158            .expect("retained original step");
30159        step_owner.adjoints.extend(output_views);
30160        step_owner
30161            .policy_vjp_workspaces
30162            .push(Arc::clone(&vjp_workspace));
30163        record_policy_vjp(
30164            &self.domain,
30165            &mut self.poisoned,
30166            recorder,
30167            execute,
30168            descriptor,
30169            &vjp_workspace.coefficients,
30170            vjp_workspace.score_cotangents.as_ref(),
30171            None,
30172        )?;
30173        if let Err(error) = self.order_content_consumers(consumer_stream) {
30174            self.poisoned = true;
30175            return Err(error);
30176        }
30177        self.policy_tapes.remove(tape_index);
30178        Ok(SemanticPolicyGradients {
30179            component_baselines,
30180            numerical,
30181            binding,
30182            invocation,
30183            layout,
30184            parameters,
30185            text_logits,
30186            provider: Arc::clone(&self.provider),
30187            step_aliases,
30188            publication,
30189            continuation: original,
30190            vjp_workspace,
30191            support_cells,
30192        })
30193    }
30194
30195    // Only construction and fresh native restoration may initialize these
30196    // private immutable allocations. Proposal tapes keep views of the same bytes.
30197    fn upload_cold_codebooks(&mut self) -> Result<(), SemanticTransitionError> {
30198        let upload = (|| {
30199            self.provider
30200                .htod_sync_copy_into_tracked(&self.codebooks.words, &mut self.device_codebooks)?;
30201            self.provider.htod_sync_copy_into_tracked(
30202                &self.codebooks.components,
30203                &mut self.device_components,
30204            )
30205        })();
30206        upload.map_err(|error| {
30207            self.poisoned = true;
30208            runtime_error("cold codebook upload", error)
30209        })
30210    }
30211
30212    fn upload_rng_state(
30213        &mut self,
30214        binding: SemanticCatalogueBinding,
30215        rng: SemanticRngBinding,
30216    ) -> Result<(), SemanticTransitionError> {
30217        let state = DeviceState {
30218            model_generation: rng.model_generation,
30219            family_id: u32::from(rng.family_id),
30220            stream_serial: rng.stream_serial,
30221            next_proposal: u64::from(rng.proposal),
30222            catalogue_generation: binding.generation,
30223            catalogue_digest: Identity256::from_bytes(CATALOGUE_DIGEST),
30224            binding_digest: binding.digest,
30225            ..DeviceState::default()
30226        };
30227        let upload = self
30228            .provider
30229            .htod_sync_copy_into_tracked(&[state], &mut self.state);
30230        upload.map_err(|e| {
30231            self.poisoned = true;
30232            runtime_error("RNG state upload", e)
30233        })
30234    }
30235
30236    pub fn capture(&mut self) -> Result<(), SemanticTransitionError> {
30237        self.ensure_rebindable()?;
30238        if self.publication.is_some()
30239            && (self.continuation_base.is_none()
30240                || self
30241                    .admitted_transition
30242                    .is_none_or(|(_, word, _)| Some(word) != self.continuation_base))
30243        {
30244            return Err(publication_input_error(
30245                "publication capture requires the admitted acquired-parent continuation",
30246            ));
30247        }
30248        if self.rng.is_none() {
30249            return Err(SemanticTransitionError::NotBound);
30250        }
30251        self.validate_ranges()?;
30252        let descriptor = self.descriptor();
30253        let execute = self.execute.clone();
30254        let recorder = self.kernel_recorder();
30255        self.graph.enter_transition();
30256        // Remain poisoned through EndCapture and instantiation, including unwind.
30257        // Admission inside capture transfers the actual owners to the graph.
30258        self.poisoned = true;
30259        let captured =
30260            CapturedCudaGraph::capture_on_stream_retaining(&self.stream, Vec::new(), || {
30261                // SAFETY: exact ABI, recorded disjoint allocations and bound stream.
30262                let enqueued = unsafe {
30263                    self.domain.enqueue(recorder, |enqueue| {
30264                        execute
30265                            .launch_in(
30266                                enqueue,
30267                                LaunchConfig {
30268                                    grid_dim: (1, 1, 1),
30269                                    block_dim: (256, 1, 1),
30270                                    shared_mem_bytes: 0,
30271                                },
30272                                (descriptor,),
30273                            )
30274                            .map_err(|error| XlogError::Kernel(error.to_string()))
30275                    })
30276                }
30277                .map_err(LaunchEnqueueError::into_xlog_error)?;
30278                enqueued.commit().map_err(|error| {
30279                    XlogError::Kernel(format!("semantic transition capture commit: {error}"))
30280                })
30281            })
30282            .map_err(|error| runtime_error("capture", error))?;
30283        self.captured = Some(captured);
30284        self.poisoned = false;
30285        Ok(())
30286    }
30287
30288    /// Nonblocking replay. All 136 distributions and RNG blocks execute on device.
30289    pub fn launch(&mut self) -> Result<(), SemanticTransitionError> {
30290        self.ensure_rebindable()?;
30291        if let Some(binding) = self.text_binding.as_ref().map(Arc::clone) {
30292            self.guard_continuation_content(&binding)?;
30293        }
30294        let graph = self
30295            .captured
30296            .as_ref()
30297            .ok_or(SemanticTransitionError::NotCaptured)?;
30298        if self.next_proposal > u64::from(u32::MAX) {
30299            return Err(SemanticTransitionError::GenerationExhausted);
30300        }
30301        let recorder = self.kernel_recorder();
30302        // SAFETY: every captured allocation is registered, owned, and cannot be
30303        // rebound or observed until terminal completion. Graph has no host nodes.
30304        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |stream| {
30305            graph.launch_in(stream)
30306        })?;
30307        self.pending = true;
30308        #[cfg(feature = "semantic-policy")]
30309        if let Some(policy) = &mut self.policy {
30310            policy.tape_live = true;
30311        }
30312        Ok(())
30313    }
30314
30315    /// Waits for completion, copies the typed bank into pinned memory, then observes
30316    /// the actual immutable hypergraph root. Unreconciled failures poison reuse;
30317    /// verified ordinary refusals retain the original invocation for finalization.
30318    pub fn observe(
30319        &mut self,
30320        expected_proposal: u32,
30321    ) -> Result<SemanticTransitionOutcome, SemanticTransitionError> {
30322        if self.is_poisoned() {
30323            return Err(SemanticTransitionError::Poisoned);
30324        }
30325        if !self.pending {
30326            return Err(SemanticTransitionError::NoPendingLaunch);
30327        }
30328        // Successful observation advances the session RNG. The original tape
30329        // must keep the invocation that produced its retained receipts.
30330        #[cfg(feature = "semantic-policy")]
30331        let policy_invocation = self.rng;
30332        let result = self.observe_terminal(expected_proposal);
30333        if result.is_err() {
30334            self.poisoned = true;
30335        } else {
30336            self.pending = false;
30337            #[cfg(feature = "semantic-policy")]
30338            if let Err(error) = self.retain_policy_tape(
30339                policy_invocation,
30340                match &result {
30341                    Ok(SemanticTransitionOutcome::Refused(refusal)) => Some(*refusal),
30342                    _ => None,
30343                },
30344            ) {
30345                self.poisoned = true;
30346                return Err(error);
30347            }
30348            self.task_observed = self.task.is_some() && self.publication.is_none();
30349            if self.publication.is_some() {
30350                self.continuation_base = None;
30351                self.admitted_transition = None;
30352                self.text_binding = None;
30353            }
30354        }
30355        result
30356    }
30357
30358    #[cfg(feature = "semantic-policy")]
30359    fn retain_policy_tape(
30360        &mut self,
30361        invocation: Option<SemanticRngBinding>,
30362        refusal: Option<SemanticTransitionRefusal>,
30363    ) -> Result<(), SemanticTransitionError> {
30364        let Some(policy) = self.policy.as_ref() else {
30365            return Ok(());
30366        };
30367        let invocation = invocation.ok_or(SemanticTransitionError::ObservationMismatch)?;
30368        let next_state = &policy
30369            .replacement
30370            .as_ref()
30371            .expect("proposal reserved its next working banks")
30372            .state;
30373        let mut recorder = self.domain.new_strict_recorder();
30374        recorder.read(&self.state);
30375        recorder.write(next_state);
30376        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |enqueue| {
30377            // SAFETY: the recorded source and reserved destination each hold
30378            // exactly one DeviceState on the controller's ordered CUDA stream.
30379            unsafe {
30380                sys::cuMemcpyDtoDAsync_v2(
30381                    next_state.device_ptr_value(),
30382                    self.state.device_ptr_value(),
30383                    size_of::<DeviceState>(),
30384                    enqueue.stream().cu_stream(),
30385                )
30386            }
30387            .result()
30388            .map_err(|error| XlogError::Kernel(error.to_string()))
30389        })?;
30390        let mut policy = self.policy.take().expect("checked original policy");
30391        let replacement = policy
30392            .replacement
30393            .take()
30394            .expect("proposal reserved its next working banks");
30395        self.rng = None;
30396        self.captured = None;
30397        self.policy_tapes.push(PolicyTape {
30398            invocation,
30399            refusal,
30400            binding: self.binding(),
30401            policy,
30402            support: std::mem::replace(&mut self.support, replacement.support),
30403            receipts: std::mem::replace(&mut self.receipts, replacement.receipts),
30404            prepared_bank: None,
30405            origin_state: Some(std::mem::replace(&mut self.state, replacement.state)),
30406            components: self.device_components.view(),
30407            codebooks: self.device_codebooks.view(),
30408        });
30409        Ok(())
30410    }
30411
30412    fn observe_terminal(
30413        &mut self,
30414        expected_proposal: u32,
30415    ) -> Result<SemanticTransitionOutcome, SemanticTransitionError> {
30416        let _ordinary = crate::cuda_graph::reserve_uncaptured_stream(&self.stream)
30417            .map_err(|error| runtime_error("terminal observation stream admission", error))?;
30418        wait_on_stream(
30419            &self.stream,
30420            &mut self.poisoned,
30421            &mut self.stream_waits,
30422            "terminal wait",
30423            CudaStream::synchronize,
30424        )?;
30425        let mut recorder = self.domain.new_strict_recorder();
30426        recorder.read(&self.state);
30427        recorder.read(&self.receipts);
30428        // SAFETY: pinned destination and tracked sources live through the second
30429        // wait, including cleanup on an enqueue/commit error.
30430        enqueue_recorded(&self.domain, &mut self.poisoned, recorder, |stream| {
30431            self.pinned.enqueue_copy(
30432                self.state.device_ptr_value(),
30433                self.receipts.device_ptr_value(),
30434                stream.stream(),
30435            )
30436        })?;
30437        wait_on_stream(
30438            &self.stream,
30439            &mut self.poisoned,
30440            &mut self.stream_waits,
30441            "observation wait",
30442            CudaStream::synchronize,
30443        )?;
30444        // SAFETY: both transfers and the final stream wait succeeded.
30445        let (state, components) = unsafe { self.pinned.read()? };
30446        self.provider
30447            .record_final_observation_transfer(size_of::<DeviceState>() as u64);
30448        self.provider.record_final_observation_transfer(
30449            (COMPONENT_COUNT * size_of::<SemanticTransitionReceipt>()) as u64,
30450        );
30451        if matches!(state.status, 2 | 5 | 11 | 12..=14) && self.publication.is_some() {
30452            let refusal = self.reconcile_refusal(&state, expected_proposal)?;
30453            return Ok(SemanticTransitionOutcome::Refused(refusal));
30454        }
30455        if state.status == 2 {
30456            return Err(SemanticTransitionError::InvalidFinalSupport {
30457                completed_draws: state.blocks,
30458            });
30459        }
30460        if state.status == 5 {
30461            return Err(SemanticTransitionError::NonFinitePolicyInput {
30462                completed_draws: state.blocks,
30463            });
30464        }
30465        if state.status == 11 {
30466            return Err(SemanticTransitionError::WorkCounterOverflow {
30467                completed_draws: state.blocks,
30468            });
30469        }
30470        if matches!(state.status, 12..=14) {
30471            return Err(SemanticTransitionError::InvalidTrainingView {
30472                status: state.status - 11,
30473            });
30474        }
30475        match state.status {
30476            7 => return Err(SemanticTransitionError::InvalidTaskBank),
30477            8 => return Err(SemanticTransitionError::InvalidTaskBase),
30478            9 => return Err(SemanticTransitionError::TaskOwnerFailure),
30479            _ => {}
30480        }
30481        let published = if self.publication.is_some() {
30482            Some(self.reconcile_publication(&state, expected_proposal)?)
30483        } else {
30484            None
30485        };
30486        let rng = self
30487            .rng
30488            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30489        if expected_proposal != rng.proposal || u64::from(expected_proposal) != self.next_proposal {
30490            return Err(SemanticTransitionError::ObservationMismatch);
30491        }
30492        let policy_text = false;
30493        #[cfg(feature = "semantic-policy")]
30494        let policy_text = self.policy.is_some() || policy_text;
30495        self.finish_observed_transition(state, components, rng, published, policy_text)
30496    }
30497
30498    fn finish_observed_transition(
30499        &mut self,
30500        state: DeviceState,
30501        components: Vec<SemanticTransitionReceipt>,
30502        rng: SemanticRngBinding,
30503        published: Option<(
30504            PublicationHeader,
30505            (SemanticRootHandle, SemanticRootSnapshot),
30506            SemanticTransitionKind,
30507        )>,
30508        policy_text: bool,
30509    ) -> Result<SemanticTransitionOutcome, SemanticTransitionError> {
30510        let proposal = u64::from(rng.proposal);
30511        if state.model_generation != rng.model_generation
30512            || state.family_id != u32::from(rng.family_id)
30513            || state.stream_serial != rng.stream_serial
30514        {
30515            return Err(SemanticTransitionError::ObservationMismatch);
30516        }
30517        if let Some((header, (root, snapshot), kind)) = published {
30518            if kind != SemanticTransitionKind::Proposal {
30519                if state.status != 0
30520                    || state.blocks != 0
30521                    || state.proposal != proposal
30522                    || state.next_proposal != proposal
30523                    || state.importance_weight != 1.0
30524                {
30525                    return Err(SemanticTransitionError::ObservationMismatch);
30526                }
30527                self.root = root;
30528                self.base_snapshot = snapshot;
30529                self.next_proposal = header.proposal;
30530                return Ok(SemanticTransitionOutcome::Published(
30531                    SemanticTransitionObservation {
30532                        components: Vec::new(),
30533                        root_handle: root,
30534                        root: snapshot,
30535                        next_proposal: header.proposal,
30536                        lanes: std::array::from_fn(|_| SemanticTransitionLane {
30537                            root: None,
30538                            task_refusal: None,
30539                            program_rules: [None; 2],
30540                            edits: [Ok(None), Ok(None)],
30541                            work: SemanticTransitionWork::default(),
30542                        }),
30543                        importance_weight: state.importance_weight,
30544                        task_evaluation: None,
30545                    },
30546                ));
30547            }
30548        }
30549        if state.semantic_receipts[0][0] != 0 {
30550            self.graph
30551                .observe_transition_root(state.semantic_receipts[0])
30552                .map_err(SemanticTransitionError::Semantic)?;
30553        }
30554        let binding = SemanticActionCatalogue::current().binding();
30555        let editable_program = self
30556            .task
30557            .as_ref()
30558            .is_some_and(|(task, _)| task.spec().program.editable_program().is_some());
30559        if state.status != 0
30560            || state.proposal != proposal
30561            || state.next_proposal != proposal + 1
30562            || components.len() != COMPONENT_COUNT
30563            || state.blocks != COMPONENT_COUNT as u64
30564            || state.catalogue_generation != binding.generation
30565            || state.catalogue_digest != binding.digest
30566            || state.binding_digest != self.binding().digest
30567            || state
30568                .work
30569                .iter()
30570                .any(|work| !work.is_valid(editable_program))
30571            || (published.is_none() && state.retired_roots_mask != 0)
30572            || state.retired_roots_mask & !3 != 0
30573            || !state.importance_weight.is_finite()
30574            || state.importance_weight <= 0.0
30575        {
30576            return Err(SemanticTransitionError::ObservationMismatch);
30577        }
30578        for (row, component) in components.iter().zip(&self.codebooks.components) {
30579            let inactive_text = policy_text
30580                && component.kind == COMPONENT_KIND_TEXT as u32
30581                && canonical_text_null(row);
30582            if row.ordinal != component.ordinal
30583                || row.lane != component.lane
30584                || row.slot != component.slot
30585                || row.field != component.field
30586                || row.kind != component.kind
30587                || row.proposal != state.proposal
30588                || row.catalogue_generation != binding.generation
30589                || row.catalogue_digest != binding.digest
30590                || row.admission_binding != self.binding().digest
30591                || if inactive_text {
30592                    !canonical_text_null(row)
30593                } else {
30594                    row.choice >= component.cardinality
30595                }
30596                || row.cdf_start > row.draw
30597                || row.draw >= row.cdf_end
30598                || row.cdf_end > 1u64 << 63
30599                || row.cdf_end - row.cdf_start != row.mass
30600                || row.mass < 1u64 << 32
30601            {
30602                return Err(SemanticTransitionError::ObservationMismatch);
30603            }
30604        }
30605        let mut integrity_error = None;
30606        let task_evaluation = if let Some((binding, _)) = &self.task {
30607            let task = &state.task_evaluation;
30608            if task.query_count < 3
30609                || task.query_count > 9
30610                || !task.query_count.is_multiple_of(3)
30611                || task.winner > 2
30612                || task.facts[task.winner as usize].eligible != 1
30613                || task.lane_refusal.iter().any(|&code| code > 4)
30614                || (binding.spec.program.editable_program().is_none()
30615                    && task.lane_refusal.iter().any(|&code| code >= 3))
30616            {
30617                return Err(SemanticTransitionError::ObservationMismatch);
30618            }
30619            Some(SemanticTaskEvaluation {
30620                binding: binding.identity(),
30621                query_count: task.query_count,
30622                winner: task.winner,
30623                return_value: task.return_value,
30624                facts: task.facts,
30625            })
30626        } else {
30627            None
30628        };
30629        let edit_choices: [[[u32; 18]; 2]; 2] = std::array::from_fn(|lane| {
30630            std::array::from_fn(|slot| {
30631                std::array::from_fn(|field| components[lane * 68 + 32 + slot * 18 + field].choice)
30632            })
30633        });
30634        let mut program_rules = [[None; 2]; 2];
30635        if let Some((task, _)) = &self.task {
30636            if let Some(program) = task.spec().program.editable_program() {
30637                if let Err(error) = validate_program_query_receipts(
30638                    program,
30639                    task.identity(),
30640                    &self.codebooks,
30641                    &state,
30642                    &edit_choices,
30643                ) {
30644                    self.poisoned = true;
30645                    return Err(error);
30646                }
30647                for lane in 0..2 {
30648                    for slot in 0..2 {
30649                        let choices = &edit_choices[lane][slot];
30650                        let receipt = &state.semantic_receipts[1 + lane * 3 + slot];
30651                        if choices[0] == 1 && choices[1] == 2 {
30652                            let previous = (slot == 1).then_some(&edit_choices[lane][0]);
30653                            match validated_rule_receipt(
30654                                &self.codebooks,
30655                                program,
30656                                task.identity(),
30657                                lane,
30658                                slot,
30659                                choices,
30660                                previous,
30661                                receipt,
30662                            ) {
30663                                Ok((decoded, _)) => program_rules[lane][slot] = Some(decoded.rule),
30664                                Err(error) => {
30665                                    self.poisoned = true;
30666                                    return Err(error);
30667                                }
30668                            }
30669                        } else if choices[0] == 1 || receipt[1] == 3 {
30670                            self.poisoned = true;
30671                            return Err(SemanticTransitionError::ObservationMismatch);
30672                        }
30673                    }
30674                }
30675            }
30676        }
30677        let lanes = std::array::from_fn(|i| {
30678            let task_refusal = if task_evaluation.is_some() {
30679                match state.task_evaluation.lane_refusal[i] {
30680                    1 => Some(SemanticTaskRefusal::Scope),
30681                    2 => Some(SemanticTaskRefusal::HardConstraint),
30682                    3 => Some(SemanticTaskRefusal::FactCapacity),
30683                    4 => Some(SemanticTaskRefusal::FuelExhausted),
30684                    _ => None,
30685                }
30686            } else {
30687                None
30688            };
30689            let root =
30690                (task_refusal.is_none() && state.retired_roots_mask & (1 << i) == 0).then(|| {
30691                    self.graph
30692                        .observe_transition_root(state.semantic_receipts[3 + i * 3])
30693                });
30694            if self.graph.ensure_not_poisoned().is_err() {
30695                if let Some(Err(error)) = &root {
30696                    integrity_error.get_or_insert_with(|| error.clone());
30697                }
30698            }
30699            let edits = std::array::from_fn(|j| {
30700                let result = if program_rules[i][j].is_some() {
30701                    Ok(None)
30702                } else {
30703                    self.graph
30704                        .observe_transition_edit(state.semantic_receipts[1 + i * 3 + j])
30705                };
30706                if self.graph.ensure_not_poisoned().is_err() {
30707                    if let Err(error) = &result {
30708                        integrity_error.get_or_insert_with(|| error.clone());
30709                    }
30710                }
30711                result
30712            });
30713            SemanticTransitionLane {
30714                root,
30715                task_refusal,
30716                program_rules: program_rules[i],
30717                edits,
30718                work: state.work[i],
30719            }
30720        });
30721        if let Some(error) = integrity_error {
30722            return Err(SemanticTransitionError::Semantic(error));
30723        }
30724        if let Some((_, (root, snapshot), _)) = published {
30725            self.root = root;
30726            self.base_snapshot = snapshot;
30727        }
30728        self.next_proposal = state.next_proposal;
30729        if let Ok(proposal) = u32::try_from(self.next_proposal) {
30730            self.rng = Some(SemanticRngBinding { proposal, ..rng });
30731        }
30732        Ok(SemanticTransitionOutcome::Published(
30733            SemanticTransitionObservation {
30734                components,
30735                root_handle: self.root,
30736                root: self.base_snapshot,
30737                next_proposal: state.next_proposal,
30738                lanes,
30739                importance_weight: state.importance_weight,
30740                task_evaluation,
30741            },
30742        ))
30743    }
30744
30745    fn reconcile_refusal(
30746        &mut self,
30747        state: &DeviceState,
30748        expected_proposal: u32,
30749    ) -> Result<SemanticTransitionRefusal, SemanticTransitionError> {
30750        let rng = self
30751            .rng
30752            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30753        if rng.proposal != expected_proposal || u64::from(expected_proposal) != self.next_proposal {
30754            return Err(SemanticTransitionError::ObservationMismatch);
30755        }
30756        let refusal = refused_terminal(
30757            state,
30758            rng,
30759            SemanticActionCatalogue::current().binding(),
30760            self.binding().digest,
30761            None,
30762        )?;
30763        let storage = Arc::clone(
30764            self.publication
30765                .as_ref()
30766                .ok_or(SemanticTransitionError::NotBound)?,
30767        );
30768        let (token, base_word, _) = self
30769            .admitted_transition
30770            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30771        let original = Arc::clone(
30772            self.text_binding
30773                .as_ref()
30774                .ok_or(SemanticTransitionError::ObservationMismatch)?,
30775        );
30776        let reader = self
30777            .readers
30778            .get(&token)
30779            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30780        let step = self
30781            .steps
30782            .get(&token)
30783            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30784        if self.continuation_base != Some(base_word)
30785            || original._witness.reader_token != token
30786            || original.published_parent()?.0 != (base_word & 1) as usize
30787            || !Arc::ptr_eq(&original._witness.issuer, &self.publication_issuer)
30788            || !Arc::ptr_eq(&original._witness._witness, &step.content_witnesses)
30789            || step
30790                .content
30791                .get(original._witness.index)
30792                .is_none_or(|content| !matches!(content.seals, TensorContentSeals::Captured(_)))
30793        {
30794            return Err(SemanticTransitionError::ObservationMismatch);
30795        }
30796        let lease_view = reader.device.view();
30797        let lease = self.publication_read(lease_view)?[0];
30798        let control = self.publication_read(storage.control.view())?[0];
30799        if lease.abi != 1
30800            || lease.status != 0
30801            || lease.active != 1
30802            || lease.instance != storage.instance
30803            || lease.word != base_word
30804            || lease.bank != base_word & 1
30805            || lease.epoch != base_word >> 1
30806            || control.reader_counts[lease.bank as usize] == 0
30807            || control.abi != 1
30808            || control.instance != storage.instance
30809            || control.word != base_word
30810            || control.reader_gate != 0
30811            || control.refusal != 0
30812        {
30813            return Err(SemanticTransitionError::ObservationMismatch);
30814        }
30815        let (bank, parent_header) = original.published_parent()?;
30816        let header = self.read_publication_header(bank)?;
30817        if header != parent_header
30818            || header.abi != 1
30819            || header.instance != storage.instance
30820            || header.publication_word != base_word
30821            || header.sealed_epoch != base_word >> 1
30822            || header.proposal != state.proposal
30823            || header.model_generation != u64::from(state.model_generation)
30824            || header.family_id != u64::from(state.family_id)
30825            || header.stream_serial != state.stream_serial
30826        {
30827            return Err(SemanticTransitionError::ObservationMismatch);
30828        }
30829        // The kernel snapshots this exact protected root after ordinary cleanup,
30830        // including the pre-staging numerical refusal. No success receipt is invented.
30831        let (root, snapshot) = self.observe_publication_root(state, &header, 0)?;
30832        if root != self.root || snapshot != self.base_snapshot {
30833            return Err(SemanticTransitionError::ObservationMismatch);
30834        }
30835        refused_root_cleanup(
30836            state,
30837            self.graph.transition_arena()[1],
30838            u64::from(root.slot()),
30839            root.generation(),
30840        )?;
30841        Ok(refusal)
30842    }
30843
30844    fn observe_publication_root(
30845        &mut self,
30846        state: &DeviceState,
30847        header: &PublicationHeader,
30848        index: usize,
30849    ) -> Result<(SemanticRootHandle, SemanticRootSnapshot), SemanticTransitionError> {
30850        let (root, snapshot) = self
30851            .graph
30852            .observe_transition_root(state.semantic_receipts[index])
30853            .map_err(SemanticTransitionError::Semantic)?;
30854        let extents = snapshot.extents();
30855        if header.semantic_owner != self.graph.transition_arena()[1]
30856            || header.semantic_slot != u64::from(root.slot())
30857            || header.semantic_generation != root.generation()
30858            || header.semantic_digest.as_bytes() != snapshot.digest().as_bytes()
30859            || header.semantic_extents
30860                != [
30861                    u64::from(extents.statements()),
30862                    u64::from(extents.supports()),
30863                    u64::from(extents.versions()),
30864                ]
30865        {
30866            return Err(SemanticTransitionError::ObservationMismatch);
30867        }
30868        Ok((root, snapshot))
30869    }
30870
30871    fn reconcile_publication(
30872        &mut self,
30873        state: &DeviceState,
30874        expected_proposal: u32,
30875    ) -> Result<
30876        (
30877            PublicationHeader,
30878            (SemanticRootHandle, SemanticRootSnapshot),
30879            SemanticTransitionKind,
30880        ),
30881        SemanticTransitionError,
30882    > {
30883        let storage = Arc::clone(
30884            self.publication
30885                .as_ref()
30886                .ok_or(SemanticTransitionError::NotBound)?,
30887        );
30888        let (_, base_word, kind) = self
30889            .admitted_transition
30890            .ok_or(SemanticTransitionError::ObservationMismatch)?;
30891        let control = self.publication_read(storage.control.view())?[0];
30892        if control.refusal != 0 || state.status == 10 {
30893            return Err(SemanticTransitionError::PublicationRefused {
30894                status: control.refusal,
30895            });
30896        }
30897        let epoch = (base_word >> 1)
30898            .checked_add(1)
30899            .filter(|&epoch| epoch <= u64::MAX >> 1)
30900            .ok_or(SemanticTransitionError::GenerationExhausted)?;
30901        let expected_word = (epoch << 1) | ((base_word ^ 1) & 1);
30902        if state.status != 0
30903            || control.abi != 1
30904            || control.instance != storage.instance
30905            || control.word != expected_word
30906            || self.continuation_base != Some(base_word)
30907            || u64::from(expected_proposal) != self.next_proposal
30908        {
30909            return Err(SemanticTransitionError::ObservationMismatch);
30910        }
30911        let header = self.read_publication_header((expected_word & 1) as usize)?;
30912        let next_proposal = self
30913            .next_proposal
30914            .checked_add(u64::from(kind == SemanticTransitionKind::Proposal))
30915            .ok_or(SemanticTransitionError::GenerationExhausted)?;
30916        if header.abi != 1
30917            || header.instance != control.instance
30918            || header.base_word != base_word
30919            || header.publication_word != expected_word
30920            || header.sealed_epoch != epoch
30921            || header.proposal != next_proposal
30922        {
30923            return Err(SemanticTransitionError::ObservationMismatch);
30924        }
30925        let winner = if kind == SemanticTransitionKind::Proposal {
30926            state.task_evaluation.winner
30927        } else {
30928            0
30929        };
30930        let index = match winner {
30931            0 => 0,
30932            1 => 3,
30933            2 => 6,
30934            _ => return Err(SemanticTransitionError::ObservationMismatch),
30935        };
30936        if winner > 0 && state.retired_roots_mask & (1 << (winner - 1)) != 0 {
30937            return Err(SemanticTransitionError::ObservationMismatch);
30938        }
30939        let root = self.observe_publication_root(state, &header, index)?;
30940        Ok((header, root, kind))
30941    }
30942
30943    fn ensure_quiescent(&self) -> Result<(), SemanticTransitionError> {
30944        if self.is_poisoned() {
30945            Err(SemanticTransitionError::Poisoned)
30946        } else if self.pending {
30947            Err(SemanticTransitionError::OverlappingLaunch)
30948        } else {
30949            Ok(())
30950        }
30951    }
30952
30953    fn ensure_rebindable(&self) -> Result<(), SemanticTransitionError> {
30954        if self.initial_prefill.is_some() {
30955            return Err(publication_input_error(
30956                "an imported task's initial prefill stage cannot be rebound",
30957            ));
30958        }
30959        self.ensure_rebindable_with_prefill()
30960    }
30961
30962    fn ensure_rebindable_with_prefill(&self) -> Result<(), SemanticTransitionError> {
30963        self.ensure_quiescent()?;
30964        #[cfg(feature = "semantic-policy")]
30965        self.require_closed_evaluations()?;
30966        validate_rebinding_ownership(
30967            self.prepared_segment.as_ref(),
30968            self.steps.values().any(|step| step.identity.is_none()),
30969        )?;
30970        if self.task_observed {
30971            return Err(SemanticTransitionError::UnpublishedTask);
30972        }
30973        #[cfg(feature = "semantic-policy")]
30974        if self.policy.as_ref().is_some_and(|policy| policy.tape_live) {
30975            return Err(SemanticTransitionError::UnconsumedPolicyTape);
30976        }
30977        Ok(())
30978    }
30979
30980    fn transition_kernel_io(&self) -> TransitionKernelIo<'_> {
30981        let logits = &self.logits;
30982        let text = self.text_binding.as_deref();
30983        #[cfg(feature = "semantic-policy")]
30984        let (logits, text) = self.policy.as_ref().map_or((logits, text), |policy| {
30985            (&policy.text_logits, Some(policy.text_binding.as_ref()))
30986        });
30987        TransitionKernelIo {
30988            logits,
30989            support: &self.support,
30990            receipts: &self.receipts,
30991            state: &self.state,
30992            text,
30993            model_work: None,
30994            replay_custody: None,
30995            model_update: None,
30996            lease: self
30997                .admitted_transition
30998                .map(|(token, _, _)| &self.readers[&token].device),
30999            #[cfg(feature = "semantic-policy")]
31000            policy: self.policy.as_ref(),
31001            training_selection: None,
31002        }
31003    }
31004
31005    #[cfg(feature = "semantic-policy")]
31006    fn prepared_kernel_io(
31007        &self,
31008        step: &SemanticPreparedStep,
31009        bank: usize,
31010    ) -> Result<TransitionKernelIo<'_>, SemanticTransitionError> {
31011        let prepared = self
31012            .steps
31013            .get(&step.token)
31014            .and_then(|owner| owner.prepared.as_ref())
31015            .ok_or_else(|| {
31016                publication_input_error("prepared transition has no original storage")
31017            })?;
31018        let branch = prepared
31019            .branches
31020            .get(bank)
31021            .ok_or_else(|| publication_input_error("prepared transition bank is invalid"))?;
31022        let policy = branch.policy.as_ref();
31023        let text = &branch
31024            .continuation
31025            .as_ref()
31026            .ok_or_else(|| {
31027                publication_input_error("prepared transition has no original continuation")
31028            })?
31029            .text_binding;
31030        let logits = match policy {
31031            Some(policy) => &policy.text_logits,
31032            None => {
31033                &branch
31034                    .policy_buffers
31035                    .as_ref()
31036                    .ok_or_else(|| {
31037                        publication_input_error("prepared transition has no retained cold buffers")
31038                    })?
31039                    .text_logits
31040            }
31041        };
31042        Ok(TransitionKernelIo {
31043            // Nonproposal execution returns before reading logits or support.
31044            // Retain the original cold allocation; do not invent policy values.
31045            logits,
31046            support: branch
31047                .support
31048                .as_ref()
31049                .ok_or_else(|| publication_input_error("prepared support has retired"))?,
31050            receipts: branch
31051                .receipts
31052                .as_ref()
31053                .ok_or_else(|| publication_input_error("prepared receipts have retired"))?,
31054            state: &branch.state,
31055            text: Some(text),
31056            lease: Some(&prepared.reader),
31057            policy,
31058            model_work: prepared.model_work.as_ref(),
31059            replay_custody: prepared.replay_custody.as_ref(),
31060            model_update: branch.model_update.as_ref(),
31061            training_selection: branch
31062                .continuation
31063                .as_ref()
31064                .and_then(|continuation| continuation.training_selection.as_ref()),
31065        })
31066    }
31067
31068    #[cfg(feature = "semantic-policy")]
31069    fn prepared_drain_kernel_io(
31070        &self,
31071        step: &SemanticPreparedStep,
31072    ) -> Result<TransitionKernelIo<'_>, SemanticTransitionError> {
31073        let prepared = self
31074            .steps
31075            .get(&step.token)
31076            .and_then(|owner| owner.prepared.as_ref())
31077            .ok_or_else(|| publication_input_error("prepared drain has no original storage"))?;
31078        let branch = &prepared.branches[0];
31079        let logits = if let Some(policy) = branch.policy.as_ref() {
31080            &policy.text_logits
31081        } else {
31082            &branch
31083                .policy_buffers
31084                .as_ref()
31085                .ok_or_else(|| {
31086                    publication_input_error("prepared drain has no retained cold buffers")
31087                })?
31088                .text_logits
31089        };
31090        Ok(TransitionKernelIo {
31091            logits,
31092            support: branch
31093                .support
31094                .as_ref()
31095                .ok_or_else(|| publication_input_error("prepared support has retired"))?,
31096            receipts: branch
31097                .receipts
31098                .as_ref()
31099                .ok_or_else(|| publication_input_error("prepared receipts have retired"))?,
31100            state: &branch.state,
31101            text: None,
31102            lease: Some(&prepared.reader),
31103            policy: None,
31104            model_work: None,
31105            model_update: None,
31106            training_selection: None,
31107            replay_custody: None,
31108        })
31109    }
31110
31111    fn descriptor(&self) -> Descriptor {
31112        self.descriptor_with(&self.transition_kernel_io())
31113    }
31114
31115    fn descriptor_with(&self, io: &TransitionKernelIo<'_>) -> Descriptor {
31116        #[cfg(not(feature = "semantic-policy"))]
31117        let policy = PolicyDescriptor::default();
31118        #[cfg(feature = "semantic-policy")]
31119        let policy = io.policy.map_or(PolicyDescriptor::default(), |policy| {
31120            Self::retained_policy_descriptor(&policy.buffers)
31121        });
31122        Descriptor {
31123            logits: 0,
31124            support: 0,
31125            scratch: self.scratch.device_ptr_value(),
31126            receipts: 0,
31127            state: 0,
31128            components: self.device_components.device_ptr_value(),
31129            codebooks: self.device_codebooks.device_ptr_value(),
31130            arena: self.graph.transition_arena(),
31131            policy: PolicyDescriptor::default(),
31132            backward: PolicyBackward::default(),
31133            task: self
31134                .task
31135                .as_ref()
31136                .map_or(0, |(_, device)| device.device_ptr_value()),
31137            task_words: self
31138                .task
31139                .as_ref()
31140                .map_or(0, |(_, device)| device.len() as u64),
31141            task_return_bound: self
31142                .task
31143                .as_ref()
31144                .map_or(0, |(binding, _)| binding.objective_law.return_bound as u64),
31145            publication: PublicationCommand {
31146                control: self
31147                    .publication
31148                    .as_ref()
31149                    .map_or(0, |storage| storage.control.device_ptr_value()),
31150                lease: 0,
31151                operation: 0,
31152            },
31153            text: TextBinding::default(),
31154            model_work: ModelWorkInput::default(),
31155            replay: io.replay_custody.map_or(
31156                PreparedReplayDescriptor::default(),
31157                PreparedReplayCustody::descriptor,
31158            ),
31159        }
31160        .with_transition(TransitionKernelPointers {
31161            logits: io.logits.device_ptr_value(),
31162            support: io.support.device_ptr_value(),
31163            receipts: io.receipts.device_ptr_value(),
31164            state: io.state.device_ptr_value(),
31165            lease: io.lease.map_or(0, TrackedCudaSlice::device_ptr_value),
31166            text: io
31167                .text
31168                .map_or(TextBinding::default(), TextBindingStorage::descriptor),
31169            policy,
31170            model_work: io
31171                .model_work
31172                .map_or(ModelWorkInput::default(), PreparedModelWork::descriptor),
31173        })
31174    }
31175
31176    #[cfg(feature = "semantic-policy")]
31177    fn retained_policy_descriptor(policy: &PolicyBuffers) -> PolicyDescriptor {
31178        let parameter = |offset: usize| policy.parameters.device_ptr_value() + (offset * 4) as u64;
31179        let mut retained_offset = 0usize;
31180        let fields = std::array::from_fn(|i| {
31181            let field = &policy.layout.fields[i];
31182            let result = PolicyField {
31183                embeddings: if field.embeddings.is_empty() {
31184                    0
31185                } else {
31186                    parameter(field.embeddings.start)
31187                },
31188                biases: if field.biases.is_empty() {
31189                    0
31190                } else {
31191                    parameter(field.biases.start)
31192                },
31193                cardinality: field.cardinality as u32,
31194                null_category: field.null_category.map_or(-1, |index| index as i32),
31195                retained_offset: retained_offset as u64,
31196            };
31197            retained_offset += field.cardinality;
31198            result
31199        });
31200        PolicyDescriptor {
31201            z: parameter(policy.layout.z.start),
31202            recurrence: parameter(policy.layout.recurrence.start),
31203            positions: parameter(policy.layout.positions.start),
31204            hidden: policy.hidden.device_ptr_value(),
31205            scores: policy.scores.device_ptr_value(),
31206            recurrent: policy.recurrent.device_ptr_value(),
31207            retained_scores: policy.retained_scores.device_ptr_value(),
31208            retained_score_stride: policy.layout.retained_score_stride() as u64,
31209            final_masks: policy.final_masks.device_ptr_value(),
31210            active_sets: policy.active_sets.device_ptr_value(),
31211            pwl_cells: policy.pwl_cells.device_ptr_value(),
31212            selected_score_vjps: policy.selected_score_vjps.device_ptr_value(),
31213            component_baselines: policy.component_baselines.device_ptr_value(),
31214            fields,
31215            numerical: policy.numerical.descriptor(policy.layout.parameter_cells),
31216        }
31217    }
31218
31219    fn validate_ranges(&self) -> Result<(), SemanticTransitionError> {
31220        self.validate_ranges_with(&self.transition_kernel_io())
31221    }
31222
31223    fn validate_ranges_with(
31224        &self,
31225        io: &TransitionKernelIo<'_>,
31226    ) -> Result<(), SemanticTransitionError> {
31227        let d = self.descriptor_with(io);
31228        let mut ranges = vec![
31229            (d.logits, (io.logits.len() * 4) as u64),
31230            (d.support, io.support.len() as u64),
31231            (d.scratch, SCRATCH_BYTES as u64),
31232            (
31233                d.receipts,
31234                (io.receipts.len() * size_of::<SemanticTransitionReceipt>()) as u64,
31235            ),
31236            (d.state, size_of::<DeviceState>() as u64),
31237            (
31238                d.components,
31239                (COMPONENT_COUNT * size_of::<SemanticComponent>()) as u64,
31240            ),
31241            (d.codebooks, (self.codebooks.words.len() * 8) as u64),
31242            (d.arena[0], d.arena[6] * 8),
31243        ];
31244        if let Some((_, device)) = &self.task {
31245            ranges.push((device.device_ptr_value(), (device.len() * 8) as u64));
31246        }
31247        #[cfg(feature = "semantic-policy")]
31248        {
31249            if let Some(policy) = io.policy {
31250                for buffer in policy.numerical.buffers() {
31251                    ranges.push((buffer.device_ptr_value(), (buffer.len() * 8) as u64));
31252                }
31253                for buffer in [
31254                    &policy.parameters,
31255                    &policy.hidden,
31256                    &policy.scores,
31257                    &policy.retained_scores,
31258                    &policy.recurrent,
31259                    &policy.component_baselines,
31260                ] {
31261                    if !buffer.is_empty() {
31262                        ranges.push((buffer.device_ptr_value(), (buffer.len() * 4) as u64));
31263                    }
31264                }
31265                for buffer in [&policy.final_masks, &policy.active_sets] {
31266                    if !buffer.is_empty() {
31267                        ranges.push((buffer.device_ptr_value(), buffer.len() as u64));
31268                    }
31269                }
31270                ranges.push((
31271                    policy.pwl_cells.device_ptr_value(),
31272                    (policy.pwl_cells.len() * size_of::<SemanticPolicyPwlCell>()) as u64,
31273                ));
31274                ranges.push((
31275                    policy.selected_score_vjps.device_ptr_value(),
31276                    (policy.selected_score_vjps.len() * size_of::<SemanticPolicySelectedScoreVjp>())
31277                        as u64,
31278                ));
31279            }
31280        }
31281        if let Some(text) = io.text {
31282            for input in &text.inputs {
31283                if let Some(source) = &input.source {
31284                    ranges.push((input.data, source.len() as u64));
31285                }
31286            }
31287        }
31288        if let Some(selection) = io.training_selection {
31289            ranges.push((
31290                *selection.device_ptr(),
31291                size_of::<SemanticTrainingViewSelection>() as u64,
31292            ));
31293        }
31294        if let Some(update) = io.model_update {
31295            ranges.push((
31296                update.bindings.device_ptr_value(),
31297                (update.bindings.len() * size_of::<ModelUpdateBinding>()) as u64,
31298            ));
31299            if let Some(output) = &update.output {
31300                for allocation in &output.allocations {
31301                    if let Some(source) = &allocation.source {
31302                        ranges.push((allocation.data, source.len() as u64));
31303                    }
31304                }
31305                if let Some(source) = &output.admissibility.source {
31306                    ranges.push((output.admissibility.data, source.len() as u64));
31307                }
31308                if let Some(source) = &output.baseline_logits.source {
31309                    ranges.push((output.baseline_logits.data, source.len() as u64));
31310                }
31311                if let Some(source) = &output.candidate_logits.source {
31312                    ranges.push((output.candidate_logits.data, source.len() as u64));
31313                }
31314            }
31315        }
31316        disjoint_ranges(&ranges)
31317    }
31318
31319    fn kernel_recorder(&self) -> LaunchRecorder {
31320        self.kernel_recorder_with(&self.transition_kernel_io())
31321    }
31322
31323    fn kernel_recorder_with(&self, io: &TransitionKernelIo<'_>) -> LaunchRecorder {
31324        // Replay custody is never exposed as a numerical alias. Retain all
31325        // original private destinations for the complete captured transaction.
31326        let mut recorder = self.domain.new_strict_recorder();
31327        recorder.read(io.logits);
31328        recorder.read(io.support);
31329        if let Some(work) = io.model_work {
31330            recorder.read(&work.device);
31331            recorder.read(&work.actual);
31332        }
31333        if let Some(custody) = io.replay_custody {
31334            custody.record(&mut recorder);
31335        }
31336        if let Some(update) = io.model_update {
31337            update.record(&mut recorder);
31338        }
31339        recorder.write(&self.scratch);
31340        recorder.write(io.receipts);
31341        recorder.read_write(io.state);
31342        recorder.read(&self.device_codebooks);
31343        recorder.read(&self.device_components);
31344        if let Some((_, device)) = &self.task {
31345            recorder.read(device);
31346        }
31347        #[cfg(feature = "semantic-policy")]
31348        if let Some(policy) = io.policy {
31349            policy.numerical.record(&mut recorder);
31350            recorder.read(&policy.parameters);
31351            recorder.read(&policy.component_baselines);
31352            recorder.write(&policy.hidden);
31353            recorder.write(&policy.scores);
31354            recorder.write(&policy.retained_scores);
31355            recorder.write(&policy.final_masks);
31356            recorder.write(&policy.active_sets);
31357            recorder.write(&policy.pwl_cells);
31358            recorder.write(&policy.selected_score_vjps);
31359            recorder.write(&policy.recurrent);
31360        }
31361        self.graph.record_transition(&mut recorder);
31362        if let Some(publication) = &self.publication {
31363            publication.record(&mut recorder);
31364        }
31365        if let Some(lease) = io.lease {
31366            recorder.read(lease);
31367        }
31368        if let Some(text) = io.text {
31369            text.record(&mut recorder);
31370        }
31371        if let Some(selection) = io.training_selection {
31372            recorder.read(selection);
31373        }
31374        recorder
31375    }
31376}
31377
31378fn enqueue_recorded<E: fmt::Display>(
31379    domain: &ResidentExecutionDomain,
31380    poisoned: &mut bool,
31381    recorder: LaunchRecorder,
31382    operation: impl FnOnce(&CudaEnqueue<'_>) -> Result<(), E>,
31383) -> Result<(), SemanticTransitionError> {
31384    // SAFETY: all call sites register exactly the allocations used on the supplied
31385    // stream. Poison is armed before the may-enqueue boundary, including unwinding;
31386    // only a successful consuming commit permits reuse.
31387    let result = unsafe {
31388        domain.enqueue(recorder, |stream| {
31389            *poisoned = true;
31390            operation(stream)
31391        })
31392    };
31393    let enqueued = result.map_err(|e| {
31394        if matches!(
31395            &e,
31396            LaunchEnqueueError::Operation(_) | LaunchEnqueueError::OperationAndCleanup { .. }
31397        ) {
31398            *poisoned = true;
31399        }
31400        runtime_error("enqueue", e)
31401    })?;
31402    enqueued
31403        .commit()
31404        .map_err(|e| runtime_error("enqueue commit", e))?;
31405    *poisoned = false;
31406    Ok(())
31407}
31408
31409fn wait_on_stream<E: fmt::Display>(
31410    stream: &CudaStream,
31411    poisoned: &mut bool,
31412    waits: &mut u64,
31413    operation: &'static str,
31414    wait: impl FnOnce(&CudaStream) -> Result<(), E>,
31415) -> Result<(), SemanticTransitionError> {
31416    *waits += 1;
31417    wait(stream).map_err(|e| {
31418        *poisoned = true;
31419        runtime_error(operation, e)
31420    })
31421}
31422
31423fn validate_bound_inputs(
31424    components: &[SemanticComponent],
31425    rng: SemanticRngBinding,
31426    inputs: &[SemanticComponentInput],
31427) -> Result<(), SemanticTransitionError> {
31428    let invalid = |detail: &str| SemanticTransitionError::InvalidInput {
31429        detail: detail.into(),
31430    };
31431    if rng.stream_serial >= 1u64 << 56 {
31432        return Err(invalid("stream serial exceeds 56 bits"));
31433    }
31434    if inputs.len() != COMPONENT_COUNT {
31435        return Err(invalid("input roster must contain exactly 136 components"));
31436    }
31437    for (component, input) in components.iter().zip(inputs) {
31438        if input.logits.len() != component.cardinality as usize
31439            || input.product_support.len() != input.logits.len()
31440        {
31441            return Err(invalid("logits/support shape differs from the catalogue"));
31442        }
31443        if input.product_support.iter().any(|&m| m > 1) {
31444            return Err(invalid("product support must be binary"));
31445        }
31446        debug_assert!(component.is_text() || component.kind == COMPONENT_KIND_EDIT as u32);
31447        let has_support = input.product_support.contains(&1);
31448        if !has_support {
31449            return Err(invalid("empty product support"));
31450        }
31451        if input
31452            .logits
31453            .iter()
31454            .zip(&input.product_support)
31455            .any(|(&z, &m)| m == 1 && !z.is_finite())
31456        {
31457            return Err(invalid("legal logits must be finite FP32"));
31458        }
31459    }
31460    Ok(())
31461}
31462
31463fn disjoint_ranges(ranges: &[(u64, u64)]) -> Result<(), SemanticTransitionError> {
31464    for (i, &(start, len)) in ranges.iter().enumerate() {
31465        let end = start
31466            .checked_add(len)
31467            .filter(|_| start != 0 && len != 0)
31468            .ok_or(SemanticTransitionError::OverlappingInputs)?;
31469        for &(other, other_len) in &ranges[..i] {
31470            let other_end = other
31471                .checked_add(other_len)
31472                .ok_or(SemanticTransitionError::OverlappingInputs)?;
31473            if start < other_end && other < end {
31474                return Err(SemanticTransitionError::OverlappingInputs);
31475            }
31476        }
31477    }
31478    Ok(())
31479}
31480
31481#[cfg(test)]
31482mod tests {
31483    #[test]
31484    fn raw_prefix_export_retains_the_original_input_seal() {
31485        let range = PublicationRange {
31486            role: 1,
31487            index: 0,
31488            generation: 1,
31489            length_bytes: 64,
31490            logical_begin: 0,
31491            logical_end: 1,
31492            ..PublicationRange::default()
31493        };
31494        let input = StepInputPlan {
31495            role: 1,
31496            index: 0,
31497            layout: committed_prefix_layout(&range, 4).unwrap(),
31498            banks: [
31499                StepInputBankPlan {
31500                    storage_slot: 0,
31501                    span: 0..256,
31502                },
31503                StepInputBankPlan {
31504                    storage_slot: 0,
31505                    span: 0..256,
31506                },
31507            ],
31508        };
31509        let raw = publication_record_layout(&range);
31510        let exported = publication_export_span(&range, &raw, 256).unwrap();
31511        assert_eq!(exported, 0..64);
31512        assert!(step_input_alias_matches(
31513            &input,
31514            &range,
31515            4096,
31516            256,
31517            (raw, 0, 0, 4096, exported.len())
31518        ));
31519        assert!(!step_input_alias_matches(
31520            &input,
31521            &range,
31522            4096,
31523            256,
31524            (raw, 0, 0, 4097, exported.len())
31525        ));
31526        assert!(!step_input_alias_matches(
31527            &input,
31528            &range,
31529            4096,
31530            256,
31531            (raw, 0, 1, 4096, exported.len())
31532        ));
31533        assert!(!step_input_alias_matches(
31534            &input,
31535            &range,
31536            4096,
31537            256,
31538            (raw, 0, 0, 4096, 128)
31539        ));
31540        assert!(step_input_alias_matches(
31541            &input,
31542            &range,
31543            4096,
31544            256,
31545            (input.layout, 0, 1, 4096, 256)
31546        ));
31547        let empty = PublicationRange {
31548            length_bytes: 0,
31549            logical_end: 0,
31550            ..range
31551        };
31552        let raw_empty = publication_record_layout(&empty);
31553        assert_eq!(
31554            publication_export_span(&empty, &raw_empty, 256).unwrap(),
31555            0..0
31556        );
31557        assert!(step_input_alias_matches(
31558            &input,
31559            &empty,
31560            4096,
31561            256,
31562            (raw_empty, 0, 0, 4096, 0)
31563        ));
31564    }
31565
31566    #[test]
31567    fn transition_descriptors_preserve_each_original_policy_and_outcome() {
31568        use super::*;
31569        let shared = Descriptor {
31570            logits: 0,
31571            support: 0,
31572            scratch: 8,
31573            receipts: 0,
31574            state: 0,
31575            components: 16,
31576            codebooks: 24,
31577            arena: [32; 7],
31578            policy: PolicyDescriptor::default(),
31579            backward: PolicyBackward::default(),
31580            task: 40,
31581            task_words: 66,
31582            task_return_bound: 0,
31583            publication: PublicationCommand {
31584                control: 48,
31585                lease: 0,
31586                operation: 0,
31587            },
31588            text: TextBinding::default(),
31589            model_work: ModelWorkInput::default(),
31590            replay: PreparedReplayDescriptor::default(),
31591        };
31592        let original = |base| TransitionKernelPointers {
31593            logits: base,
31594            support: base + 8,
31595            receipts: base + 16,
31596            state: base + 24,
31597            lease: base + 32,
31598            text: TextBinding {
31599                rows: base + 40,
31600                count: base + 48,
31601                selected: base + 56,
31602            },
31603            policy: PolicyDescriptor {
31604                z: base + 64,
31605                recurrent: base + 72,
31606                ..PolicyDescriptor::default()
31607            },
31608            model_work: ModelWorkInput {
31609                events: base + 80,
31610                count: base + 88,
31611                bound: base + 96,
31612            },
31613        };
31614        let first = shared.with_transition(original(1024));
31615        let second = shared.with_transition(original(2048));
31616        for (descriptor, base) in [(first, 1024), (second, 2048)] {
31617            assert_eq!(
31618                (
31619                    descriptor.logits,
31620                    descriptor.support,
31621                    descriptor.receipts,
31622                    descriptor.state
31623                ),
31624                (base, base + 8, base + 16, base + 24)
31625            );
31626            assert_eq!(
31627                (
31628                    descriptor.policy.z,
31629                    descriptor.policy.recurrent,
31630                    descriptor.publication.lease
31631                ),
31632                (base + 64, base + 72, base + 32)
31633            );
31634            assert_eq!(
31635                (
31636                    descriptor.text.rows,
31637                    descriptor.text.count,
31638                    descriptor.text.selected
31639                ),
31640                (base + 40, base + 48, base + 56)
31641            );
31642            assert_eq!(
31643                (
31644                    descriptor.model_work.events,
31645                    descriptor.model_work.count,
31646                    descriptor.model_work.bound
31647                ),
31648                (base + 80, base + 88, base + 96)
31649            );
31650            assert_eq!(
31651                (
31652                    descriptor.scratch,
31653                    descriptor.components,
31654                    descriptor.codebooks,
31655                    descriptor.task
31656                ),
31657                (8, 16, 24, 40)
31658            );
31659            assert_eq!(descriptor.publication.control, 48);
31660        }
31661        assert_ne!(first.policy.recurrent, second.policy.recurrent);
31662        assert_ne!(first.receipts, second.receipts);
31663    }
31664
31665    const COLD_CAPACITY: SemanticSegmentColdCapacity = SemanticSegmentColdCapacity {
31666        tensor_content_capacity: 1,
31667        model_work_capacity: 1,
31668        segment_capacity_bytes: 1,
31669        other_external_cuda_bytes: 0,
31670    };
31671
31672    #[test]
31673    fn prepared_schedule_preserves_each_requested_mode_until_recording() {
31674        let issuer = Arc::new(());
31675        let schedule = [
31676            SemanticTransitionKind::Proposal,
31677            SemanticTransitionKind::Recompute,
31678            SemanticTransitionKind::Proposal,
31679        ];
31680        let mut build = PreparedSegmentState::new(
31681            Arc::clone(&issuer),
31682            vec![4, 5, 6],
31683            schedule.into_iter(),
31684            COLD_CAPACITY,
31685        )
31686        .unwrap();
31687        let steps = build.handles().unwrap();
31688        assert!(build.enter(&steps[1], &issuer).is_err());
31689        for (step, expected) in steps.iter().zip(schedule) {
31690            assert_eq!(build.requested_kind(step, &issuer).unwrap(), expected);
31691            assert_eq!(build.enter(step, &issuer).unwrap(), expected);
31692            build.leave(step, &issuer).unwrap();
31693        }
31694        build.finish().unwrap();
31695        build.submit().unwrap();
31696        assert!(build.submit().is_err());
31697        assert!(build.requested_kind(&steps[0], &Arc::new(())).is_err());
31698        assert!(PreparedSegmentState::new(
31699            Arc::clone(&issuer),
31700            vec![9],
31701            schedule.into_iter(),
31702            COLD_CAPACITY
31703        )
31704        .is_err());
31705        assert!(PreparedSegmentState::new(
31706            issuer,
31707            vec![9],
31708            std::iter::once(SemanticTransitionKind::Drain),
31709            COLD_CAPACITY,
31710        )
31711        .is_err());
31712    }
31713
31714    #[test]
31715    fn prepared_step_scope_rejects_foreign_owners_and_out_of_order_recording() {
31716        let issuer = Arc::new(());
31717        let mut build = PreparedSegmentState::new(
31718            Arc::clone(&issuer),
31719            vec![4, 5],
31720            [
31721                SemanticTransitionKind::Proposal,
31722                SemanticTransitionKind::Proposal,
31723            ]
31724            .into_iter(),
31725            COLD_CAPACITY,
31726        )
31727        .unwrap();
31728        let steps = build.handles().unwrap();
31729        assert!(build.check(&steps[0], &issuer, false).is_ok());
31730        assert!(build.check(&steps[0], &Arc::new(()), false).is_err());
31731        assert!(build.enter(&steps[1], &issuer).is_err());
31732        build.enter(&steps[0], &issuer).unwrap();
31733        assert!(build.check(&steps[0], &issuer, true).is_ok());
31734        assert!(build.check(&steps[1], &issuer, true).is_err());
31735        assert!(build.finish().is_err());
31736        build.leave(&steps[0], &issuer).unwrap();
31737        assert!(build.enter(&steps[0], &issuer).is_err());
31738        build.enter(&steps[1], &issuer).unwrap();
31739        build.leave(&steps[1], &issuer).unwrap();
31740        build.finish().unwrap();
31741        assert!(build.check(&steps[0], &issuer, false).is_err());
31742        assert!(
31743            PreparedSegmentState::new(issuer, Vec::new(), std::iter::empty(), COLD_CAPACITY)
31744                .is_err()
31745        );
31746    }
31747    use super::*;
31748    use xlog_core::MemoryBudget;
31749
31750    #[test]
31751    fn publication_role_roster_preserves_every_required_owner() {
31752        let mut counts = [1; 55];
31753        counts[15] = 3;
31754        assert!(validate_publication_counts(&counts).is_ok());
31755        for code in [1usize, 14, 17, 38, 47, 55] {
31756            let mut omitted = counts;
31757            omitted[code - 1] = 0;
31758            assert!(validate_publication_counts(&omitted).is_err());
31759        }
31760        counts[18] = 0;
31761        counts[19] = 0;
31762        counts[20] = 0;
31763        counts[23] = 0;
31764        counts[24] = 0;
31765        assert!(validate_publication_counts(&counts).is_ok());
31766        counts[50] = 2;
31767        assert!(validate_publication_counts(&counts).is_err());
31768        assert!(SemanticStateRole::from_code(0).is_none());
31769        assert!(SemanticStateRole::from_code(56).is_none());
31770        assert!(SemanticStateRole::from_code(u64::MAX).is_none());
31771        for code in 1..=55 {
31772            assert_eq!(SemanticStateRole::from_code(code).unwrap() as u64, code);
31773        }
31774    }
31775
31776    #[test]
31777    fn prefix_snapshot_copy_respects_owned_capacity_strides() {
31778        let source = SemanticTensorLayout {
31779            role: 4,
31780            index: 0,
31781            element_bytes: 2,
31782            scalar_type: 4,
31783            rank: 4,
31784            logical_axis: 2,
31785            dimensions: [1, 2, 3, 4],
31786            strides_bytes: [48, 24, 8, 2],
31787        };
31788        let destination = prefix_capacity_layout(source, 8).unwrap();
31789        assert_eq!(destination.dimensions, [1, 2, 8, 4]);
31790        assert_eq!(destination.strides_bytes, [128, 64, 8, 2]);
31791        assert_eq!(
31792            tensor_copy_plan(&source, &destination).unwrap(),
31793            [(0, 0, 24), (24, 64, 24)]
31794        );
31795        let mut empty = source;
31796        empty.dimensions[2] = 0;
31797        assert!(tensor_copy_plan(&empty, &destination).unwrap().is_empty());
31798    }
31799
31800    #[cfg(feature = "semantic-policy")]
31801    #[test]
31802    fn policy_score_cotangent_admission_requires_exact_fp64_metadata() {
31803        use crate::dlpack::{DLDataType, DLDevice, DLTensor, K_DLCUDA, K_DLFLOAT, K_DLINT};
31804
31805        let mut shape = [COMPONENT_COUNT as i64];
31806        let mut stride = [1i64];
31807        // This exercises the production metadata boundary only: the address is
31808        // never dereferenced and no CUDA provider or managed owner is created.
31809        let mut tensor = DLTensor {
31810            data: 4096usize as *mut std::ffi::c_void,
31811            device: DLDevice {
31812                device_type: K_DLCUDA,
31813                device_id: 0,
31814            },
31815            ndim: 1,
31816            dtype: DLDataType {
31817                code: K_DLFLOAT,
31818                bits: 64,
31819                lanes: 1,
31820            },
31821            shape: shape.as_mut_ptr(),
31822            strides: std::ptr::null_mut(),
31823            byte_offset: 0,
31824        };
31825        // SAFETY: the local shape/stride arrays outlive each metadata-only call.
31826        let admit = |tensor: &DLTensor| unsafe { policy_score_cotangent_metadata(tensor, 0) };
31827        assert_eq!(
31828            admit(&tensor).unwrap(),
31829            (4096, COMPONENT_COUNT * size_of::<f64>())
31830        );
31831        tensor.strides = stride.as_mut_ptr();
31832        tensor.byte_offset = 8;
31833        assert_eq!(
31834            admit(&tensor).unwrap(),
31835            (4104, COMPONENT_COUNT * size_of::<f64>())
31836        );
31837        tensor.byte_offset = 0;
31838        tensor.dtype.code = K_DLINT;
31839        assert!(
31840            admit(&tensor).is_err(),
31841            "Int64 cells must not be bitcast as FP64 cotangents"
31842        );
31843        tensor.dtype.code = K_DLFLOAT;
31844        tensor.dtype.bits = 32;
31845        assert!(admit(&tensor).is_err());
31846        tensor.dtype.bits = 64;
31847        tensor.dtype.lanes = 2;
31848        assert!(admit(&tensor).is_err());
31849        tensor.dtype.lanes = 1;
31850        for extent in [0, COMPONENT_COUNT as i64 - 1, COMPONENT_COUNT as i64 + 1] {
31851            shape[0] = extent;
31852            assert!(admit(&tensor).is_err());
31853        }
31854        shape[0] = COMPONENT_COUNT as i64;
31855        tensor.shape = shape.as_mut_ptr();
31856        stride[0] = 2;
31857        assert!(matches!(
31858            admit(&tensor),
31859            Err(SemanticTransitionError::InvalidInput { .. })
31860        ));
31861        stride[0] = 1;
31862        tensor.strides = stride.as_mut_ptr();
31863        tensor.ndim = 2;
31864        assert!(admit(&tensor).is_err());
31865        tensor.ndim = 1;
31866        tensor.device.device_id = 1;
31867        assert!(admit(&tensor).is_err());
31868        tensor.device.device_id = 0;
31869        tensor.byte_offset = 4;
31870        assert!(admit(&tensor).is_err());
31871    }
31872
31873    #[cfg(feature = "semantic-policy")]
31874    #[test]
31875    #[ignore = "requires an explicitly authorized CUDA runtime"]
31876    fn policy_dlpack_binding_snapshots_actual_producer_allocations() {
31877        policy_dlpack_binding_fixture(PolicyFixtureCompletion::Backward);
31878    }
31879
31880    #[cfg(feature = "semantic-policy")]
31881    #[test]
31882    #[ignore = "requires an explicitly authorized CUDA runtime"]
31883    fn policy_inference_finish_retires_published_and_refused_original_owners() {
31884        for completion in [
31885            PolicyFixtureCompletion::Inference,
31886            PolicyFixtureCompletion::NumericalRefusal,
31887        ] {
31888            policy_dlpack_binding_fixture(completion);
31889        }
31890    }
31891
31892    #[cfg(feature = "semantic-policy")]
31893    #[derive(Clone, Copy)]
31894    enum PolicyFixtureCompletion {
31895        Backward,
31896        Inference,
31897        NumericalRefusal,
31898    }
31899
31900    #[cfg(feature = "semantic-policy")]
31901    fn policy_dlpack_binding_fixture(completion: PolicyFixtureCompletion) {
31902        use crate::memory::CudaColumn;
31903        use xlog_core::{ScalarType, Schema};
31904
31905        // The complete catalogue's actor/full numerical buffers exceed 3 GiB.
31906        let provider = Arc::new(
31907            crate::CudaProviderBuilder::new(0, MemoryBudget::with_limit(4 * 1024 * 1024 * 1024))
31908                .with_stream_capacity(1)
31909                .build()
31910                .unwrap(),
31911        );
31912        let runtime = Arc::clone(provider.memory().runtime().unwrap());
31913        let id = runtime.stream_pool().acquire().unwrap();
31914        let stream = runtime.stream_pool().resolve(id).unwrap();
31915        let domain = provider
31916            .bind_resident_execution_domain(runtime, id, stream)
31917            .unwrap();
31918        let mut session =
31919            super::text_parent_tests::publication_test_session(Arc::clone(&provider), &domain);
31920        session
31921            .bind_parent(super::text_parent_tests::publication_test_parent(&provider))
31922            .unwrap();
31923        let mut parent = session.acquire().unwrap();
31924        session
31925            .admit_transition(&parent, SemanticTransitionKind::Proposal)
31926            .unwrap();
31927        let (continuation, witness) =
31928            super::text_parent_tests::publication_test_continuation_with_numerical_admissibility(
31929                &mut session,
31930                &parent,
31931                &provider,
31932                u8::from(!matches!(
31933                    completion,
31934                    PolicyFixtureCompletion::NumericalRefusal
31935                )),
31936            );
31937        session
31938            .bind_continuation(&parent, continuation, &witness, 1)
31939            .unwrap();
31940        let witness = if matches!(completion, PolicyFixtureCompletion::Backward) {
31941            drop(witness);
31942            None
31943        } else {
31944            Some(witness)
31945        };
31946        let layout = session.policy_layout().unwrap();
31947        let mut logits = provider
31948            .memory()
31949            .alloc::<f32>(32 * TEXT_CARDINALITY)
31950            .unwrap();
31951        let mut support = provider
31952            .memory()
31953            .alloc::<u8>(session.codebooks.input_cells)
31954            .unwrap();
31955        let mut parameters = provider
31956            .memory()
31957            .alloc::<f32>(layout.parameter_cells)
31958            .unwrap();
31959        let mut component_baselines = provider.memory().alloc::<f32>(COMPONENT_COUNT).unwrap();
31960        provider
31961            .htod_sync_copy_into_tracked(&vec![2.0; logits.len()], &mut logits)
31962            .unwrap();
31963        provider
31964            .htod_sync_copy_into_tracked(&vec![1u8; support.len()], &mut support)
31965            .unwrap();
31966        provider
31967            .htod_sync_copy_into_tracked(&vec![3.0; parameters.len()], &mut parameters)
31968            .unwrap();
31969        provider
31970            .htod_sync_copy_into_tracked(
31971                &vec![0.5; component_baselines.len()],
31972                &mut component_baselines,
31973            )
31974            .unwrap();
31975        let original_logit = logits.view().slice(0..1);
31976        let original_support = support.view().slice(0..1);
31977        let original_parameter = parameters.view().slice(0..1);
31978        let layouts = policy_numerical_producer_layouts(
31979            session.codebooks.input_cells,
31980            layout.parameter_cells,
31981        )
31982        .unwrap();
31983        let mut sources = vec![
31984            logits.into_bytes().view(),
31985            support.view(),
31986            parameters.into_bytes().view(),
31987            component_baselines.into_bytes().view(),
31988        ];
31989        for (index, numerical_layout) in layouts.iter().enumerate().skip(4) {
31990            let cells = numerical_layout.dimensions[..numerical_layout.rank as usize]
31991                .iter()
31992                .product::<u64>() as usize;
31993            // These producer inputs are fixed literal FP32 values, not computed
31994            // model outputs. Their original real domains have zero error.
31995            let values = match index {
31996                4 | 5 => vec![0.0; cells],
31997                6..=8 => {
31998                    let magnitude = [3.0, 2.0, 0.5][index - 6];
31999                    [magnitude, 0.0, 0.0, magnitude].repeat(cells / 4)
32000                }
32001                _ => unreachable!("five original numerical inputs"),
32002            };
32003            let mut numerical = provider.memory().alloc::<f64>(cells).unwrap();
32004            provider
32005                .htod_sync_copy_into_tracked(&values, &mut numerical)
32006                .unwrap();
32007            sources.push(numerical.into_bytes().view());
32008        }
32009        let publication = Arc::clone(session.publication.as_ref().unwrap());
32010        let export = |view: DeviceMemoryView<u8>, tensor_layout: SemanticTensorLayout| {
32011            let rank = tensor_layout.rank as usize;
32012            export_owned_allocation(
32013                view,
32014                tensor_layout.dimensions[..rank]
32015                    .iter()
32016                    .map(|&n| n as i64)
32017                    .collect(),
32018                tensor_layout.strides_bytes[..rank]
32019                    .iter()
32020                    .map(|&n| (n / tensor_layout.element_bytes) as i64)
32021                    .collect(),
32022                (
32023                    if tensor_layout.scalar_type == 8 { 6 } else { 2 },
32024                    (tensor_layout.element_bytes * 8) as u8,
32025                ),
32026                provider.device().ordinal() as i32,
32027                Arc::new(()),
32028                Arc::clone(&publication),
32029                None,
32030                None,
32031            )
32032        };
32033        let capture = sources
32034            .iter()
32035            .cloned()
32036            .zip(layouts)
32037            .map(|(view, layout)| SemanticTensorInput {
32038                tensor: export(view, layout),
32039                layout,
32040                logical_begin: 0,
32041                logical_end: 0,
32042                native_allocation: None,
32043            })
32044            .collect();
32045        let policy_witness = session.capture_tensor_content(&parent, capture, 1).unwrap();
32046        let producers = sources
32047            .into_iter()
32048            .zip(layouts)
32049            .map(|(view, layout)| export(view, layout))
32050            .collect::<Vec<_>>();
32051        let [logits, support, parameters, component_baselines, numerical @ ..]:
32052            [DlpackManagedTensor; 9] = producers.try_into().ok().unwrap();
32053        let rng = session.continuation_rng(&parent).unwrap();
32054        let original_components = session.device_components.device_ptr_value();
32055        let original_codebooks = session.device_codebooks.device_ptr_value();
32056        let before_policy_binding = session.host_io_stats();
32057        session
32058            .bind_policy_dlpack(
32059                &parent,
32060                session.binding(),
32061                rng,
32062                logits,
32063                support,
32064                parameters,
32065                component_baselines,
32066                numerical,
32067                &policy_witness,
32068                1,
32069            )
32070            .unwrap();
32071        assert_eq!(
32072            session.host_io_stats(),
32073            before_policy_binding,
32074            "policy binding must not upload state or immutable catalogue metadata"
32075        );
32076        // Original captured producers remain immutable through final use.
32077        // Distinct device banks prove that the policy owns its snapshots.
32078        let policy = session.policy.as_ref().unwrap();
32079        assert_ne!(
32080            policy.text_logits.device_ptr_value(),
32081            *original_logit.device_ptr()
32082        );
32083        assert_ne!(
32084            session.support.device_ptr_value(),
32085            *original_support.device_ptr()
32086        );
32087        assert_ne!(
32088            policy.parameters.device_ptr_value(),
32089            *original_parameter.device_ptr()
32090        );
32091        let read = |view: crate::memory::DeviceMemoryView<f32>| {
32092            provider.device().inner().dtoh_sync_copy(&view).unwrap()[0]
32093        };
32094        assert_eq!(
32095            read(
32096                session
32097                    .policy
32098                    .as_ref()
32099                    .unwrap()
32100                    .text_logits
32101                    .view()
32102                    .slice(0..1)
32103            ),
32104            2.0
32105        );
32106        assert_eq!(
32107            read(
32108                session
32109                    .policy
32110                    .as_ref()
32111                    .unwrap()
32112                    .parameters
32113                    .view()
32114                    .slice(0..1)
32115            ),
32116            3.0
32117        );
32118        assert_eq!(
32119            provider
32120                .device()
32121                .inner()
32122                .dtoh_sync_copy(&session.support.view().slice(0..1))
32123                .unwrap(),
32124            [1u8]
32125        );
32126        assert_eq!(session.rng, Some(rng));
32127        // An unconsumed forward retains its real continuation witness.
32128        if matches!(completion, PolicyFixtureCompletion::Backward) {
32129            assert!(session.release(&mut parent, &[1]).is_err());
32130        }
32131        session.capture().unwrap();
32132        let before_launch = session.host_io_stats();
32133        session.launch().unwrap();
32134        assert_eq!(session.host_io_stats(), before_launch);
32135        let outcome = session.observe(0).unwrap();
32136        assert_eq!(
32137            session.device_components.device_ptr_value(),
32138            original_components
32139        );
32140        assert_eq!(
32141            session.device_codebooks.device_ptr_value(),
32142            original_codebooks
32143        );
32144        assert_eq!(
32145            *session.policy_tapes[0].components.device_ptr(),
32146            original_components
32147        );
32148        assert_eq!(
32149            *session.policy_tapes[0].codebooks.device_ptr(),
32150            original_codebooks
32151        );
32152        match (&completion, &outcome) {
32153            (
32154                PolicyFixtureCompletion::NumericalRefusal,
32155                SemanticTransitionOutcome::Refused(
32156                    SemanticTransitionRefusal::NonFinitePolicyInput { completed_draws: 0 },
32157                ),
32158            ) => {}
32159            (
32160                PolicyFixtureCompletion::Backward | PolicyFixtureCompletion::Inference,
32161                SemanticTransitionOutcome::Published(_),
32162            ) => {}
32163            _ => panic!("policy fixture returned the wrong native outcome: {outcome:?}"),
32164        }
32165        let parent_identity = session.retained_step_identity(&parent).unwrap();
32166        session.release_published_reader(&mut parent, &[1]).unwrap();
32167        assert!(!parent.active && !session.readers.contains_key(&parent.token));
32168        assert_eq!(
32169            session.retained_step_identity(&parent).unwrap(),
32170            parent_identity
32171        );
32172        assert!(session.published_identity(&parent).is_err());
32173        if !matches!(completion, PolicyFixtureCompletion::Backward) {
32174            let mut foreign_session =
32175                super::text_parent_tests::publication_test_session(Arc::clone(&provider), &domain);
32176            foreign_session
32177                .bind_parent(super::text_parent_tests::publication_test_parent(&provider))
32178                .unwrap();
32179            let mut foreign_parent = foreign_session.acquire().unwrap();
32180            let parent_identity = session.retained_step_identity(&parent).unwrap();
32181            let witness_owners = Arc::strong_count(&session.steps[&parent.token].content_witnesses);
32182            assert!(witness_owners > 1);
32183            assert_eq!(session.policy_tapes.len(), 1);
32184            assert_eq!(session.policy_tapes[0].invocation, rng);
32185            let before_final_use = session.host_io_stats();
32186            for invalid_stream in [0, 2] {
32187                assert!(session
32188                    .finish_policy_invocation(&parent, rng, invalid_stream)
32189                    .is_err());
32190                assert_eq!(session.policy_tapes.len(), 1);
32191                assert_eq!(session.policy_tapes[0].invocation, rng);
32192                assert_eq!(
32193                    Arc::strong_count(&session.steps[&parent.token].content_witnesses),
32194                    witness_owners
32195                );
32196            }
32197            assert!(session
32198                .finish_policy_invocation(&foreign_parent, rng, 1)
32199                .is_err());
32200            assert_eq!(session.policy_tapes.len(), 1);
32201            assert_eq!(session.policy_tapes[0].invocation, rng);
32202            assert_eq!(
32203                Arc::strong_count(&session.steps[&parent.token].content_witnesses),
32204                witness_owners
32205            );
32206            assert_eq!(
32207                session.retained_step_identity(&parent).unwrap(),
32208                parent_identity
32209            );
32210            session.finish_policy_invocation(&parent, rng, 1).unwrap();
32211            assert!(session.policy_tapes.is_empty());
32212            assert!(session.steps[&parent.token].consumer_streams.contains(&1));
32213            assert_eq!(
32214                session.host_io_stats(),
32215                before_final_use,
32216                "inference final use must use original device guards and stream events only"
32217            );
32218            let retained_witness_owners =
32219                Arc::strong_count(&session.steps[&parent.token].content_witnesses);
32220            assert!(retained_witness_owners > 1 && !parent.active);
32221            assert!(session.finish_policy_invocation(&parent, rng, 1).is_err());
32222            assert_eq!(
32223                Arc::strong_count(&session.steps[&parent.token].content_witnesses),
32224                retained_witness_owners
32225            );
32226            assert_eq!(
32227                session.retained_step_identity(&parent).unwrap(),
32228                parent_identity
32229            );
32230            drop(witness);
32231            drop(policy_witness);
32232            drop((original_logit, original_support, original_parameter));
32233            drop(outcome);
32234            assert_eq!(
32235                Arc::strong_count(&session.steps[&parent.token].content_witnesses),
32236                1
32237            );
32238            session.release(&mut parent, &[1]).unwrap();
32239            assert!(!parent.active && !session.readers.contains_key(&parent.token));
32240            assert!(!session.is_poisoned());
32241            foreign_session.release(&mut foreign_parent, &[1]).unwrap();
32242            return;
32243        }
32244        let mut coefficients = provider.memory().alloc::<f64>(COMPONENT_COUNT).unwrap();
32245        provider
32246            .htod_sync_copy_into_tracked(&vec![1.0f64; COMPONENT_COUNT], &mut coefficients)
32247            .unwrap();
32248        let buffer = provider
32249            .buffer_from_columns(
32250                vec![CudaColumn::Owned(coefficients.into_bytes())],
32251                COMPONENT_COUNT as u64,
32252                Schema::new(vec![("cotangent".into(), ScalarType::F64)]),
32253            )
32254            .unwrap();
32255        let cotangents = provider.to_dlpack_table(buffer).column(0).unwrap();
32256        let before_backward = session.host_io_stats();
32257        let gradients = session.backward_policy_dlpack(rng, cotangents, 1).unwrap();
32258        let parameter_pointer = gradients.parameters.device_ptr_value();
32259        let text_pointer = gradients.text_logits.device_ptr_value();
32260        let [parameters, text, numerical @ ..] = gradients.into_dlpack().unwrap();
32261        assert_eq!(
32262            session.host_io_stats(),
32263            before_backward,
32264            "backward and original gradient exports must use device guards and stream events only"
32265        );
32266        // SAFETY: both managed owners retain these complete immutable DLPack
32267        // descriptors and their real backward allocations during inspection.
32268        unsafe {
32269            let parameter_tensor = &(*parameters.as_ptr()).dl_tensor;
32270            let text_tensor = &(*text.as_ptr()).dl_tensor;
32271            assert_eq!((parameter_tensor.ndim, text_tensor.ndim), (1, 2));
32272            assert!(
32273                !parameter_tensor.shape.is_null()
32274                    && !text_tensor.shape.is_null()
32275                    && !text_tensor.strides.is_null()
32276            );
32277            assert_eq!(
32278                std::slice::from_raw_parts(parameter_tensor.shape, 1),
32279                [layout.parameter_cells as i64]
32280            );
32281            assert_eq!(
32282                std::slice::from_raw_parts(text_tensor.shape, 2),
32283                [32, TEXT_CARDINALITY as i64]
32284            );
32285            assert_eq!(
32286                std::slice::from_raw_parts(text_tensor.strides, 2),
32287                [TEXT_CARDINALITY as i64, 1]
32288            );
32289            assert_eq!(parameter_tensor.data as usize as u64, parameter_pointer);
32290            assert_eq!(text_tensor.data as usize as u64, text_pointer);
32291            assert_eq!(
32292                (
32293                    text_tensor.dtype.code,
32294                    text_tensor.dtype.bits,
32295                    text_tensor.dtype.lanes
32296                ),
32297                (2, 32, 1)
32298            );
32299            assert_eq!(
32300                text_tensor.device.device_id,
32301                provider.device().ordinal() as i32
32302            );
32303            let dimensions = [
32304                vec![1, COMPONENT_COUNT as i64],
32305                vec![layout.parameter_cells as i64, 2],
32306                vec![32, TEXT_CARDINALITY as i64, 2],
32307                vec![1, COMPONENT_COUNT as i64, 2],
32308                vec![2, layout.parameter_cells as i64, 4],
32309                vec![2, 32, TEXT_CARDINALITY as i64, 4],
32310                vec![2, 1, COMPONENT_COUNT as i64, 4],
32311            ];
32312            for (index, (tensor, dimensions)) in numerical.iter().zip(dimensions).enumerate() {
32313                let tensor = &(*tensor.as_ptr()).dl_tensor;
32314                assert_eq!(tensor.ndim as usize, dimensions.len());
32315                assert!(!tensor.shape.is_null());
32316                assert_eq!(
32317                    std::slice::from_raw_parts(tensor.shape, dimensions.len()),
32318                    dimensions
32319                );
32320                assert_eq!(
32321                    (tensor.dtype.code, tensor.dtype.bits, tensor.dtype.lanes),
32322                    (2, if index == 0 { 32 } else { 64 }, 1)
32323                );
32324                assert_eq!(tensor.device.device_id, provider.device().ordinal() as i32);
32325            }
32326        }
32327        assert!(session.steps[&parent.token].consumer_streams.contains(&1));
32328        assert!(
32329            session.release(&mut parent, &[1]).is_err(),
32330            "live gradient owners retain their original parent"
32331        );
32332        drop(parameters);
32333        drop(text);
32334        assert!(
32335            session.release(&mut parent, &[1]).is_err(),
32336            "baseline and numerical gradient owners retain their original parent"
32337        );
32338        drop(numerical);
32339        drop(witness);
32340        drop(policy_witness);
32341        drop((original_logit, original_support, original_parameter));
32342        drop(outcome);
32343        session.release(&mut parent, &[1]).unwrap();
32344        assert!(session.retained_step_identity(&parent).is_err());
32345        drop(session);
32346    }
32347
32348    #[test]
32349    fn semantic_work_accepts_refused_prefixes_and_rejects_impossible_effects() {
32350        for (edit_commands, added_supports, defined_truth_changes, valid) in [
32351            (0, 0, 0, true), // NO_EDIT only
32352            (1, 0, 0, true), // duplicate or refusal without mutation
32353            (2, 1, 0, true), // one attachment, then duplicate or refusal
32354            (2, 2, 1, true), // NEITHER -> TRUE -> BOTH
32355            (2, 2, 2, true), // edits to two already defined statements
32356            (3, 0, 0, false),
32357            (0, 1, 0, false),
32358            (1, 2, 0, false),
32359            (1, 1, 2, false),
32360            (u64::MAX, 0, 0, false),
32361        ] {
32362            let work = SemanticTransitionWork {
32363                edit_commands,
32364                added_supports,
32365                defined_truth_changes,
32366            };
32367            assert_eq!(work.is_valid(false), valid, "{work:?}");
32368        }
32369    }
32370
32371    #[test]
32372    fn editable_program_work_counts_materialized_facts_and_bounds_signed_return() {
32373        let work = SemanticTransitionWork {
32374            edit_commands: 2,
32375            added_supports: crate::semantic_program::RESIDENT_PROGRAM_FACT_CAPACITY as u64,
32376            defined_truth_changes: 3,
32377        };
32378        assert!(!work.is_valid(false));
32379        assert!(work.is_valid(true));
32380        assert!(!SemanticTransitionWork {
32381            added_supports: work.added_supports + 1,
32382            ..work
32383        }
32384        .is_valid(true));
32385        let scoring = SemanticTaskScoring {
32386            correct_weight: 14,
32387            all_correct_weight: 7,
32388            work_weight: 1,
32389            improvement_weight: 45,
32390            refusal_weight: 15,
32391            spent_weight: 1,
32392        };
32393        assert_eq!(scoring.return_bound(false).unwrap(), 2522);
32394        assert_eq!(scoring.return_bound(true).unwrap(), 186799);
32395    }
32396
32397    #[test]
32398    fn structural_cost_law_tracks_program_mode_without_task_identity() {
32399        let graph = semantic_structural_cost_descriptor(false);
32400        let editable = semantic_structural_cost_descriptor(true);
32401        assert_eq!(graph.cap, 6);
32402        assert_eq!(editable.cap, 4101);
32403        assert_ne!(graph.unit, editable.unit);
32404        assert_ne!(graph.unit, Identity256::default());
32405        assert_eq!(graph, semantic_structural_cost_descriptor(false));
32406        assert_eq!(editable, semantic_structural_cost_descriptor(true));
32407        let maximum = SemanticTransitionWork {
32408            edit_commands: 2,
32409            added_supports: 4096,
32410            defined_truth_changes: 3,
32411        };
32412        assert_eq!(maximum.raw_structural_cost(), editable.cap);
32413        assert_eq!(SemanticTransitionWork::default().raw_structural_cost(), 0);
32414    }
32415
32416    #[test]
32417    #[cfg(feature = "semantic-policy")]
32418    fn candidate_resource_refusals_preserve_the_completed_base() {
32419        let scoring = SemanticTaskScoring {
32420            correct_weight: 0,
32421            all_correct_weight: 0,
32422            work_weight: 1,
32423            improvement_weight: 0,
32424            refusal_weight: 1,
32425            spent_weight: 0,
32426        };
32427        let facts = [
32428            SemanticTaskFacts {
32429                eligible: 1,
32430                ..SemanticTaskFacts::default()
32431            },
32432            SemanticTaskFacts {
32433                c: 1,
32434                v: -1,
32435                ..SemanticTaskFacts::default()
32436            },
32437            SemanticTaskFacts::default(),
32438        ];
32439        let work = [
32440            SemanticTransitionWork {
32441                edit_commands: 1,
32442                ..SemanticTransitionWork::default()
32443            },
32444            SemanticTransitionWork::default(),
32445        ];
32446        assert!(validate_completed_task_scoring(
32447            scoring,
32448            true,
32449            &[],
32450            &facts,
32451            &work,
32452            [3, 4],
32453            3,
32454            0,
32455            -2,
32456        ));
32457        assert!(!validate_completed_task_scoring(
32458            scoring,
32459            true,
32460            &[],
32461            &facts,
32462            &work,
32463            [3, 5],
32464            3,
32465            0,
32466            -2,
32467        ));
32468        assert!(!validate_completed_task_scoring(
32469            scoring,
32470            false,
32471            &[],
32472            &facts,
32473            &work,
32474            [3, 4],
32475            3,
32476            0,
32477            -2,
32478        ));
32479        assert_eq!(
32480            SemanticTaskRefusal::FactCapacity.canonical_kind(),
32481            "fact-capacity"
32482        );
32483        assert_eq!(
32484            SemanticTaskRefusal::FuelExhausted.canonical_kind(),
32485            "fuel-exhausted"
32486        );
32487    }
32488
32489    #[test]
32490    #[cfg(feature = "semantic-policy")]
32491    fn completed_scoring_accepts_program_materialization_cost() {
32492        let scoring = SemanticTaskScoring {
32493            correct_weight: 14,
32494            all_correct_weight: 7,
32495            work_weight: 1,
32496            improvement_weight: 45,
32497            refusal_weight: 15,
32498            spent_weight: 1,
32499        };
32500        let work = SemanticTransitionWork {
32501            edit_commands: 2,
32502            added_supports: crate::semantic_program::RESIDENT_PROGRAM_FACT_CAPACITY as u64,
32503            defined_truth_changes: 3,
32504        };
32505        let facts = [
32506            SemanticTaskFacts {
32507                eligible: 1,
32508                ..SemanticTaskFacts::default()
32509            },
32510            SemanticTaskFacts {
32511                truth: [1; 3],
32512                correct: [1; 3],
32513                g: 3,
32514                p: 1,
32515                c: 4101,
32516                v: -4052,
32517                eligible: 1,
32518            },
32519            SemanticTaskFacts::default(),
32520        ];
32521        let work = [work, SemanticTransitionWork::default()];
32522        assert!(validate_completed_task_scoring(
32523            scoring,
32524            true,
32525            &[],
32526            &facts,
32527            &work,
32528            [0, 1],
32529            6,
32530            1,
32531            -182361,
32532        ));
32533        assert!(!validate_completed_task_scoring(
32534            scoring,
32535            false,
32536            &[],
32537            &facts,
32538            &work,
32539            [0, 1],
32540            6,
32541            1,
32542            -182361,
32543        ));
32544    }
32545
32546    #[test]
32547    fn policy_storage_follows_native_codebooks_without_allocating_null_embeddings() {
32548        let layout = SemanticPolicyLayout::from_components(COMPONENTS).unwrap();
32549        assert_eq!(layout.z, 0..4 * 128);
32550        assert_eq!(layout.recurrence, layout.z.end..layout.z.end + 128 * 128);
32551        assert_eq!(
32552            layout.positions,
32553            layout.recurrence.end..layout.recurrence.end + 18 * 128
32554        );
32555        let mut cursor = layout.positions.end;
32556        for (field, component) in layout.fields.iter().zip(&COMPONENTS[32..50]) {
32557            let cardinality = component.cardinality as usize;
32558            let null = component.field != 0;
32559            assert_eq!(field.null_category, if null { Some(0) } else { None });
32560            assert_eq!(field.cardinality, cardinality);
32561            assert_eq!(
32562                field.embeddings,
32563                cursor..cursor + (cardinality - usize::from(null)) * 128
32564            );
32565            cursor = field.embeddings.end;
32566            let bias_count = if null && cardinality == 1 {
32567                0
32568            } else {
32569                cardinality
32570            };
32571            assert_eq!(field.biases, cursor..cursor + bias_count);
32572            cursor = field.biases.end;
32573        }
32574        assert_eq!(layout.parameter_cells, cursor);
32575        assert_eq!(layout.recurrent_cells(), 2 * 37 * 128);
32576        assert_eq!(
32577            layout.score_cells(),
32578            COMPONENTS[32..50]
32579                .iter()
32580                .map(|c| c.cardinality as usize)
32581                .max()
32582                .unwrap()
32583        );
32584    }
32585
32586    #[test]
32587    fn resident_ranges_reject_partial_overlap_overflow_and_empty_storage() {
32588        assert!(disjoint_ranges(&[(8, 16), (24, 8)]).is_ok());
32589        for ranges in [
32590            [(8, 16), (16, 16)],
32591            [(8, 16), (8, 8)],
32592            [(8, 16), (u64::MAX, 8)],
32593            [(8, 0), (16, 8)],
32594        ] {
32595            assert_eq!(
32596                disjoint_ranges(&ranges),
32597                Err(SemanticTransitionError::OverlappingInputs)
32598            );
32599        }
32600    }
32601
32602    #[test]
32603    fn policy_layout_tracks_admitted_cardinality_and_rejects_inconsistent_slots() {
32604        let mut components = COMPONENTS.to_vec();
32605        for lane in 0..2 {
32606            for slot in 0..2 {
32607                components[lane * 68 + 32 + slot * 18 + 2].cardinality = 7;
32608            }
32609        }
32610        let layout = SemanticPolicyLayout::from_components(&components).unwrap();
32611        assert_eq!(layout.fields[2].embeddings.len(), 6 * 128);
32612        assert_eq!(layout.fields[2].biases.len(), 7);
32613        assert_eq!(layout.fields[2].null_category, Some(0));
32614        assert_eq!(layout.fields[0].null_category, None);
32615        assert_eq!(
32616            layout.fields[0].embeddings.len(),
32617            layout.fields[0].cardinality * 128
32618        );
32619        components[32 + 18 + 2].cardinality = 6;
32620        assert!(SemanticPolicyLayout::from_components(&components).is_err());
32621        assert!(SemanticPolicyLayout::from_components(&COMPONENTS[..135]).is_err());
32622        let mut malformed = COMPONENTS.to_vec();
32623        malformed[32].lane = 0;
32624        assert!(SemanticPolicyLayout::from_components(&malformed).is_err());
32625        malformed[32] = COMPONENTS[32];
32626        malformed[32].cardinality = 0;
32627        assert!(SemanticPolicyLayout::from_components(&malformed).is_err());
32628    }
32629
32630    #[test]
32631    fn decoded_support_corruption_rolls_back_first_lane_and_poison_closes_session() {
32632        use crate::{
32633            SemanticPolarity, SemanticPredicateRecord, SemanticRecordRole, SemanticSupportRecord,
32634            SemanticTypedRecord,
32635        };
32636        use cudarc::nvrtc::Ptx;
32637        use xlog_core::{RelId, Schema};
32638        if std::env::var("XLOG_REQUIRE_CUDA").as_deref() != Ok("1") {
32639            return;
32640        }
32641        #[derive(Clone, Copy)]
32642        enum IntegrityFault {
32643            SecondEdit,
32644            AfterSealedLane,
32645            RefusedEditThenInvalidLogit,
32646        }
32647        for fault_case in [
32648            IntegrityFault::SecondEdit,
32649            IntegrityFault::AfterSealedLane,
32650            IntegrityFault::RefusedEditThenInvalidLogit,
32651        ] {
32652            let late_failure = matches!(fault_case, IntegrityFault::AfterSealedLane);
32653            let refused_then_invalid =
32654                matches!(fault_case, IntegrityFault::RefusedEditThenInvalidLogit);
32655            let global_failure = late_failure || refused_then_invalid;
32656            let provider =
32657                crate::CudaProviderBuilder::new(0, MemoryBudget::with_limit(256 * 1024 * 1024))
32658                    .with_stream_capacity(1)
32659                    .build()
32660                    .unwrap();
32661            let provider = Arc::new(provider);
32662            let runtime = Arc::clone(provider.memory().runtime().unwrap());
32663            let id = runtime.stream_pool().acquire().unwrap();
32664            let stream = runtime.stream_pool().resolve(id).unwrap();
32665            let domain = provider
32666                .bind_resident_execution_domain(runtime, id, stream)
32667                .unwrap();
32668            let mut graph = provider
32669                .allocate_semantic_hypergraph(
32670                    &domain,
32671                    SemanticHypergraphCapacities::try_new(3, 4, 4, 4).unwrap(),
32672                )
32673                .unwrap();
32674            let base = graph.empty_root();
32675            let roles = [
32676                SemanticRecordRole::Statement,
32677                SemanticRecordRole::Provenance,
32678                SemanticRecordRole::Source,
32679                SemanticRecordRole::Context,
32680                SemanticRecordRole::Scope,
32681            ];
32682            graph
32683                .admit_records(
32684                    base,
32685                    SemanticAdmissionRecords {
32686                        predicates: roles
32687                            .into_iter()
32688                            .enumerate()
32689                            .map(|(i, role)| SemanticPredicateRecord {
32690                                predicate: RelId(i as u32),
32691                                role,
32692                                schema: Schema::new(vec![]),
32693                            })
32694                            .collect(),
32695                        records: (0..5)
32696                            .map(|i| SemanticTypedRecord {
32697                                predicate: RelId(i),
32698                                arguments: vec![],
32699                                qualifiers: vec![],
32700                            })
32701                            .collect(),
32702                        supports: vec![SemanticSupportRecord {
32703                            statement: 0,
32704                            polarity: SemanticPolarity::Pro,
32705                            provenance: 1,
32706                            source: 2,
32707                            context: 3,
32708                            scope: 4,
32709                        }],
32710                    },
32711                    SemanticAdmissionLimits {
32712                        max_records: 12,
32713                        max_terms: 0,
32714                        max_references: 5,
32715                        max_utf8_bytes: 0,
32716                    },
32717                )
32718                .unwrap();
32719            let mut session = SemanticTransitionSession::from_hypergraph(graph).unwrap();
32720
32721            // Immutable typed inputs cannot produce an invalid polarity. Inject
32722            // faults in this compilation of the production kernel; actual sampler,
32723            // mutation and cleanup remain unchanged. These are integrity failures,
32724            // not semantic policy refusals.
32725            let source = include_str!("../kernels/semantic_transition.cu");
32726            let anchor = if late_failure {
32727                "lane_live=candidate.words[41]!=0;"
32728            } else {
32729                "decode_action(books,choices,&statement,&event);"
32730            };
32731            assert_eq!(source.matches(anchor).count(), 1);
32732            let fault = if late_failure {
32733                "if (lane==1) {failed=1;state->status=3;}"
32734            } else if refused_then_invalid {
32735                "if (lane==0 && component.slot==0) event.polarity=0;"
32736            } else {
32737                "if (lane==0 && component.slot==1) event.polarity=0;"
32738            };
32739            let source = source.replacen(anchor, &format!("{anchor}\n{fault}"), 1);
32740            // Use the same ahead-of-time compiler as the normal kernel build. NVRTC
32741            // does not supply the standard headers included by this canonical source.
32742            struct CompilationFiles(std::path::PathBuf);
32743            impl Drop for CompilationFiles {
32744                fn drop(&mut self) {
32745                    for file in ["transition.cu", "transition.ptx"] {
32746                        if let Err(error) = std::fs::remove_file(self.0.join(file)) {
32747                            if error.kind() != std::io::ErrorKind::NotFound {
32748                                eprintln!("failed to remove test compiler output: {error}");
32749                            }
32750                        }
32751                    }
32752                    if let Err(error) = std::fs::remove_dir(&self.0) {
32753                        eprintln!("failed to remove test compiler directory: {error}");
32754                    }
32755                }
32756            }
32757            let unique = std::time::SystemTime::now()
32758                .duration_since(std::time::UNIX_EPOCH)
32759                .unwrap()
32760                .as_nanos();
32761            let path = std::env::temp_dir().join(format!(
32762                "xlog-decoded-support-{}-{unique}",
32763                std::process::id()
32764            ));
32765            std::fs::create_dir(&path).unwrap();
32766            let files = CompilationFiles(path);
32767            std::fs::write(files.0.join("transition.cu"), source).unwrap();
32768            let output = std::process::Command::new(
32769                std::env::var_os("NVCC_PATH").unwrap_or_else(|| "nvcc".into()),
32770            )
32771            .args([
32772                "--ptx",
32773                "-arch=sm_75",
32774                "-O3",
32775                "-std=c++17",
32776                "-I",
32777                env!("OUT_DIR"),
32778                "-I",
32779                concat!(env!("CARGO_MANIFEST_DIR"), "/kernels"),
32780            ])
32781            .arg(files.0.join("transition.cu"))
32782            .arg("-o")
32783            .arg(files.0.join("transition.ptx"))
32784            .output()
32785            .expect("compile canonical transition with decoded support corruption");
32786            assert!(
32787                output.status.success(),
32788                "{}",
32789                String::from_utf8_lossy(&output.stderr)
32790            );
32791            let ptx =
32792                Ptx::from_src(std::fs::read_to_string(files.0.join("transition.ptx")).unwrap());
32793            drop(files);
32794            let device = provider.device().inner();
32795            let module = "semantic_transition_decoded_support_corruption";
32796            device
32797                .load_ptx(ptx, module, &["semantic_transition_execute"])
32798                .unwrap();
32799            session.execute = device
32800                .get_func(module, "semantic_transition_execute")
32801                .unwrap();
32802            let inputs: Vec<_> = session
32803                .components()
32804                .iter()
32805                .map(|component| {
32806                    let mut product_support = vec![0; component.cardinality as usize];
32807                    let choice = usize::from(
32808                        !component.is_text() && matches!(component.field, 0 | 1 | 2 | 11 | 17),
32809                    );
32810                    product_support[choice] = 1;
32811                    SemanticComponentInput {
32812                        logits: vec![0.; product_support.len()],
32813                        product_support,
32814                    }
32815                })
32816                .collect();
32817            session
32818                .bind_inputs(
32819                    session.binding(),
32820                    SemanticRngBinding {
32821                        model_generation: 1,
32822                        stream_serial: 1,
32823                        family_id: 1,
32824                        proposal: 0,
32825                    },
32826                    &inputs,
32827                )
32828                .unwrap();
32829            if refused_then_invalid {
32830                // Corrupt the retained bank only after valid cold binding. The
32831                // second edit's first conditional factor then fails through the
32832                // production nonfinite-logit check, after a genuine edit refusal
32833                // has retained its candidate acquisition for cleanup.
32834                let mut corrupted_logits: Vec<_> = inputs
32835                    .iter()
32836                    .flat_map(|input| input.logits.iter().copied())
32837                    .collect();
32838                let component = session.components()[50];
32839                assert_eq!((component.lane, component.slot, component.field), (1, 1, 0));
32840                corrupted_logits[component.offset as usize + 1] = f32::NAN;
32841                provider
32842                    .htod_sync_copy_into_tracked(&corrupted_logits, &mut session.logits)
32843                    .unwrap();
32844            }
32845            let [arena_ptr, _, root_capacity, statement_capacity, _, _, arena_words] =
32846                session.graph.transition_arena();
32847            assert_eq!(
32848                (root_capacity, statement_capacity, arena_words),
32849                (3, 4, 260)
32850            );
32851            assert_eq!(base.slot(), 0);
32852            let readback_stream = Arc::clone(&session.stream);
32853            let read_resident_arena = || {
32854                readback_stream.synchronize().unwrap();
32855                let mut words = vec![0u64; arena_words as usize];
32856                // SAFETY: the session still owns this entire allocation; its stream
32857                // is idle and the destination has exactly the advertised capacity.
32858                assert_eq!(
32859                    unsafe {
32860                        sys::cuMemcpyDtoH_v2(
32861                            words.as_mut_ptr().cast(),
32862                            arena_ptr,
32863                            std::mem::size_of_val(words.as_slice()),
32864                        )
32865                    },
32866                    sys::cudaError_enum::CUDA_SUCCESS
32867                );
32868                words
32869            };
32870            // Diagnostic I/O stays outside capture and the measured launch interval.
32871            // Read the device allocation itself, never the cached base_snapshot.
32872            let original_arena = read_resident_arena();
32873            // Canonical layout: sixteen control words, then sixteen words per root;
32874            // root statement heads precede the final candidate statement-head array.
32875            let base_record = 16..32;
32876            let heads_start = (arena_words - (root_capacity + 1) * statement_capacity) as usize;
32877            let base_heads = heads_start..heads_start + statement_capacity as usize;
32878            assert_eq!(&original_arena[19..22], &[0, 0, 0]);
32879            assert!(original_arena[base_heads.clone()]
32880                .iter()
32881                .all(|head| *head == 0));
32882            session.capture().unwrap();
32883            assert_eq!(session.captured.as_ref().unwrap().node_count().unwrap(), 1);
32884            let before = session.host_io_stats();
32885            session.launch().unwrap();
32886            assert_eq!(session.host_io_stats(), before);
32887            let error = session.observe(0).unwrap_err();
32888            if refused_then_invalid {
32889                assert!(matches!(
32890                    error,
32891                    SemanticTransitionError::NonFinitePolicyInput {
32892                        completed_draws: 50
32893                    }
32894                ));
32895            } else if late_failure {
32896                assert!(matches!(
32897                    error,
32898                    SemanticTransitionError::ObservationMismatch
32899                ));
32900            } else {
32901                assert!(matches!(error, SemanticTransitionError::Semantic(_)));
32902            }
32903            assert!(session.is_poisoned());
32904            assert_eq!(
32905                session.next_proposal, 0,
32906                "integrity error must not publish RNG successor"
32907            );
32908            assert!(matches!(
32909                session.launch(),
32910                Err(SemanticTransitionError::Poisoned)
32911            ));
32912            assert!(matches!(
32913                session.observe(0),
32914                Err(SemanticTransitionError::Poisoned)
32915            ));
32916
32917            // SAFETY: observe completed both copies and stream waits before decoding
32918            // the integrity failure. Inspect that same terminal bank, with no new I/O.
32919            let (state, components) = unsafe { session.pinned.read() }.unwrap();
32920            if global_failure {
32921                assert_eq!(
32922                    (state.status, state.blocks, state.next_proposal),
32923                    if late_failure { (3, 68, 0) } else { (5, 50, 0) }
32924                );
32925                if late_failure {
32926                    assert_eq!(state.semantic_receipts[3][1], 1, "first lane really sealed");
32927                    assert_eq!(state.retired_roots_mask, 1);
32928                    assert_eq!(state.cleanup_receipts[1][0], 0, "sealed root reclaimed");
32929                } else {
32930                    assert_eq!(
32931                        state.semantic_receipts[1][0], 12,
32932                        "original edit refusal retained"
32933                    );
32934                    assert_eq!(&state.semantic_receipts[1][40..42], &[0, 1]);
32935                    assert_eq!(state.retired_roots_mask, 0, "no root was sealed");
32936                }
32937                assert_eq!(state.cleanup_receipts[0][0], 0, "live candidate discarded");
32938                assert_eq!(&state.cleanup_receipts[0][40..42], &[0, 0]);
32939                let terminal_arena = read_resident_arena();
32940                assert_eq!(
32941                    &terminal_arena[base_record.clone()],
32942                    &original_arena[base_record]
32943                );
32944                assert_eq!(
32945                    &terminal_arena[base_heads.clone()],
32946                    &original_arena[base_heads]
32947                );
32948                for slot in [32, 48, 64] {
32949                    assert_eq!(terminal_arena[slot], 0, "no pending root or candidate");
32950                }
32951                drop(session);
32952                provider.memory().reap_pending_deallocations().unwrap();
32953                assert_eq!(provider.memory().allocated_bytes(), 0);
32954                assert_eq!(provider.memory().deallocation_failure_bytes(), 0);
32955                continue;
32956            }
32957            assert_eq!((state.status, state.blocks), (0, 136));
32958            for (row, component) in components.iter().zip(session.components()) {
32959                assert_eq!(row.ordinal, component.ordinal);
32960                assert_eq!(row.admission_binding, session.binding().digest);
32961                assert_eq!(
32962                    row.choice,
32963                    u32::from(
32964                        !component.is_text() && matches!(component.field, 0 | 1 | 2 | 11 | 17)
32965                    )
32966                );
32967                assert_eq!(
32968                    (row.cdf_start, row.cdf_end, row.mass),
32969                    (0, 1 << 63, 1 << 63)
32970                );
32971                assert!(row.draw < row.cdf_end);
32972            }
32973            let receipts = state.semantic_receipts;
32974            assert_eq!(receipts[0][0], 0); // Acquired-base preflight succeeded.
32975            assert_eq!(&receipts[0][13..16], &[0, 0, 0]);
32976            assert_eq!(&receipts[1][0..3], &[0, 1, 1]); // First actual insertion.
32977            assert_eq!(receipts[2][0], 12); // Invalid second decoded support.
32978            assert_eq!(receipts[3][0], 12); // Refusal survives discard/seal.
32979            assert_eq!(&receipts[3][40..42], &[0, 1]); // Original refusal diagnostic retained.
32980            assert_eq!(&receipts[4][0..3], &[0, 1, 1]); // Next lane executes.
32981            assert_eq!(&receipts[5][0..3], &[0, 2, 1]); // Then exact duplicate.
32982            assert_eq!(&receipts[4][40..42], &[0, 2]); // Discarded candidate reused safely.
32983            assert_eq!(&receipts[5][40..42], &[0, 2]);
32984            assert_eq!(receipts[6][0], 0);
32985            assert_eq!(&receipts[6][13..16], &[1, 1, 1]);
32986            assert_eq!(receipts[6][6], 3); // Successful terminal retires the candidate again.
32987            assert_eq!(&receipts[6][3..5], &[1, 1]); // No root published by the failed lane.
32988            for slot in [7, 9, 11] {
32989                assert_eq!(receipts[4][slot], receipts[1][slot]);
32990                assert!(receipts[4][slot + 1] > receipts[1][slot + 1]);
32991            }
32992            // Observe has completed the failed lane's cleanup and the successful
32993            // next lane. Re-read resident state even though public observation is
32994            // now poison-closed. For this empty base, zero heads exhaust reachable
32995            // content; other roots and globally reused records may legitimately change.
32996            let terminal_arena = read_resident_arena();
32997            assert_eq!(&terminal_arena[..16], &original_arena[..16]);
32998            assert_eq!(
32999                &terminal_arena[base_record.clone()],
33000                &original_arena[base_record]
33001            );
33002            assert_eq!(
33003                &terminal_arena[base_heads.clone()],
33004                &original_arena[base_heads]
33005            );
33006            drop(session);
33007            provider.memory().reap_pending_deallocations().unwrap();
33008            assert_eq!(provider.memory().allocated_bytes(), 0);
33009            assert_eq!(provider.memory().deallocation_failure_bytes(), 0);
33010        }
33011    }
33012
33013    #[test]
33014    fn actual_enqueued_work_and_terminal_wait_faults_poison_public_session() {
33015        if std::env::var("XLOG_REQUIRE_CUDA").as_deref() != Ok("1") {
33016            return;
33017        }
33018        let provider =
33019            crate::CudaProviderBuilder::new(0, MemoryBudget::with_limit(256 * 1024 * 1024))
33020                .with_stream_capacity(1)
33021                .build()
33022                .unwrap();
33023        let provider = Arc::new(provider);
33024        let runtime = Arc::clone(provider.memory().runtime().unwrap());
33025        let id = runtime.stream_pool().acquire().unwrap();
33026        let stream = runtime.stream_pool().resolve(id).unwrap();
33027        let domain = provider
33028            .bind_resident_execution_domain(runtime, id, stream)
33029            .unwrap();
33030        for failure in 0..12 {
33031            let mut session = SemanticTransitionSession::new(&provider, &domain).unwrap();
33032            let inputs: Vec<_> = session
33033                .components()
33034                .iter()
33035                .map(|c| {
33036                    let mut mask = vec![0; c.cardinality as usize];
33037                    mask[0] = 1;
33038                    SemanticComponentInput {
33039                        logits: vec![0.; mask.len()],
33040                        product_support: mask,
33041                    }
33042                })
33043                .collect();
33044            session
33045                .bind_inputs(
33046                    session.binding(),
33047                    SemanticRngBinding {
33048                        model_generation: 1,
33049                        stream_serial: 2,
33050                        family_id: 3,
33051                        proposal: 4,
33052                    },
33053                    &inputs,
33054                )
33055                .unwrap();
33056            session.capture().unwrap();
33057            assert_eq!(session.captured.as_ref().unwrap().node_count().unwrap(), 1);
33058            if failure == 0 {
33059                let recorder = session.kernel_recorder();
33060                let graph = session.captured.as_ref().unwrap();
33061                let result = enqueue_recorded(&domain, &mut session.poisoned, recorder, |stream| {
33062                    graph.launch_in(stream)?;
33063                    Err::<(), _>(XlogError::Kernel(
33064                        "injected error after actual graph enqueue".into(),
33065                    ))
33066                });
33067                assert!(result.is_err());
33068            } else if failure == 1 {
33069                session.launch().unwrap();
33070                let result = wait_on_stream(
33071                    &session.stream,
33072                    &mut session.poisoned,
33073                    &mut session.stream_waits,
33074                    "terminal wait",
33075                    |stream| {
33076                        stream.synchronize().unwrap();
33077                        Err::<(), _>(XlogError::Kernel(
33078                            "injected terminal wait error after actual completion".into(),
33079                        ))
33080                    },
33081                );
33082                assert!(result.is_err());
33083            } else if failure == 2 {
33084                // Exercise the actual device-side rejection and typed observation:
33085                // corrupt a private cold state binding after public preflight.
33086                let invalid = DeviceState {
33087                    next_proposal: 4,
33088                    ..DeviceState::default()
33089                };
33090                provider
33091                    .htod_sync_copy_into_tracked(&[invalid], &mut session.state)
33092                    .unwrap();
33093                session.launch().unwrap();
33094                assert!(matches!(
33095                    session.observe(4),
33096                    Err(SemanticTransitionError::ObservationMismatch)
33097                ));
33098            } else if failure == 3 {
33099                // A captured-but-never-launched session must release its storage.
33100                assert!(!session.is_poisoned());
33101            } else if failure == 4 {
33102                // Repeated capture and a normal terminal observation also retire
33103                // all read dependencies without carrying capture-only events.
33104                session.capture().unwrap();
33105                session.launch().unwrap();
33106                session.observe(4).unwrap();
33107            } else if failure == 5 {
33108                // Internal integrity diagnostics must close the enclosing owner,
33109                // not merely appear as a nested lane error permitting replay.
33110                let mut words = [0; 42];
33111                words[0] = 11;
33112                assert!(session.graph.observe_transition_edit(words).is_err());
33113            } else if failure == 6 {
33114                let mut words = [0; 42];
33115                words[3] = u64::MAX;
33116                assert!(session.graph.observe_transition_root(words).is_err());
33117            } else {
33118                let mut words = [0; 42];
33119                words[1] = if failure == 11 { 2 } else { 1 };
33120                words[8] = 1;
33121                words[10] = 1;
33122                words[12] = 1;
33123                words[39] = session.graph.transition_arena()[1];
33124                match failure {
33125                    7 => words[39] = 0,
33126                    8 => words[8] = 0,
33127                    9 => words[10] = 0,
33128                    _ => words[12] = 0,
33129                }
33130                assert!(session.graph.observe_transition_edit(words).is_err());
33131            }
33132            if !(3..5).contains(&failure) {
33133                assert!(session.is_poisoned());
33134                assert!(matches!(
33135                    session.launch(),
33136                    Err(SemanticTransitionError::Poisoned)
33137                ));
33138                assert!(matches!(
33139                    session.observe(4),
33140                    Err(SemanticTransitionError::Poisoned)
33141                ));
33142            }
33143            drop(session);
33144            provider.memory().reap_pending_deallocations().unwrap();
33145            assert_eq!(provider.memory().allocated_bytes(), 0);
33146            assert_eq!(provider.memory().deallocation_failure_bytes(), 0);
33147        }
33148    }
33149}
33150
33151#[cfg(test)]
33152mod text_parent_tests {
33153    use super::*;
33154
33155    #[test]
33156    fn model_content_snapshot_copies_original_seals_and_exact_contract_interval() {
33157        let directory = [
33158            PublicationRange {
33159                role: 18,
33160                generation: 1,
33161                length_bytes: 4,
33162                ..PublicationRange::default()
33163            },
33164            PublicationRange {
33165                role: 44,
33166                generation: 1,
33167                storage_slot: 2,
33168                offset_bytes: 7,
33169                length_bytes: 11,
33170                ..PublicationRange::default()
33171            },
33172            PublicationRange {
33173                role: 20,
33174                generation: 1,
33175                length_bytes: 4,
33176                ..PublicationRange::default()
33177            },
33178        ];
33179        let plan = model_content_copy_plan(&directory, &[2, 0], &[4, 4, 19]).unwrap();
33180        assert_eq!(
33181            plan.directory_offsets,
33182            [
33183                2 * size_of::<PublicationRange>(),
33184                0,
33185                size_of::<PublicationRange>()
33186            ]
33187        );
33188        assert_eq!(plan.contract_storage_slot, 2);
33189        assert_eq!(plan.contract_span, 7..18);
33190        let mut changed = directory;
33191        changed[1].digest = Identity256::from_bytes([91; 32]);
33192        let changed_plan = model_content_copy_plan(&changed, &[2, 0], &[4, 4, 19]).unwrap();
33193        assert_eq!(
33194            changed_plan.directory_offsets, plan.directory_offsets,
33195            "copy geometry must not upload a host-cached expected digest"
33196        );
33197    }
33198
33199    #[test]
33200    fn model_content_snapshot_refuses_incomplete_or_unowned_ranges() {
33201        let directory = [
33202            PublicationRange {
33203                role: 18,
33204                generation: 1,
33205                length_bytes: 4,
33206                ..PublicationRange::default()
33207            },
33208            PublicationRange {
33209                role: 44,
33210                generation: 1,
33211                storage_slot: 1,
33212                offset_bytes: 3,
33213                length_bytes: 5,
33214                ..PublicationRange::default()
33215            },
33216        ];
33217        let plan = |rows: &[PublicationRange], indices: &[usize], allocations: &[usize]| {
33218            model_content_copy_plan(rows, indices, allocations)
33219        };
33220        assert!(plan(&directory, &[], &[4, 8]).is_err());
33221        assert!(plan(&directory, &[2], &[4, 8]).is_err());
33222        assert!(plan(&directory, &[1], &[4, 8]).is_err());
33223        assert!(plan(&directory, &[0, 0], &[4, 8]).is_err());
33224        assert!(plan(&directory[..1], &[0], &[4, 8]).is_err());
33225        assert!(plan(&directory, &[0], &[4]).is_err());
33226        assert!(plan(&directory, &[0], &[4, 7]).is_err());
33227        let mut changed = directory;
33228        changed[1].offset_bytes = u64::MAX;
33229        assert!(plan(&changed, &[0], &[4, usize::MAX]).is_err());
33230        changed = directory;
33231        changed[1].length_bytes = 0;
33232        assert!(plan(&changed, &[0], &[4, 8]).is_err());
33233        changed = directory;
33234        changed[1].generation = 2;
33235        assert!(plan(&changed, &[0], &[4, 8]).is_err());
33236        changed = directory;
33237        changed[1].index = 1;
33238        assert!(plan(&changed, &[0], &[4, 8]).is_err());
33239        let duplicate = [directory[0], directory[1], directory[1]];
33240        assert!(plan(&duplicate, &[0], &[4, 8]).is_err());
33241    }
33242
33243    #[test]
33244    fn model_content_binding_requires_the_complete_original_roster() {
33245        let layout = |role, index| SemanticTensorLayout {
33246            role,
33247            index,
33248            scalar_type: 6,
33249            element_bytes: 4,
33250            rank: 2,
33251            logical_axis: u64::MAX,
33252            dimensions: [2, 3, 0, 0],
33253            strides_bytes: [12, 4, 0, 0],
33254        };
33255        let layouts: BTreeMap<_, _> = [(18, 0), (18, 1), (19, 0), (20, 0)]
33256            .into_iter()
33257            .map(|key| (key, layout(key.0, key.1)))
33258            .collect();
33259        let mut directory: Vec<_> = layouts
33260            .values()
33261            .map(|layout| PublicationRange {
33262                role: layout.role,
33263                index: layout.index,
33264                generation: 1,
33265                length_bytes: 24,
33266                ..PublicationRange::default()
33267            })
33268            .collect();
33269        directory.push(PublicationRange {
33270            role: 44,
33271            generation: 1,
33272            length_bytes: 8,
33273            ..PublicationRange::default()
33274        });
33275        let original: Vec<_> = layouts.values().map(|&layout| (layout, 0, 0, 24)).collect();
33276        let bind = |rows: &[(SemanticTensorLayout, u64, u64, usize)]| {
33277            model_content_ranges(&directory, &layouts, rows.iter().copied())
33278        };
33279        assert_eq!(bind(&original).unwrap(), vec![0, 1, 2, 3]);
33280        assert!(bind(&original[..3]).is_err());
33281        assert!(bind(&[]).is_err());
33282        let mut duplicate = original.clone();
33283        duplicate[3] = original[2];
33284        assert!(bind(&duplicate).is_err());
33285        let mut transient = original.clone();
33286        transient[0].0.role = 0;
33287        assert!(bind(&transient).is_err());
33288        let mut extra = original.clone();
33289        extra.push((layout(18, 2), 0, 0, 24));
33290        assert!(bind(&extra).is_err());
33291        let mut reordered = original.clone();
33292        reordered.reverse();
33293        assert_eq!(bind(&reordered).unwrap(), vec![3, 2, 1, 0]);
33294        let without_adapter: Vec<_> = directory
33295            .iter()
33296            .copied()
33297            .filter(|row| row.role != 19)
33298            .collect();
33299        let absent_adapter: Vec<_> = original
33300            .iter()
33301            .copied()
33302            .filter(|row| row.0.role != 19)
33303            .collect();
33304        assert!(
33305            model_content_ranges(&without_adapter, &layouts, absent_adapter.iter().copied())
33306                .is_ok()
33307        );
33308        assert!(
33309            model_content_ranges(&without_adapter, &layouts, original.iter().copied()).is_err()
33310        );
33311        assert!(model_content_ranges(&directory[..4], &layouts, original.iter().copied()).is_err());
33312    }
33313
33314    #[test]
33315    fn model_content_binding_accepts_logical_equality_not_changed_shape_or_interval() {
33316        let expected = SemanticTensorLayout {
33317            role: 18,
33318            index: 0,
33319            scalar_type: 6,
33320            element_bytes: 4,
33321            rank: 2,
33322            logical_axis: 0,
33323            dimensions: [2, 3, 0, 0],
33324            strides_bytes: [12, 4, 0, 0],
33325        };
33326        let layouts = BTreeMap::from([((18, 0), expected)]);
33327        let directory = [
33328            PublicationRange {
33329                role: 18,
33330                generation: 1,
33331                length_bytes: 24,
33332                logical_begin: 5,
33333                logical_end: 7,
33334                ..PublicationRange::default()
33335            },
33336            PublicationRange {
33337                role: 44,
33338                generation: 1,
33339                length_bytes: 8,
33340                ..PublicationRange::default()
33341            },
33342        ];
33343        let bind = |layout, begin, end, bytes| {
33344            model_content_ranges(
33345                &directory,
33346                &layouts,
33347                std::iter::once((layout, begin, end, bytes)),
33348            )
33349        };
33350        let mut actual = expected;
33351        actual.strides_bytes = [4, 8, 0, 0];
33352        assert_eq!(bind(actual, 5, 7, 24).unwrap(), vec![0]);
33353        actual.strides_bytes = [32, 4, 0, 0];
33354        assert_eq!(bind(actual, 5, 7, 44).unwrap(), vec![0]);
33355        assert!(bind(actual, 5, 7, 24).is_err());
33356        assert!(bind(actual, 6, 8, 44).is_err());
33357        actual.strides_bytes = [4, 4, 0, 0];
33358        assert!(bind(actual, 5, 7, 16).is_err());
33359        actual = expected;
33360        actual.dimensions = [3, 2, 0, 0];
33361        actual.strides_bytes = [8, 4, 0, 0];
33362        assert!(bind(actual, 5, 8, 24).is_err());
33363        actual = expected;
33364        actual.scalar_type = 2;
33365        assert!(bind(actual, 5, 7, 24).is_err());
33366    }
33367
33368    #[test]
33369    fn tensor_content_range_accepts_private_operands_without_publication_roles() {
33370        for (scalar_type, element_bytes, dtype) in [
33371            (
33372                9,
33373                8,
33374                crate::dlpack::DLDataType {
33375                    code: crate::dlpack::K_DLFLOAT,
33376                    bits: 64,
33377                    lanes: 1,
33378                },
33379            ),
33380            (
33381                7,
33382                8,
33383                crate::dlpack::DLDataType {
33384                    code: 0,
33385                    bits: 64,
33386                    lanes: 1,
33387                },
33388            ),
33389            (
33390                8,
33391                1,
33392                crate::dlpack::DLDataType {
33393                    code: 6,
33394                    bits: 8,
33395                    lanes: 1,
33396                },
33397            ),
33398            (
33399                6,
33400                4,
33401                crate::dlpack::DLDataType {
33402                    code: 2,
33403                    bits: 32,
33404                    lanes: 1,
33405                },
33406            ),
33407        ] {
33408            let mut layout = SemanticTensorLayout {
33409                role: 0,
33410                index: 0,
33411                scalar_type,
33412                element_bytes,
33413                rank: 2,
33414                logical_axis: u64::MAX,
33415                dimensions: [2, 3, 0, 0],
33416                strides_bytes: [element_bytes, 2 * element_bytes, 0, 0],
33417            };
33418            let metadata = TensorMetadata {
33419                device_type: 2,
33420                device_id: 0,
33421                dtype,
33422                shape: &[2, 3],
33423                strides: Some(&[1, 2]),
33424                data: 4096,
33425                byte_offset: 0,
33426            };
33427            let bytes = 6 * element_bytes as usize;
33428            assert_eq!(
33429                validate_tensor_metadata(&layout, &metadata, 0).unwrap(),
33430                (4096, bytes)
33431            );
33432            assert_eq!(tensor_content_range(&layout, 0, 0, bytes).unwrap().role, 0);
33433            assert!(SemanticStateRole::from_code(0).is_none());
33434            layout.role = 56;
33435            assert!(validate_tensor_metadata(&layout, &metadata, 0).is_err());
33436            assert!(tensor_content_range(&layout, 0, 0, bytes).is_err());
33437            layout.role = 0;
33438            layout.dimensions[0] = 0;
33439            assert_eq!(
33440                tensor_content_range(&layout, 0, 0, 0).unwrap().length_bytes,
33441                0
33442            );
33443        }
33444    }
33445
33446    #[test]
33447    fn content_coordinates_keep_private_occurrences_in_original_roster_order() {
33448        assert!(validate_content_coordinates([(0, 0), (0, 1), (0, 2)].into_iter()).is_ok());
33449        assert!(validate_content_coordinates([(4, 1), (0, 1), (5, 1)].into_iter()).is_ok());
33450        for coordinates in [
33451            vec![(0, 1)],
33452            vec![(0, 0), (0, 0)],
33453            vec![(0, 0), (0, 2)],
33454            vec![(4, 0), (4, 0)],
33455            vec![(56, 0)],
33456        ] {
33457            assert!(validate_content_coordinates(coordinates.into_iter()).is_err());
33458        }
33459    }
33460
33461    #[test]
33462    fn tensor_content_range_preserves_signed_tokens_and_boolean_masks() {
33463        for (scalar_type, element_bytes, dtype) in [
33464            (
33465                7,
33466                8,
33467                crate::dlpack::DLDataType {
33468                    code: 0,
33469                    bits: 64,
33470                    lanes: 1,
33471                },
33472            ),
33473            (
33474                8,
33475                1,
33476                crate::dlpack::DLDataType {
33477                    code: 6,
33478                    bits: 8,
33479                    lanes: 1,
33480                },
33481            ),
33482        ] {
33483            let layout = SemanticTensorLayout {
33484                role: 1,
33485                index: 0,
33486                scalar_type,
33487                element_bytes,
33488                rank: 2,
33489                logical_axis: 1,
33490                dimensions: [1, 3, 0, 0],
33491                strides_bytes: [3 * element_bytes, element_bytes, 0, 0],
33492            };
33493            let metadata = TensorMetadata {
33494                device_type: 2,
33495                device_id: 0,
33496                dtype,
33497                shape: &[1, 3],
33498                strides: Some(&[3, 1]),
33499                data: 4096,
33500                byte_offset: 0,
33501            };
33502            assert_eq!(
33503                validate_tensor_metadata(&layout, &metadata, 0).unwrap(),
33504                (4096, 3 * element_bytes as usize)
33505            );
33506            let range = tensor_content_range(&layout, 11, 14, 3 * element_bytes as usize).unwrap();
33507            assert_eq!(
33508                (
33509                    range.role,
33510                    range.index,
33511                    range.logical_begin,
33512                    range.logical_end
33513                ),
33514                (1, 0, 11, 14)
33515            );
33516            assert!(tensor_content_range(&layout, 11, 13, 3 * element_bytes as usize).is_err());
33517            let mut wrong = metadata;
33518            wrong.dtype.code = 1;
33519            assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
33520        }
33521    }
33522
33523    #[test]
33524    fn tensor_content_range_checks_transposed_empty_and_exact_byte_extents() {
33525        let mut layout = SemanticTensorLayout {
33526            role: 4,
33527            index: 2,
33528            scalar_type: 6,
33529            element_bytes: 4,
33530            rank: 2,
33531            logical_axis: u64::MAX,
33532            dimensions: [2, 3, 0, 0],
33533            strides_bytes: [4, 8, 0, 0],
33534        };
33535        assert_eq!(
33536            tensor_content_range(&layout, 0, 0, 24)
33537                .unwrap()
33538                .length_bytes,
33539            24
33540        );
33541        assert!(tensor_content_range(&layout, 0, 1, 24).is_err());
33542        assert!(tensor_content_range(&layout, 0, 0, 23).is_err());
33543        assert!(tensor_content_range(&layout, 0, 0, 25).is_err());
33544        layout.logical_axis = 0;
33545        layout.dimensions[0] = 0;
33546        assert_eq!(
33547            tensor_content_range(&layout, 9, 9, 0).unwrap().length_bytes,
33548            0
33549        );
33550        assert!(tensor_content_range(&layout, 9, 8, 0).is_err());
33551    }
33552
33553    fn publication_test_tensor(
33554        provider: &CudaKernelProvider,
33555        role: u64,
33556        value: f32,
33557    ) -> SemanticTensorInput {
33558        let bytes = value.to_le_bytes();
33559        let owner = allocate_publication::<u8>(provider, bytes.len()).unwrap();
33560        upload_publication(provider, &bytes, &owner).unwrap();
33561        let tensor = crate::dlpack::export_slice_managed_tensor(
33562            Arc::new(owner),
33563            provider.device().ordinal() as i32,
33564            crate::dlpack::DLDataType {
33565                code: 2,
33566                bits: 32,
33567                lanes: 1,
33568            },
33569            1,
33570            1,
33571        )
33572        .unwrap();
33573        SemanticTensorInput {
33574            layout: SemanticTensorLayout {
33575                role,
33576                index: 0,
33577                scalar_type: 6,
33578                element_bytes: 4,
33579                rank: 2,
33580                logical_axis: u64::MAX,
33581                dimensions: [1, 1, 0, 0],
33582                strides_bytes: [4, 4, 0, 0],
33583            },
33584            logical_begin: 0,
33585            logical_end: 0,
33586            tensor,
33587            native_allocation: None,
33588        }
33589    }
33590
33591    pub(super) fn publication_test_session(
33592        provider: Arc<CudaKernelProvider>,
33593        domain: &ResidentExecutionDomain,
33594    ) -> SemanticTransitionSession {
33595        use crate::{SemanticArgument, SemanticPredicateRecord, SemanticTypedRecord};
33596        use xlog_core::{RelId, ScalarType, Schema};
33597        let mut graph = provider
33598            .allocate_semantic_hypergraph(
33599                domain,
33600                crate::SemanticHypergraphCapacities::try_new(4, 8, 8, 8).unwrap(),
33601            )
33602            .unwrap();
33603        let records = SemanticAdmissionRecords {
33604            predicates: vec![SemanticPredicateRecord {
33605                predicate: RelId(1),
33606                role: SemanticRecordRole::Statement,
33607                schema: Schema::new(vec![
33608                    ("left".into(), ScalarType::U32),
33609                    ("right".into(), ScalarType::U32),
33610                ])
33611                .with_sort_labels(vec!["bit".into(), "bit".into()])
33612                .unwrap(),
33613            }],
33614            records: [[1, 1], [0, 1]]
33615                .into_iter()
33616                .map(|values| SemanticTypedRecord {
33617                    predicate: RelId(1),
33618                    arguments: values.map(SemanticArgument::U32).to_vec(),
33619                    qualifiers: vec![],
33620                })
33621                .collect(),
33622            supports: vec![],
33623        };
33624        graph
33625            .admit_records(
33626                graph.empty_root(),
33627                records,
33628                SemanticAdmissionLimits {
33629                    max_records: 8,
33630                    max_terms: 32,
33631                    max_references: 8,
33632                    max_utf8_bytes: 256,
33633                },
33634            )
33635            .unwrap();
33636        let mut session = SemanticTransitionSession::from_hypergraph(graph).unwrap();
33637        session
33638            .bind_task_evaluation(task_binding_tests::task_spec([0, 1, 1], vec![]))
33639            .unwrap();
33640        session
33641    }
33642
33643    fn publication_test_provider() -> (Arc<CudaKernelProvider>, ResidentExecutionDomain) {
33644        let provider = Arc::new(
33645            crate::CudaProviderBuilder::new(
33646                0,
33647                xlog_core::MemoryBudget::with_limit(512 * 1024 * 1024),
33648            )
33649            .with_stream_capacity(1)
33650            .build()
33651            .unwrap(),
33652        );
33653        let runtime = Arc::clone(provider.memory().runtime().unwrap());
33654        let stream_id = runtime.stream_pool().acquire().unwrap();
33655        let stream = runtime.stream_pool().resolve(stream_id).unwrap();
33656        let domain = provider
33657            .bind_resident_execution_domain(runtime, stream_id, stream)
33658            .unwrap();
33659        (provider, domain)
33660    }
33661
33662    pub(super) fn publication_test_parent(provider: &CudaKernelProvider) -> SemanticParentBinding {
33663        let mut counts = [1u64; 55];
33664        counts[15] = 3;
33665        for role in [4, 5, 6, 7, 19, 20, 21, 22, 23, 24, 25, 51, 52, 53, 54] {
33666            counts[role - 1] = 0;
33667        }
33668        let mut records = Vec::new();
33669        let mut model_contract_layout = SemanticModelContractLayout::default();
33670        for role in 1..=55 {
33671            if is_tensor_role(role) || matches!(role, 1..=3 | 14..=16 | 30..=33 | 43 | 47 | 48 | 55)
33672            {
33673                continue;
33674            }
33675            let mut bytes = format!("application record {role}").into_bytes();
33676            if role == 44 {
33677                model_contract_layout = SemanticModelContractLayout {
33678                    schema_begin: 104,
33679                    schema_bytes: bytes.len() as u64,
33680                    schema_digest_offset: 0,
33681                    generation_offset: 32,
33682                    numerical_digest_offset: 40,
33683                    identity_offset: 72,
33684                };
33685                let mut record = vec![0; 104];
33686                record.extend_from_slice(&bytes);
33687                bytes = record;
33688            }
33689            records.push(SemanticStateRecord {
33690                role: SemanticStateRole::from_code(role).unwrap(),
33691                index: 0,
33692                capacity_bytes: 128,
33693                bytes,
33694            });
33695        }
33696        let slot = |token, logical_position, committed| SemanticTextSlot {
33697            token,
33698            logical_position,
33699            kind: 1,
33700            provenance: 1,
33701            valid: 1,
33702            committed,
33703            recomputed: 1,
33704            provenance_record: 0,
33705        };
33706        let mut source = [SemanticTextSlot::default(); 32];
33707        source[0] = slot(7, 0, 0);
33708        source[1] = slot(8, 1, 0);
33709        let model_owner = Arc::new(allocate_publication::<u8>(provider, 4).unwrap());
33710        upload_publication(provider, &18f32.to_le_bytes(), &model_owner).unwrap();
33711        let tensor = crate::dlpack::export_slice_managed_tensor(
33712            Arc::clone(&model_owner),
33713            provider.device().ordinal() as i32,
33714            crate::dlpack::DLDataType {
33715                code: 2,
33716                bits: 32,
33717                lanes: 1,
33718            },
33719            1,
33720            1,
33721        )
33722        .unwrap();
33723        let backing = crate::dlpack::export_slice_managed_tensor(
33724            Arc::clone(&model_owner),
33725            provider.device().ordinal() as i32,
33726            crate::dlpack::DLDataType {
33727                code: 1,
33728                bits: 8,
33729                lanes: 1,
33730            },
33731            1,
33732            4,
33733        )
33734        .unwrap();
33735        // SAFETY: this newly owned export has not been shared. Dropping its
33736        // singleton dimension preserves all four bytes and the original owner;
33737        // the retained shape allocation still owns the selected second entry.
33738        unsafe {
33739            let metadata = &mut (*backing.as_ptr()).dl_tensor;
33740            metadata.ndim = 1;
33741            metadata.shape = metadata.shape.add(1);
33742        }
33743        let model_layout = SemanticTensorLayout {
33744            role: 18,
33745            index: 0,
33746            scalar_type: 6,
33747            element_bytes: 4,
33748            rank: 2,
33749            logical_axis: u64::MAX,
33750            dimensions: [1, 1, 0, 0],
33751            strides_bytes: [4, 4, 0, 0],
33752        };
33753        let mut tensors = (8..=13)
33754            .map(|role| publication_test_tensor(provider, role, role as f32))
33755            .collect::<Vec<_>>();
33756        tensors.push(SemanticTensorInput {
33757            layout: model_layout,
33758            logical_begin: 0,
33759            logical_end: 0,
33760            tensor,
33761            native_allocation: None,
33762        });
33763        let mut parent = SemanticParentBinding {
33764            recovered_instance: None,
33765            source,
33766            prefix: vec![],
33767            ring_head: 2,
33768            provenance_records: 0,
33769            prefix_capacity: 64,
33770            feedback_capacity: 3,
33771            max_position: 262144,
33772            pad_token: 0,
33773            terminal_tokens: vec![100],
33774            final_intent_payload_bytes: 8,
33775            intent_effect: b"record result".to_vec(),
33776            intent_entry_capacity: 4,
33777            intent_payload_capacity_bytes: 256,
33778            acknowledgement_payload_capacity_bytes: 4096,
33779            model_generation: 1,
33780            policy_generation: 1,
33781            neural_generation: 1,
33782            cache_generation: 1,
33783            model_numerical_mode: b"native test numerical mode".to_vec(),
33784            model_contract_layout,
33785            authority_generation: 1,
33786            training_cursor: 0,
33787            training_rng: [1, 2, 3, 4],
33788            fuel: 8,
33789            rng: SemanticRngBinding {
33790                model_generation: 1,
33791                stream_serial: 5,
33792                family_id: 2,
33793                proposal: 0,
33794            },
33795            topology_identity: Identity256::from_bytes([4; 32]),
33796            table_identity: Identity256::from_bytes([5; 32]),
33797            role_counts: counts,
33798            records,
33799            tensors,
33800            model_memory: SemanticModelMemory {
33801                allocations: vec![SemanticTensorInput {
33802                    layout: SemanticTensorLayout {
33803                        role: 0,
33804                        index: 0,
33805                        scalar_type: 1,
33806                        element_bytes: 1,
33807                        rank: 1,
33808                        logical_axis: u64::MAX,
33809                        dimensions: [4, 0, 0, 0],
33810                        strides_bytes: [1, 0, 0, 0],
33811                    },
33812                    logical_begin: 0,
33813                    logical_end: 0,
33814                    tensor: backing,
33815                    native_allocation: None,
33816                }],
33817                storages: vec![SemanticModelStorage {
33818                    allocation: 0,
33819                    byte_offset: 0,
33820                    span_bytes: 4,
33821                }],
33822                views: vec![SemanticModelView {
33823                    role: 18,
33824                    index: 0,
33825                    storage: 0,
33826                    byte_offset: 0,
33827                }],
33828            },
33829            active_layouts: vec![],
33830        };
33831        parent
33832            .bind_initial_sources(
33833                &[SemanticObservedSource {
33834                    identity: "observed-input".into(),
33835                    tokens: vec![7, 8],
33836                    origin: b"complete observed fixture input".to_vec(),
33837                }],
33838                &(0..2)
33839                    .map(|position| SemanticSourceMapping {
33840                        source: "observed-input".into(),
33841                        offset: position,
33842                        logical_position: position,
33843                    })
33844                    .collect::<Vec<_>>(),
33845                b"current fixture authority",
33846                64,
33847            )
33848            .unwrap();
33849        parent
33850    }
33851
33852    #[test]
33853    #[ignore = "requires an explicitly authorized remote CUDA run"]
33854    fn nonempty_initial_prefix_cannot_bind_without_its_prefill_stage() {
33855        let (provider, domain) = publication_test_provider();
33856        let mut session = publication_test_session(Arc::clone(&provider), &domain);
33857        let mut parent = publication_test_parent(&provider);
33858        parent.prefix.push(SemanticTextSlot {
33859            token: 7,
33860            logical_position: 0,
33861            kind: 1,
33862            provenance: 1,
33863            valid: 1,
33864            committed: 1,
33865            ..SemanticTextSlot::default()
33866        });
33867        assert!(matches!(
33868            session.bind_parent(parent),
33869            Err(SemanticTransitionError::InvalidInput { .. })
33870        ));
33871        session
33872            .bind_parent(publication_test_parent(&provider))
33873            .unwrap();
33874    }
33875
33876    fn publication_test_tensor_pair(
33877        provider: &CudaKernelProvider,
33878        layout: SemanticTensorLayout,
33879        bytes: &[u8],
33880    ) -> (SemanticTensorInput, SemanticTensorInput) {
33881        use xlog_core::{ScalarType, Schema};
33882        let owner = allocate_publication::<u8>(provider, bytes.len()).unwrap();
33883        upload_publication(provider, bytes, &owner).unwrap();
33884        let scalar = match layout.scalar_type {
33885            3 => ScalarType::U64,
33886            6 => ScalarType::F32,
33887            8 => ScalarType::Bool,
33888            _ => panic!("fixture tensor has an unsupported scalar type"),
33889        };
33890        let (original, captured) = if layout.rank == 1 {
33891            let buffer = provider
33892                .buffer_from_columns(
33893                    vec![crate::CudaColumn::Owned(owner)],
33894                    layout.dimensions[0],
33895                    Schema::new(vec![("value".into(), scalar)]),
33896                )
33897                .unwrap();
33898            let table = provider.to_dlpack_table(buffer);
33899            (table.column(0).unwrap(), table.column(0).unwrap())
33900        } else {
33901            assert_eq!(layout.rank, 2);
33902            let dtype = match scalar {
33903                ScalarType::U64 => crate::dlpack::DLDataType {
33904                    code: 1,
33905                    bits: 64,
33906                    lanes: 1,
33907                },
33908                ScalarType::F32 => crate::dlpack::DLDataType {
33909                    code: 2,
33910                    bits: 32,
33911                    lanes: 1,
33912                },
33913                _ => unreachable!("fixture matrices use floating point or unsigned integers"),
33914            };
33915            let owner = Arc::new(owner);
33916            let export = || {
33917                crate::dlpack::export_slice_managed_tensor(
33918                    Arc::clone(&owner),
33919                    provider.device().ordinal() as i32,
33920                    dtype,
33921                    layout.dimensions[0] as usize,
33922                    layout.dimensions[1] as usize,
33923                )
33924                .unwrap()
33925            };
33926            (export(), export())
33927        };
33928        let input = |tensor| SemanticTensorInput {
33929            layout,
33930            logical_begin: 0,
33931            logical_end: 0,
33932            tensor,
33933            native_allocation: None,
33934        };
33935        (input(original), input(captured))
33936    }
33937
33938    pub(super) fn publication_test_continuation(
33939        session: &mut SemanticTransitionSession,
33940        old: &SemanticPublishedLease,
33941        provider: &CudaKernelProvider,
33942    ) -> (SemanticContinuationInput, SemanticTensorContentWitness) {
33943        publication_test_continuation_with_numerical_admissibility(session, old, provider, 1)
33944    }
33945
33946    pub(super) fn publication_test_continuation_with_numerical_admissibility(
33947        session: &mut SemanticTransitionSession,
33948        old: &SemanticPublishedLease,
33949        provider: &CudaKernelProvider,
33950        numerical_admissibility: u8,
33951    ) -> (SemanticContinuationInput, SemanticTensorContentWitness) {
33952        assert!(numerical_admissibility <= 1);
33953        let contract = session.publication.as_ref().unwrap().contract_value;
33954        let feedback = session
33955            .read_published_record_bytes(old, SemanticStateRole::RawFeedback)
33956            .unwrap();
33957        assert_eq!(
33958            feedback.len(),
33959            contract.feedback_capacity as usize * size_of::<RawFeedbackRecord>()
33960        );
33961        let mut filled: Vec<_> = old
33962            .source
33963            .iter()
33964            .enumerate()
33965            .filter(|(_, slot)| slot.valid == 1 && slot.kind == 1)
33966            .collect();
33967        let mut masks: Vec<_> = old
33968            .source
33969            .iter()
33970            .enumerate()
33971            .filter(|(_, slot)| slot.valid == 1 && slot.kind == 2)
33972            .collect();
33973        filled.sort_by_key(|(_, slot)| slot.logical_position);
33974        masks.sort_by_key(|(_, slot)| slot.logical_position);
33975        let mut text_rows = vec![0u64; 32 * 2];
33976        for (row, &(slot, source)) in masks.iter().enumerate() {
33977            text_rows[row * 2] = slot as u64;
33978            text_rows[row * 2 + 1] = source.logical_position;
33979        }
33980        let capacity = 32 + contract.feedback_capacity;
33981        let mut active_rows = vec![0u64; capacity as usize * 4];
33982        let mut active_count = 0u64;
33983        let mut append = |physical, slot, position, kind| {
33984            let offset = active_count as usize * 4;
33985            active_rows[offset..offset + 4].copy_from_slice(&[physical, slot, position, kind]);
33986            active_count += 1;
33987        };
33988        for (physical, &(slot, source)) in filled.iter().enumerate() {
33989            append(physical as u64, slot as u64, source.logical_position, 1);
33990        }
33991        for (slot, record) in feedback
33992            .as_chunks::<{ size_of::<RawFeedbackRecord>() }>()
33993            .0
33994            .iter()
33995            .enumerate()
33996        {
33997            let valid = u64::from_ne_bytes(record[..8].try_into().unwrap());
33998            assert!(valid <= 1);
33999            if valid == 1 {
34000                append(
34001                    (filled.len() + slot) as u64,
34002                    32 + slot as u64,
34003                    contract.prefix_capacity + 32 + slot as u64,
34004                    3,
34005                );
34006            }
34007        }
34008        for (offset, &(slot, source)) in masks.iter().enumerate() {
34009            append(
34010                filled.len() as u64 + contract.feedback_capacity + offset as u64,
34011                slot as u64,
34012                source.logical_position,
34013                2,
34014            );
34015        }
34016        let mut tensors = Vec::new();
34017        let mut capture = Vec::new();
34018        for role in 8..=13 {
34019            let layout = SemanticTensorLayout {
34020                role,
34021                index: 0,
34022                scalar_type: 6,
34023                element_bytes: 4,
34024                rank: 2,
34025                logical_axis: u64::MAX,
34026                dimensions: [1, 1, 0, 0],
34027                strides_bytes: [4, 4, 0, 0],
34028            };
34029            let (original, witnessed) =
34030                publication_test_tensor_pair(provider, layout, &(role as f32 + 1.0).to_ne_bytes());
34031            tensors.push(original);
34032            capture.push(witnessed);
34033        }
34034        let service_bytes = [
34035            publication_abi_bytes(&text_rows),
34036            publication_abi_bytes(&[masks.len() as u64]),
34037            vec![0u8; 32],
34038            publication_abi_bytes(&active_rows),
34039            publication_abi_bytes(&[active_count]),
34040            vec![numerical_admissibility],
34041        ];
34042        let layouts = continuation_service_layouts(tensors.len(), capacity, None).unwrap();
34043        let mut services = Vec::new();
34044        for (layout, bytes) in layouts.into_iter().zip(service_bytes) {
34045            let (original, witnessed) = publication_test_tensor_pair(provider, layout, &bytes);
34046            services.push(original.tensor);
34047            capture.push(witnessed);
34048        }
34049        let witness = session.capture_tensor_content(old, capture, 1).unwrap();
34050        let [text_rows, text_row_count, selected_text, active_rows, active_row_count, numerical_admissibility]:
34051            [DlpackManagedTensor; 6] = services.try_into().ok().unwrap();
34052        (
34053            SemanticContinuationInput {
34054                tensors,
34055                authority_decisions: b"current fixture continuation".to_vec(),
34056                text_rows,
34057                text_row_count,
34058                selected_text,
34059                active_rows,
34060                active_row_count,
34061                numerical_admissibility,
34062                numerical_blocks: None,
34063                model_schema_digest: None,
34064                model_identity: None,
34065            },
34066            witness,
34067        )
34068    }
34069
34070    fn publication_test_recompute(
34071        session: &mut SemanticTransitionSession,
34072        old: &SemanticPublishedLease,
34073        provider: &crate::CudaKernelProvider,
34074    ) {
34075        session
34076            .admit_transition(old, SemanticTransitionKind::Recompute)
34077            .unwrap();
34078        let (continuation, witness) = publication_test_continuation(session, old, provider);
34079        session
34080            .bind_continuation(old, continuation, &witness, 1)
34081            .unwrap();
34082        drop(witness);
34083        session.capture().unwrap();
34084        session.launch().unwrap();
34085        session.observe(0).unwrap();
34086    }
34087
34088    #[test]
34089    #[ignore = "requires an explicitly authorized remote CUDA run"]
34090    fn publication_material_native_restore_preserves_acquired_prefix_feedback_and_history() {
34091        let (provider, domain) = publication_test_provider();
34092        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34093        session
34094            .bind_parent(publication_test_parent(&provider))
34095            .unwrap();
34096        let mut old = session.acquire().unwrap();
34097        let old_prefix = session
34098            .read_published_record_bytes(&old, SemanticStateRole::PrefixSource)
34099            .unwrap();
34100        let old_mode = session.published_model_numerical_mode(&old).unwrap();
34101        assert_eq!(old_mode, b"native test numerical mode");
34102        let old_material = session.published_state_material(&old).unwrap();
34103        let (_, alias) = session.published_prefix(&old, 1).unwrap();
34104        publication_test_recompute(&mut session, &old, &provider);
34105        let mut current = session.acquire().unwrap();
34106        assert_eq!(current.header.prefix_extent, old.header.prefix_extent + 1);
34107        assert_eq!(
34108            session
34109                .read_published_record_bytes(&old, SemanticStateRole::PrefixSource)
34110                .unwrap(),
34111            old_prefix
34112        );
34113        assert_eq!(
34114            session.published_state_material(&old).unwrap(),
34115            old_material
34116        );
34117        assert!(session.release(&mut old, &[1]).is_err());
34118        drop(alias);
34119        session.release(&mut old, &[1]).unwrap();
34120        let bytes = session.published_state_material(&current).unwrap();
34121        let original = PublicationMaterial::decode(&bytes).unwrap();
34122        session.release(&mut current, &[]).unwrap();
34123        drop(session);
34124        let mut restored = publication_test_session(Arc::clone(&provider), &domain);
34125        let identity = restored.restore_state_material(&bytes).unwrap();
34126        assert_ne!(identity.instance, original.bank.header.instance);
34127        assert_eq!(identity.logical_digest, original.bank.header.logical_digest);
34128        assert_eq!(identity.state_digest, original.bank.header.state_digest);
34129        let mut lease = restored.acquire().unwrap();
34130        assert_eq!(
34131            restored.published_model_numerical_mode(&lease).unwrap(),
34132            old_mode
34133        );
34134        let reread =
34135            PublicationMaterial::decode(&restored.published_state_material(&lease).unwrap())
34136                .unwrap();
34137        for role in [1, 2, 14, 15, 27, 28, 30, 31, 32, 33, 43] {
34138            assert_eq!(
34139                reread
34140                    .ranges
34141                    .iter()
34142                    .find(|item| item.range.role == role)
34143                    .unwrap()
34144                    .bytes,
34145                original
34146                    .ranges
34147                    .iter()
34148                    .find(|item| item.range.role == role)
34149                    .unwrap()
34150                    .bytes,
34151                "role {role}"
34152            );
34153        }
34154        assert_eq!(reread.graph, original.graph);
34155        restored.release(&mut lease, &[]).unwrap();
34156        drop(restored);
34157        provider.memory().reap_pending_deallocations().unwrap();
34158    }
34159
34160    #[test]
34161    #[ignore = "requires an explicitly authorized remote CUDA run"]
34162    fn publication_material_runtime_reader_rejects_completed_layout_alias_writes() {
34163        let (provider, domain) = publication_test_provider();
34164        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34165        session
34166            .bind_parent(publication_test_parent(&provider))
34167            .unwrap();
34168        let mut lease = session.acquire().unwrap();
34169        let mode = session.published_model_numerical_mode(&lease).unwrap();
34170        let original = session
34171            .read_published_record_bytes(&lease, SemanticStateRole::TensorLayout)
34172            .unwrap();
34173        let alias = session
34174            .published_record(&lease, SemanticStateRole::TensorLayout, 0, 1)
34175            .unwrap();
34176        // SAFETY: the live managed alias retains its descriptor and the exact
34177        // published allocation for the duration of both consumer writes.
34178        let tensor = unsafe { &(*alias.as_ptr()).dl_tensor };
34179        let pointer = tensor.data as usize as u64 + tensor.byte_offset;
34180        // Mutate a layout value and then only the active-computed marker. The
34181        // latter leaves cold layouts intact, so the original seal is necessary.
34182        for offset in [
34183            size_of::<TensorLayoutTableHeader>() + 2 * size_of::<u64>(),
34184            2 * size_of::<u64>(),
34185        ] {
34186            assert!(offset < original.len());
34187            // SAFETY: one in-bounds byte of this retained alias, submitted on
34188            // its registered legacy stream; no further writer is submitted
34189            // until the getter has completed and checked that stream prefix.
34190            assert_eq!(
34191                unsafe {
34192                    sys::cuMemsetD8Async(
34193                        pointer + offset as u64,
34194                        original[offset] ^ 1,
34195                        1,
34196                        std::ptr::null_mut(),
34197                    )
34198                },
34199                sys::cudaError_enum::CUDA_SUCCESS
34200            );
34201            assert!(matches!(
34202                session.published_model_numerical_mode(&lease),
34203                Err(SemanticTransitionError::ObservationMismatch)
34204            ));
34205            // SAFETY: restore this test's byte on the same retained alias and
34206            // registered stream so ordinary retirement sees the original state.
34207            assert_eq!(
34208                unsafe {
34209                    sys::cuMemsetD8Async(
34210                        pointer + offset as u64,
34211                        original[offset],
34212                        1,
34213                        std::ptr::null_mut(),
34214                    )
34215                },
34216                sys::cudaError_enum::CUDA_SUCCESS
34217            );
34218            assert_eq!(
34219                session.published_model_numerical_mode(&lease).unwrap(),
34220                mode
34221            );
34222        }
34223        drop(alias);
34224        session.release(&mut lease, &[1]).unwrap();
34225        drop(session);
34226        provider.memory().reap_pending_deallocations().unwrap();
34227    }
34228
34229    #[test]
34230    #[ignore = "requires an explicitly authorized remote CUDA run; fatal cases use fresh processes"]
34231    fn replay_boundaries_reject_mutated_shared_predecessor_weights() {
34232        const CHILD_KIND: &str = "XLOG_REPLAY_CONTENT_TEST_CHILD";
34233        const COMPLETED: &str =
34234            "shared replay content mutation produced a fatal CUDA completion error";
34235        let Some(kind) = std::env::var_os(CHILD_KIND) else {
34236            let qualified = concat!(
34237                module_path!(),
34238                "::replay_boundaries_reject_mutated_shared_predecessor_weights"
34239            );
34240            let test_name = qualified.split_once("::").unwrap().1;
34241            for kind in ["verify", "evidence", "provenance"] {
34242                let output = std::process::Command::new(std::env::current_exe().unwrap())
34243                    .args([
34244                        "--exact",
34245                        test_name,
34246                        "--ignored",
34247                        "--nocapture",
34248                        "--test-threads=1",
34249                    ])
34250                    .env(CHILD_KIND, kind)
34251                    .output()
34252                    .unwrap();
34253                assert!(
34254                    output.status.success(),
34255                    "{kind} child did not verify a CUDA trap:\n{}\n{}",
34256                    String::from_utf8_lossy(&output.stdout),
34257                    String::from_utf8_lossy(&output.stderr)
34258                );
34259                assert!(
34260                    String::from_utf8_lossy(&output.stdout).contains(COMPLETED),
34261                    "{kind} child did not reach the typed CUDA completion check"
34262                );
34263            }
34264            return;
34265        };
34266        assert!(kind == "verify" || kind == "evidence" || kind == "provenance");
34267        let (provider, domain) = publication_test_provider();
34268        let mut original = publication_test_session(Arc::clone(&provider), &domain);
34269        original
34270            .bind_parent(publication_test_parent(&provider))
34271            .unwrap();
34272        let mut old = original.acquire().unwrap();
34273        let predecessor_bytes = original.published_state_material(&old).unwrap();
34274        publication_test_recompute(&mut original, &old, &provider);
34275        let mut current = original.acquire().unwrap();
34276        let evidence = original.published_replay_evidence(&old, &current).unwrap();
34277        assert!(
34278            original.release_events.is_empty(),
34279            "completed export events must not wait for reader release"
34280        );
34281        let material = SemanticReplayMaterial::decode(
34282            &predecessor_bytes,
34283            &evidence,
34284            old.identity.logical_digest,
34285            current.identity.logical_digest,
34286        )
34287        .unwrap();
34288        original.release(&mut old, &[1]).unwrap();
34289        original.release(&mut current, &[1]).unwrap();
34290        drop(original);
34291
34292        let mut replay = publication_test_session(Arc::clone(&provider), &domain);
34293        replay.restore_replay_material(&material).unwrap();
34294        let predecessor = replay.acquire().unwrap();
34295        publication_test_recompute(&mut replay, &predecessor, &provider);
34296        let successor = replay.acquire().unwrap();
34297        let alias = replay
34298            .published_tensor(&predecessor, SemanticStateRole::SlowWeights, 0, 1)
34299            .unwrap();
34300        let successor_alias = replay
34301            .published_tensor(&successor, SemanticStateRole::SlowWeights, 0, 1)
34302            .unwrap();
34303        // SAFETY: each managed export retains its own actual acquired reader and
34304        // valid DLPack descriptor; the pointers prove these banks share weights.
34305        let tensor = unsafe { &(*alias.as_ptr()).dl_tensor };
34306        let successor_tensor = unsafe { &(*successor_alias.as_ptr()).dl_tensor };
34307        assert_eq!(tensor.byte_offset, 0);
34308        assert_eq!(tensor.data, successor_tensor.data);
34309        let pointer = tensor.data as usize as u64;
34310        drop(successor_alias);
34311        replay
34312            .verify_replay_publication(&material, &predecessor, &successor)
34313            .unwrap();
34314        replay
34315            .published_replay_evidence(&predecessor, &successor)
34316            .unwrap();
34317        replay
34318            .published_replay_provenance(&predecessor, &successor)
34319            .unwrap();
34320        // SAFETY: the fixture's live alias retains four FP32 bytes, and the
34321        // external write uses the actual registered legacy consumer stream.
34322        assert_eq!(
34323            unsafe { sys::cuMemsetD8Async(pointer, 0, 4, std::ptr::null_mut()) },
34324            sys::cudaError_enum::CUDA_SUCCESS
34325        );
34326        if kind == "verify" {
34327            drop(alias);
34328            replay.quiesce_published_reader(&predecessor, &[1]).unwrap();
34329            assert!(replay
34330                .verify_replay_publication(&material, &predecessor, &successor)
34331                .is_err());
34332        } else if kind == "evidence" {
34333            assert!(replay
34334                .published_replay_evidence(&predecessor, &successor)
34335                .is_err());
34336        } else {
34337            assert!(replay
34338                .published_replay_provenance(&predecessor, &successor)
34339                .is_err());
34340        }
34341        // SAFETY: only this disposable child's context has been poisoned. A
34342        // typed fatal CUDA error, not a Rust panic, establishes guard refusal.
34343        let completion = unsafe { sys::cuStreamSynchronize(std::ptr::null_mut()) };
34344        assert!(
34345            matches!(
34346                completion,
34347                sys::cudaError_enum::CUDA_ERROR_ILLEGAL_INSTRUCTION
34348                    | sys::cudaError_enum::CUDA_ERROR_LAUNCH_FAILED
34349            ),
34350            "unexpected CUDA completion: {completion:?}"
34351        );
34352        println!("{COMPLETED}");
34353        std::io::Write::flush(&mut std::io::stdout()).unwrap();
34354        std::process::exit(0);
34355    }
34356
34357    fn publication_test_alias(
34358        session: &mut SemanticTransitionSession,
34359        lease: &SemanticPublishedLease,
34360        role: SemanticStateRole,
34361        consumer_stream: u64,
34362    ) -> SemanticTensorInput {
34363        let layout = session.publication.as_ref().unwrap().layouts[&(role as u64, 0)];
34364        let range = *lease
34365            .directory
34366            .iter()
34367            .find(|range| range.role == role as u64 && range.index == 0)
34368            .unwrap();
34369        let (native_allocation, backing) = session
34370            .published_tensor_allocation(lease, role, 0, consumer_stream)
34371            .unwrap();
34372        drop(backing);
34373        SemanticTensorInput {
34374            layout,
34375            logical_begin: range.logical_begin,
34376            logical_end: range.logical_end,
34377            tensor: session
34378                .published_tensor(lease, role, 0, consumer_stream)
34379                .unwrap(),
34380            native_allocation: Some(native_allocation),
34381        }
34382    }
34383
34384    struct ContentTestExport {
34385        managed: crate::dlpack::DLManagedTensor,
34386        _owner: DlpackManagedTensor,
34387        shape: [i64; 2],
34388        strides: [i64; 2],
34389    }
34390
34391    unsafe extern "C" fn delete_content_test_export(managed: *mut crate::dlpack::DLManagedTensor) {
34392        if managed.is_null() {
34393            return;
34394        }
34395        // SAFETY: content_test_export installs this sole Box owner and deleter;
34396        // its canonical managed backing owns the real allocation until drop.
34397        let owner = unsafe { (*managed).manager_ctx.cast::<ContentTestExport>() };
34398        if !owner.is_null() {
34399            drop(unsafe { Box::from_raw(owner) });
34400        }
34401    }
34402
34403    fn content_test_export(
34404        owner: Arc<TrackedCudaSlice<u8>>,
34405        device_id: i32,
34406        dtype: crate::dlpack::DLDataType,
34407        layout: SemanticTensorLayout,
34408        logical_interval: (u64, u64),
34409    ) -> SemanticTensorInput {
34410        assert_eq!(layout.rank, 2);
34411        let shape = [
34412            i64::try_from(layout.dimensions[0]).unwrap(),
34413            i64::try_from(layout.dimensions[1]).unwrap(),
34414        ];
34415        let strides = [
34416            i64::try_from(layout.strides_bytes[0] / layout.element_bytes).unwrap(),
34417            i64::try_from(layout.strides_bytes[1] / layout.element_bytes).unwrap(),
34418        ];
34419        let backing = crate::dlpack::export_slice_managed_tensor(
34420            owner,
34421            device_id,
34422            dtype,
34423            usize::try_from(shape[0]).unwrap(),
34424            usize::try_from(shape[1]).unwrap(),
34425        )
34426        .unwrap();
34427        // SAFETY: the canonical export owns valid, producer-ready metadata and
34428        // storage. The test producer supplies a genuine view of those bytes,
34429        // retaining both explicit strides and the original owner in one Box.
34430        let source = unsafe { &(*backing.as_ptr()).dl_tensor };
34431        let mut export = Box::new(ContentTestExport {
34432            managed: crate::dlpack::DLManagedTensor {
34433                dl_tensor: crate::dlpack::DLTensor {
34434                    data: source.data,
34435                    device: source.device,
34436                    ndim: 2,
34437                    dtype: source.dtype,
34438                    shape: std::ptr::null_mut(),
34439                    strides: std::ptr::null_mut(),
34440                    byte_offset: source.byte_offset,
34441                },
34442                manager_ctx: std::ptr::null_mut(),
34443                deleter: Some(delete_content_test_export),
34444            },
34445            _owner: backing,
34446            shape,
34447            strides,
34448        });
34449        export.managed.dl_tensor.shape = export.shape.as_mut_ptr();
34450        export.managed.dl_tensor.strides = export.strides.as_mut_ptr();
34451        let owner = Box::into_raw(export);
34452        // SAFETY: the stable Box retains the actual managed CUDA allocation
34453        // and both metadata arrays; the assigned deleter consumes that Box once.
34454        let tensor = unsafe {
34455            (*owner).managed.manager_ctx = owner.cast();
34456            DlpackManagedTensor::from_raw(&mut (*owner).managed)
34457        };
34458        SemanticTensorInput {
34459            layout,
34460            logical_begin: logical_interval.0,
34461            logical_end: logical_interval.1,
34462            tensor,
34463            native_allocation: None,
34464        }
34465    }
34466
34467    #[test]
34468    #[ignore = "requires an explicitly authorized remote CUDA run"]
34469    fn native_feedback_alias_capture_reuses_original_producer_seals() {
34470        let (provider, domain) = publication_test_provider();
34471        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34472        session
34473            .bind_parent(publication_test_parent(&provider))
34474            .unwrap();
34475        let mut lease = session.acquire().unwrap();
34476        session
34477            .admit_transition(&lease, SemanticTransitionKind::Proposal)
34478            .unwrap();
34479        let feedback = session.published_feedback(&lease, 1).unwrap();
34480        let layouts = session.steps[&lease.token].feedback[0]
34481            .content
34482            .tensors
34483            .iter()
34484            .map(|tensor| tensor.layout)
34485            .collect::<Vec<_>>();
34486        let inputs = feedback
34487            .into_dlpack()
34488            .into_iter()
34489            .zip(layouts.iter().copied())
34490            .map(|(tensor, layout)| SemanticTensorInput {
34491                tensor,
34492                layout,
34493                logical_begin: 0,
34494                logical_end: 0,
34495                native_allocation: None,
34496            })
34497            .collect();
34498        let mut other = session.acquire().unwrap();
34499        assert!(
34500            session.capture_tensor_content(&other, inputs, 1).is_err(),
34501            "a second reader must not reseal the first reader's native outputs"
34502        );
34503        session.release(&mut other, &[1]).unwrap();
34504        let feedback = session.published_feedback(&lease, 1).unwrap();
34505        let inputs = feedback
34506            .into_dlpack()
34507            .into_iter()
34508            .zip(layouts)
34509            .map(|(tensor, layout)| SemanticTensorInput {
34510                tensor,
34511                layout,
34512                logical_begin: 0,
34513                logical_end: 0,
34514                native_allocation: None,
34515            })
34516            .collect();
34517        let witness = session.capture_tensor_content(&lease, inputs, 1).unwrap();
34518        let reader = &session.steps[&lease.token];
34519        let TensorContentSeals::Captured(original) = &reader.feedback[1].content.seals else {
34520            panic!("native producer seals");
34521        };
34522        let TensorContentSeals::Captured(consumer) = &reader.content[witness.index].seals else {
34523            panic!("original alias seals");
34524        };
34525        assert_eq!(original.len(), 6);
34526        for (original, consumer) in original.iter().zip(consumer) {
34527            let CapturedTensorDigest::Tensor {
34528                cells: original, ..
34529            } = original
34530            else {
34531                panic!("feedback producer digest");
34532            };
34533            let CapturedTensorDigest::Tensor {
34534                cells: consumer,
34535                producer_sealed,
34536                ..
34537            } = consumer
34538            else {
34539                panic!("feedback alias digest");
34540            };
34541            assert!(
34542                Arc::ptr_eq(original, consumer),
34543                "alias capture must not allocate a replacement digest"
34544            );
34545            assert!(
34546                *producer_sealed,
34547                "alias capture must verify, never overwrite the producer seal"
34548            );
34549        }
34550        drop(witness);
34551        session.release(&mut lease, &[1]).unwrap();
34552        drop(session);
34553        provider.memory().reap_pending_deallocations().unwrap();
34554        assert_eq!(provider.memory().allocated_bytes(), 0);
34555    }
34556
34557    #[test]
34558    #[ignore = "requires an explicitly authorized remote CUDA run"]
34559    fn retained_model_content_survives_reader_retirement_and_bank_reuse() {
34560        let (provider, domain) = publication_test_provider();
34561        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34562        session
34563            .bind_parent(publication_test_parent(&provider))
34564            .unwrap();
34565        let mut lease = session.acquire().unwrap();
34566        let identity = session.published_identity(&lease).unwrap();
34567        let layout = session.publication.as_ref().unwrap().layouts[&(18, 0)];
34568        let live = Arc::new(allocate_publication::<u8>(&provider, 4).unwrap());
34569        upload_publication(&provider, &18.0f32.to_le_bytes(), &live).unwrap();
34570        let producer = || {
34571            content_test_export(
34572                Arc::clone(&live),
34573                provider.device().ordinal() as i32,
34574                crate::dlpack::DLDataType {
34575                    code: 2,
34576                    bits: 32,
34577                    lanes: 1,
34578                },
34579                layout,
34580                (0, 0),
34581            )
34582        };
34583        let witness = session
34584            .bind_model_content(&lease, vec![producer()], 1)
34585            .unwrap();
34586        session
34587            .admit_transition(&lease, SemanticTransitionKind::Recompute)
34588            .unwrap();
34589        let feedback = session.published_feedback(&lease, 1).unwrap();
34590        assert!(session.release_published_reader(&mut lease, &[1]).is_err());
34591        let (continuation, continuation_witness) =
34592            publication_test_continuation(&mut session, &lease, &provider);
34593        session
34594            .bind_continuation(&lease, continuation, &continuation_witness, 1)
34595            .unwrap();
34596        drop(continuation_witness);
34597        session.capture().unwrap();
34598        session.launch().unwrap();
34599        session.observe(0).unwrap();
34600        let (_, bank_alias) = session.published_prefix(&lease, 1).unwrap();
34601        assert!(session.release_published_reader(&mut lease, &[1]).is_err());
34602        assert!(lease.is_active());
34603        drop(bank_alias);
34604        session.release_published_reader(&mut lease, &[1]).unwrap();
34605        assert!(!lease.is_active());
34606        assert_eq!(session.retained_step_identity(&lease).unwrap(), identity);
34607        assert!(session.published_source(&lease, 1).is_err());
34608        assert!(session.quiesce_published_reader(&lease, &[1]).is_err());
34609        assert!(session.release(&mut lease, &[1]).is_err());
34610        for _ in 0..2 {
34611            let mut current = session.acquire().unwrap();
34612            publication_test_recompute(&mut session, &current, &provider);
34613            session.release(&mut current, &[1]).unwrap();
34614        }
34615        let mut reused = session.acquire().unwrap();
34616        assert_eq!((reused.identity.word >> 1) - (identity.word >> 1), 3);
34617        session.release(&mut reused, &[]).unwrap();
34618        let before = session.host_io_stats();
34619        session
34620            .verify_tensor_content(&lease, &witness, vec![producer()], 1)
34621            .unwrap();
34622        assert_eq!(session.host_io_stats(), before);
34623        drop(witness);
34624        assert!(
34625            session.release(&mut lease, &[1]).is_err(),
34626            "original feedback exports retain their step"
34627        );
34628        drop(feedback);
34629        session.release(&mut lease, &[1]).unwrap();
34630        assert!(session.retained_step_identity(&lease).is_err());
34631        drop(live);
34632        drop(session);
34633        provider.memory().reap_pending_deallocations().unwrap();
34634        assert_eq!(provider.memory().allocated_bytes(), 0);
34635    }
34636
34637    #[test]
34638    #[ignore = "requires an explicitly authorized remote CUDA run"]
34639    fn model_content_binding_uses_original_seals_and_retires_each_reader() {
34640        let (provider, domain) = publication_test_provider();
34641        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34642        session
34643            .bind_parent(publication_test_parent(&provider))
34644            .unwrap();
34645        for _ in 0..2 {
34646            let mut lease = session.acquire().unwrap();
34647            let layout = session.publication.as_ref().unwrap().layouts[&(18, 0)];
34648            let live = Arc::new(allocate_publication::<u8>(&provider, 4).unwrap());
34649            upload_publication(&provider, &18.0f32.to_le_bytes(), &live).unwrap();
34650            let producer = || {
34651                content_test_export(
34652                    Arc::clone(&live),
34653                    provider.device().ordinal() as i32,
34654                    crate::dlpack::DLDataType {
34655                        code: 2,
34656                        bits: 32,
34657                        lanes: 1,
34658                    },
34659                    layout,
34660                    (0, 0),
34661                )
34662            };
34663            let original = producer();
34664            let same = producer();
34665            let substituted =
34666                publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
34667            let before = session.host_io_stats();
34668            let witness = session
34669                .bind_model_content(&lease, vec![original], 1)
34670                .unwrap();
34671            assert!(
34672                matches!(
34673                    session.steps[&lease.token].content[witness.index].seals,
34674                    TensorContentSeals::Model(_)
34675                ),
34676                "model binding must not capture a replacement baseline"
34677            );
34678            session
34679                .verify_tensor_content(&lease, &witness, vec![same], 1)
34680                .unwrap();
34681            assert_eq!(session.host_io_stats(), before);
34682            assert!(
34683                session
34684                    .verify_tensor_content(&lease, &witness, vec![substituted], 1)
34685                    .is_err(),
34686                "equal publication bytes cannot replace this invocation's original live storage"
34687            );
34688            assert!(session.release(&mut lease, &[1]).is_err());
34689            drop(witness);
34690            session.release(&mut lease, &[1]).unwrap();
34691            assert!(
34692                session.readers.is_empty(),
34693                "the first reader is not a permanent model baseline"
34694            );
34695        }
34696        drop(session);
34697        provider.memory().reap_pending_deallocations().unwrap();
34698        assert_eq!(provider.memory().allocated_bytes(), 0);
34699        assert_eq!(provider.memory().deallocation_failure_bytes(), 0);
34700    }
34701
34702    #[test]
34703    #[ignore = "requires an explicitly authorized remote CUDA run"]
34704    fn publication_content_guards_preserve_zero_transfer_and_release_parent_alias_witnesses() {
34705        let (provider, domain) = publication_test_provider();
34706        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34707        session
34708            .bind_parent(publication_test_parent(&provider))
34709            .unwrap();
34710        let mut original = session.acquire().unwrap();
34711        let material = session.published_state_material(&original).unwrap();
34712        session.release(&mut original, &[]).unwrap();
34713        drop(session);
34714        let mut session = publication_test_session(Arc::clone(&provider), &domain);
34715        session.restore_state_material(&material).unwrap();
34716        let mut lease = session.acquire().unwrap();
34717        let before_exports = session.host_io_stats();
34718        let sealed_prefix = *lease
34719            .directory
34720            .iter()
34721            .find(|range| range.role == 1)
34722            .unwrap();
34723        let (_, prefix) = session.published_prefix(&lease, 1).unwrap();
34724        let source = session.published_source(&lease, 1).unwrap();
34725        let context = session.published_model_context(&lease, 1).unwrap();
34726        assert!(matches!(
34727            session.published_model_context(&lease, 2),
34728            Err(SemanticTransitionError::InvalidInput { .. })
34729        ));
34730        let outside_alias = session
34731            .published_tensor(&lease, SemanticStateRole::SlowWeights, 0, 1)
34732            .unwrap();
34733        assert_eq!(
34734            session.host_io_stats(),
34735            before_exports,
34736            "native capacity exports must not copy metadata or wait on the host"
34737        );
34738        // SAFETY: the genuine managed export retains its complete descriptor
34739        // and shape array until prefix is dropped below. No device bytes read.
34740        let prefix_tensor = unsafe { &(*prefix.as_ptr()).dl_tensor };
34741        assert_eq!(prefix_tensor.ndim, 2);
34742        assert_eq!(
34743            unsafe { std::slice::from_raw_parts(prefix_tensor.shape, 2) },
34744            [64, 8]
34745        );
34746        assert_eq!(
34747            (prefix_tensor.dtype.code, prefix_tensor.dtype.bits),
34748            (1, 64)
34749        );
34750        let storage = session.publication.as_ref().unwrap();
34751        let bank = storage.banks[(lease.identity.word & 1) as usize].device_ptr_value();
34752        for (tensor, field) in [
34753            (&source, PublicationBankField::Source),
34754            (&context.source, PublicationBankField::Source),
34755            (&context.prefix.1, PublicationBankField::PrefixExtent),
34756            (&context.ring_head, PublicationBankField::RingHead),
34757        ] {
34758            let (range, shape, strides) = field.layout();
34759            // SAFETY: every descriptor and metadata array belongs to the live
34760            // genuine managed export retained above; device bytes are not read.
34761            let tensor = unsafe { &(*tensor.as_ptr()).dl_tensor };
34762            assert_eq!(
34763                tensor.data as usize as u64 + tensor.byte_offset,
34764                bank + range.start as u64
34765            );
34766            assert_eq!((tensor.dtype.code, tensor.dtype.bits), (1, 64));
34767            assert_eq!(tensor.ndim as usize, shape.len());
34768            assert_eq!(
34769                unsafe { std::slice::from_raw_parts(tensor.shape, shape.len()) },
34770                shape
34771            );
34772            assert_eq!(
34773                unsafe { std::slice::from_raw_parts(tensor.strides, strides.len()) },
34774                strides
34775            );
34776        }
34777        let prefix_range = lease
34778            .directory
34779            .iter()
34780            .find(|range| range.role == 3)
34781            .unwrap();
34782        let identity_tensor = unsafe { &(*context.prefix.0.as_ptr()).dl_tensor };
34783        assert_eq!(
34784            identity_tensor.data as usize as u64 + identity_tensor.byte_offset,
34785            storage.allocations[prefix_range.storage_slot as usize].device_ptr_value()
34786                + prefix_range.offset_bytes
34787        );
34788        assert_eq!(
34789            (
34790                identity_tensor.ndim,
34791                identity_tensor.dtype.code,
34792                identity_tensor.dtype.bits
34793            ),
34794            (1, 1, 8)
34795        );
34796        assert_eq!(unsafe { *identity_tensor.shape }, 32);
34797        assert_eq!(context.parent, lease.identity);
34798        assert_eq!(context.descriptor_digest, lease.header.descriptor_digest);
34799        let after_prefix = lease
34800            .directory
34801            .iter()
34802            .find(|range| range.role == 1)
34803            .unwrap();
34804        assert_eq!(
34805            (
34806                after_prefix.logical_begin,
34807                after_prefix.logical_end,
34808                after_prefix.length_bytes,
34809                after_prefix.digest
34810            ),
34811            (
34812                sealed_prefix.logical_begin,
34813                sealed_prefix.logical_end,
34814                sealed_prefix.length_bytes,
34815                sealed_prefix.digest
34816            )
34817        );
34818        drop(prefix);
34819        drop(source);
34820        drop(context);
34821        // Generic producer fixture setup is cold; the original content-guard
34822        // measurement below starts after those fixture uploads and handoffs.
34823        let mut captured = vec![publication_test_alias(
34824            &mut session,
34825            &lease,
34826            SemanticStateRole::SlowWeights,
34827            1,
34828        )];
34829        let mut verified = vec![publication_test_alias(
34830            &mut session,
34831            &lease,
34832            SemanticStateRole::SlowWeights,
34833            1,
34834        )];
34835        let mut owners = Vec::new();
34836        let cases = [
34837            (
34838                SemanticTensorLayout {
34839                    role: 0,
34840                    index: 0,
34841                    scalar_type: 7,
34842                    element_bytes: 8,
34843                    rank: 2,
34844                    logical_axis: u64::MAX,
34845                    dimensions: [1, 3, 0, 0],
34846                    strides_bytes: [24, 8, 0, 0],
34847                },
34848                crate::dlpack::DLDataType {
34849                    code: crate::dlpack::K_DLINT,
34850                    bits: 64,
34851                    lanes: 1,
34852                },
34853                [i64::MIN, -7, i64::MAX]
34854                    .into_iter()
34855                    .flat_map(i64::to_le_bytes)
34856                    .collect::<Vec<_>>(),
34857                (0, 0),
34858            ),
34859            (
34860                SemanticTensorLayout {
34861                    role: 0,
34862                    index: 0,
34863                    scalar_type: 8,
34864                    element_bytes: 1,
34865                    rank: 2,
34866                    logical_axis: u64::MAX,
34867                    dimensions: [1, 3, 0, 0],
34868                    strides_bytes: [3, 1, 0, 0],
34869                },
34870                crate::dlpack::DLDataType {
34871                    code: crate::dlpack::K_DLBOOL,
34872                    bits: 8,
34873                    lanes: 1,
34874                },
34875                vec![0, 1, 1],
34876                (0, 0),
34877            ),
34878            (
34879                SemanticTensorLayout {
34880                    role: 0,
34881                    index: 0,
34882                    scalar_type: 6,
34883                    element_bytes: 4,
34884                    rank: 2,
34885                    logical_axis: u64::MAX,
34886                    dimensions: [2, 3, 0, 0],
34887                    strides_bytes: [4, 8, 0, 0],
34888                },
34889                crate::dlpack::DLDataType {
34890                    code: crate::dlpack::K_DLFLOAT,
34891                    bits: 32,
34892                    lanes: 1,
34893                },
34894                [1.0f32, 4.0, 2.0, 5.0, 3.0, 6.0]
34895                    .into_iter()
34896                    .flat_map(f32::to_le_bytes)
34897                    .collect(),
34898                (0, 0),
34899            ),
34900            (
34901                SemanticTensorLayout {
34902                    role: 0,
34903                    index: 0,
34904                    scalar_type: 6,
34905                    element_bytes: 4,
34906                    rank: 2,
34907                    logical_axis: u64::MAX,
34908                    dimensions: [0, 3, 0, 0],
34909                    strides_bytes: [12, 4, 0, 0],
34910                },
34911                crate::dlpack::DLDataType {
34912                    code: crate::dlpack::K_DLFLOAT,
34913                    bits: 32,
34914                    lanes: 1,
34915                },
34916                Vec::new(),
34917                (0, 0),
34918            ),
34919        ];
34920        for (mut layout, dtype, bytes, interval) in cases {
34921            layout.index = captured.len() as u64;
34922            assert_eq!(tensor_layout_bytes(&layout).unwrap(), bytes.len());
34923            let owner = Arc::new(allocate_publication::<u8>(&provider, bytes.len()).unwrap());
34924            if !bytes.is_empty() {
34925                upload_publication(&provider, &bytes, &owner).unwrap();
34926            }
34927            let device = provider.device().ordinal() as i32;
34928            let rejected = content_test_export(Arc::clone(&owner), device, dtype, layout, interval);
34929            let mut invalid_parent = publication_test_parent(&provider);
34930            invalid_parent.tensors.push(rejected);
34931            let mut admission = publication_test_session(Arc::clone(&provider), &domain);
34932            assert!(matches!(admission.bind_parent(invalid_parent),
34933                Err(SemanticTransitionError::InvalidInput { detail })
34934                    if detail == "initial parent tensor role is duplicate, uncomputed-active, or outside its model roster"));
34935            drop(admission);
34936            captured.push(content_test_export(
34937                Arc::clone(&owner),
34938                device,
34939                dtype,
34940                layout,
34941                interval,
34942            ));
34943            verified.push(content_test_export(
34944                Arc::clone(&owner),
34945                device,
34946                dtype,
34947                layout,
34948                interval,
34949            ));
34950            owners.push(owner);
34951        }
34952        let before = session.host_io_stats();
34953        session
34954            .guard_published_content(
34955                &lease,
34956                &[
34957                    (SemanticStateRole::PrefixSource, 0),
34958                    (SemanticStateRole::SlowWeights, 0),
34959                ],
34960                1,
34961            )
34962            .unwrap();
34963        let witness = session.capture_tensor_content(&lease, captured, 1).unwrap();
34964        session
34965            .verify_tensor_content(&lease, &witness, verified, 1)
34966            .unwrap();
34967        assert_eq!(
34968            session.host_io_stats(),
34969            before,
34970            "content guards must add no host transfers, metadata readback or session stream waits"
34971        );
34972        // SAFETY: protocol stream one is this context's legacy default stream;
34973        // native guard events order its consumers. This is terminal test work.
34974        assert_eq!(
34975            unsafe { sys::cuStreamSynchronize(std::ptr::null_mut()) },
34976            sys::cudaError_enum::CUDA_SUCCESS
34977        );
34978        assert!(
34979            session.release(&mut lease, &[1]).is_err(),
34980            "a live witness retains its reader"
34981        );
34982        assert!(session.quiesce_published_reader(&lease, &[1]).is_err());
34983        drop(witness);
34984        assert!(
34985            session.release(&mut lease, &[1]).is_err(),
34986            "an external alias still retains its reader"
34987        );
34988        assert!(session.quiesce_published_reader(&lease, &[1]).is_err());
34989        drop(outside_alias);
34990        let identity = session.published_identity(&lease).unwrap();
34991        let publication = Arc::clone(session.publication.as_ref().unwrap());
34992        let readers = session
34993            .publication_read(publication.control.view())
34994            .unwrap()[0]
34995            .reader_counts;
34996        session.quiesce_published_reader(&lease, &[1]).unwrap();
34997        assert!(
34998            session.release_events.is_empty(),
34999            "quiescence must retire completed consumer events"
35000        );
35001        assert_eq!(session.published_identity(&lease).unwrap(), identity);
35002        assert!(lease.active);
35003        assert_eq!(
35004            session
35005                .publication_read(publication.control.view())
35006                .unwrap()[0]
35007                .reader_counts,
35008            readers,
35009            "quiescence must retain the actual acquired native reader"
35010        );
35011        session.release(&mut lease, &[1]).unwrap();
35012        drop(session);
35013        drop(owners);
35014        provider.memory().reap_pending_deallocations().unwrap();
35015    }
35016
35017    #[test]
35018    #[ignore = "requires an explicitly authorized remote CUDA run; each fatal case uses a fresh process"]
35019    fn mutated_content_stops_the_dependent_cuda_consumer() {
35020        const CHILD_KIND: &str = "XLOG_CONTENT_GUARD_TEST_CHILD";
35021        const COMPLETED: &str = "content mutation produced a fatal CUDA completion error";
35022        let Some(kind) = std::env::var_os(CHILD_KIND) else {
35023            let qualified = concat!(
35024                module_path!(),
35025                "::mutated_content_stops_the_dependent_cuda_consumer"
35026            );
35027            let test_name = qualified.split_once("::").unwrap().1;
35028            for kind in ["publication", "witness"] {
35029                let output = std::process::Command::new(std::env::current_exe().unwrap())
35030                    .args([
35031                        "--exact",
35032                        test_name,
35033                        "--ignored",
35034                        "--nocapture",
35035                        "--test-threads=1",
35036                    ])
35037                    .env(CHILD_KIND, kind)
35038                    .output()
35039                    .unwrap();
35040                assert!(
35041                    output.status.success(),
35042                    "{kind} child did not verify a CUDA trap:\n{}\n{}",
35043                    String::from_utf8_lossy(&output.stdout),
35044                    String::from_utf8_lossy(&output.stderr)
35045                );
35046                assert!(
35047                    String::from_utf8_lossy(&output.stdout).contains(COMPLETED),
35048                    "{kind} child did not reach the typed CUDA completion check"
35049                );
35050            }
35051            return;
35052        };
35053        assert!(kind == "publication" || kind == "witness");
35054        let (provider, domain) = publication_test_provider();
35055        let mut session = publication_test_session(Arc::clone(&provider), &domain);
35056        session
35057            .bind_parent(publication_test_parent(&provider))
35058            .unwrap();
35059        let lease = session.acquire().unwrap();
35060        let alias = session
35061            .published_tensor(&lease, SemanticStateRole::SlowWeights, 0, 1)
35062            .unwrap();
35063        let captured =
35064            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35065        let unchanged =
35066            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35067        let changed =
35068            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35069        let dependent = allocate_publication::<u8>(&provider, 4).unwrap();
35070        session
35071            .guard_published_content(&lease, &[(SemanticStateRole::SlowWeights, 0)], 1)
35072            .unwrap();
35073        let witness = session
35074            .capture_tensor_content(&lease, vec![captured], 1)
35075            .unwrap();
35076        session
35077            .verify_tensor_content(&lease, &witness, vec![unchanged], 1)
35078            .unwrap();
35079        // SAFETY: fixture aliases retain a real four-byte FP32 allocation in
35080        // this context; synchronization proves the unmodified guards completed.
35081        assert_eq!(
35082            unsafe { sys::cuStreamSynchronize(std::ptr::null_mut()) },
35083            sys::cudaError_enum::CUDA_SUCCESS
35084        );
35085        // SAFETY: this still-owned managed export retains its valid DLPack
35086        // descriptor and allocation until the disposable child exits.
35087        let tensor = unsafe { &(*alias.as_ptr()).dl_tensor };
35088        assert_eq!(tensor.byte_offset, 0);
35089        let pointer = tensor.data as usize as u64;
35090        // SAFETY: this is an external consumer writing its genuine managed
35091        // alias after capture, on the same stream it passes to verification.
35092        assert_eq!(
35093            unsafe { sys::cuMemsetD8Async(pointer, 0, 4, std::ptr::null_mut()) },
35094            sys::cudaError_enum::CUDA_SUCCESS
35095        );
35096        let guarded = if kind == "publication" {
35097            session.guard_published_content(&lease, &[(SemanticStateRole::SlowWeights, 0)], 1)
35098        } else {
35099            session.verify_tensor_content(&lease, &witness, vec![changed], 1)
35100        };
35101        // A fatal asynchronous launch can already surface at event handoff.
35102        // Only the typed CUDA completion below counts as expected rejection.
35103        if let Err(error) = guarded {
35104            eprintln!("content guard handoff: {error}");
35105        }
35106        // SAFETY: both retained buffers have four bytes in this context. The
35107        // native guard orders this dependent consumer on its declared stream.
35108        let copied = unsafe {
35109            sys::cuMemcpyDtoDAsync_v2(
35110                dependent.device_ptr_value(),
35111                pointer,
35112                4,
35113                std::ptr::null_mut(),
35114            )
35115        };
35116        assert!(matches!(
35117            copied,
35118            sys::cudaError_enum::CUDA_SUCCESS
35119                | sys::cudaError_enum::CUDA_ERROR_ILLEGAL_INSTRUCTION
35120                | sys::cudaError_enum::CUDA_ERROR_LAUNCH_FAILED
35121        ));
35122        // SAFETY: terminal completion is deliberately outside the hot guard
35123        // path and belongs only to this disposable child process's CUDA context.
35124        let completion = unsafe { sys::cuStreamSynchronize(std::ptr::null_mut()) };
35125        assert!(
35126            matches!(
35127                completion,
35128                sys::cudaError_enum::CUDA_ERROR_ILLEGAL_INSTRUCTION
35129                    | sys::cudaError_enum::CUDA_ERROR_LAUNCH_FAILED
35130            ),
35131            "unexpected CUDA completion: {completion:?}"
35132        );
35133        println!("{COMPLETED}");
35134        std::io::Write::flush(&mut std::io::stdout()).unwrap();
35135        // The context is poisoned by design. Exit only after checking the
35136        // actual CUDA error; the parent never accepts a panic as trap evidence.
35137        std::process::exit(0);
35138    }
35139
35140    #[test]
35141    #[ignore = "requires an explicitly authorized remote CUDA run; aborted live owners use a fresh process"]
35142    fn aborted_session_retains_step_after_reader_retirement() {
35143        const CHILD: &str = "XLOG_ABORT_RETAINED_STEP_TEST_CHILD";
35144        const COMPLETED: &str =
35145            "aborted retained step kept its original owners without a bank reader";
35146        if std::env::var_os(CHILD).is_none() {
35147            let qualified = concat!(
35148                module_path!(),
35149                "::aborted_session_retains_step_after_reader_retirement"
35150            );
35151            let test_name = qualified.split_once("::").unwrap().1;
35152            let output = std::process::Command::new(std::env::current_exe().unwrap())
35153                .args([
35154                    "--exact",
35155                    test_name,
35156                    "--ignored",
35157                    "--nocapture",
35158                    "--test-threads=1",
35159                ])
35160                .env(CHILD, "1")
35161                .output()
35162                .unwrap();
35163            assert!(
35164                output.status.success(),
35165                "retained-step abort child failed:\n{}\n{}",
35166                String::from_utf8_lossy(&output.stdout),
35167                String::from_utf8_lossy(&output.stderr)
35168            );
35169            assert!(String::from_utf8_lossy(&output.stdout).contains(COMPLETED));
35170            return;
35171        }
35172        let (provider, domain) = publication_test_provider();
35173        let mut session = publication_test_session(Arc::clone(&provider), &domain);
35174        session
35175            .bind_parent(publication_test_parent(&provider))
35176            .unwrap();
35177        let mut lease = session.acquire().unwrap();
35178        let layout = session.publication.as_ref().unwrap().layouts[&(18, 0)];
35179        let live = Arc::new(allocate_publication::<u8>(&provider, 4).unwrap());
35180        upload_publication(&provider, &18.0f32.to_le_bytes(), &live).unwrap();
35181        let producer = || {
35182            content_test_export(
35183                Arc::clone(&live),
35184                provider.device().ordinal() as i32,
35185                crate::dlpack::DLDataType {
35186                    code: 2,
35187                    bits: 32,
35188                    lanes: 1,
35189                },
35190                layout,
35191                (0, 0),
35192            )
35193        };
35194        let witness = session
35195            .bind_model_content(&lease, vec![producer()], 1)
35196            .unwrap();
35197        session.release_published_reader(&mut lease, &[1]).unwrap();
35198        assert!(session.readers.is_empty());
35199        let before = session.host_io_stats();
35200        session.abort();
35201        assert!(matches!(
35202            session.retained_step_identity(&lease),
35203            Err(SemanticTransitionError::Poisoned)
35204        ));
35205        assert!(matches!(
35206            session.verify_tensor_content(&lease, &witness, vec![producer()], 1),
35207            Err(SemanticTransitionError::Poisoned)
35208        ));
35209        assert!(matches!(
35210            session.release(&mut lease, &[1]),
35211            Err(SemanticTransitionError::Poisoned)
35212        ));
35213        assert_eq!(session.host_io_stats(), before);
35214        let prior = UNRELEASED_PUBLICATIONS.with(|owners| owners.borrow().len());
35215        drop(session);
35216        UNRELEASED_PUBLICATIONS.with(|owners| {
35217            let owners = owners.borrow();
35218            assert_eq!(owners.len(), prior + 1);
35219            let retained = owners.last().unwrap();
35220            assert!(retained._readers.is_empty());
35221            let step = &retained._steps[&lease.token];
35222            assert_eq!(step.identity, Some(lease.identity));
35223            assert!(matches!(
35224                step.content[witness.index].seals,
35225                TensorContentSeals::Model(_)
35226            ));
35227            assert_eq!(
35228                step.content[witness.index].tensors[0].data,
35229                live.device_ptr_value()
35230            );
35231        });
35232        println!("{COMPLETED}");
35233        std::io::Write::flush(&mut std::io::stdout()).unwrap();
35234        std::process::exit(0);
35235    }
35236
35237    #[test]
35238    #[ignore = "requires an explicitly authorized remote CUDA run; aborted live owners use a fresh process"]
35239    fn aborted_session_refuses_existing_publication_and_witness_owners() {
35240        const CHILD: &str = "XLOG_ABORT_SESSION_TEST_CHILD";
35241        const COMPLETED: &str = "aborted session rejected retained publication and witness reuse";
35242        if std::env::var_os(CHILD).is_none() {
35243            let qualified = concat!(
35244                module_path!(),
35245                "::aborted_session_refuses_existing_publication_and_witness_owners"
35246            );
35247            let test_name = qualified.split_once("::").unwrap().1;
35248            let output = std::process::Command::new(std::env::current_exe().unwrap())
35249                .args([
35250                    "--exact",
35251                    test_name,
35252                    "--ignored",
35253                    "--nocapture",
35254                    "--test-threads=1",
35255                ])
35256                .env(CHILD, "1")
35257                .output()
35258                .unwrap();
35259            assert!(
35260                output.status.success(),
35261                "abort child did not verify unusable retained owners:\n{}\n{}",
35262                String::from_utf8_lossy(&output.stdout),
35263                String::from_utf8_lossy(&output.stderr)
35264            );
35265            assert!(
35266                String::from_utf8_lossy(&output.stdout).contains(COMPLETED),
35267                "abort child did not finish the native Poisoned checks"
35268            );
35269            return;
35270        }
35271        let (provider, domain) = publication_test_provider();
35272        let mut session = publication_test_session(Arc::clone(&provider), &domain);
35273        session
35274            .bind_parent(publication_test_parent(&provider))
35275            .unwrap();
35276        let lease = session.acquire().unwrap();
35277        let _outside_alias = session
35278            .published_tensor(&lease, SemanticStateRole::SlowWeights, 0, 1)
35279            .unwrap();
35280        let captured =
35281            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35282        let unchanged =
35283            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35284        let refused_capture =
35285            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35286        let refused_verify =
35287            publication_test_alias(&mut session, &lease, SemanticStateRole::SlowWeights, 1);
35288        let witness = session
35289            .capture_tensor_content(&lease, vec![captured], 1)
35290            .unwrap();
35291        session
35292            .verify_tensor_content(&lease, &witness, vec![unchanged], 1)
35293            .unwrap();
35294        let identity = session.published_identity(&lease).unwrap();
35295        assert!(!session.published_range_keys(&lease).unwrap().is_empty());
35296        // SAFETY: native events order this context's declared default consumer;
35297        // complete the genuine pre-abort witness before testing invalidation.
35298        assert_eq!(
35299            unsafe { sys::cuStreamSynchronize(std::ptr::null_mut()) },
35300            sys::cudaError_enum::CUDA_SUCCESS
35301        );
35302        let before = session.host_io_stats();
35303        session.abort();
35304        session.abort();
35305        assert!(session.is_poisoned());
35306        assert_eq!(
35307            session.host_io_stats(),
35308            before,
35309            "abort must not synchronize or transfer retained content"
35310        );
35311        assert!(
35312            session.publication.is_some(),
35313            "abort must retain live publication storage"
35314        );
35315        assert!(
35316            session.readers.contains_key(&lease.token),
35317            "abort must retain existing reader owners"
35318        );
35319        assert_eq!(
35320            lease.identity, identity,
35321            "an aborted Session retains its lease's historical identity"
35322        );
35323        assert!(matches!(
35324            session.acquire(),
35325            Err(SemanticTransitionError::Poisoned)
35326        ));
35327        assert!(matches!(
35328            session.published_identity(&lease),
35329            Err(SemanticTransitionError::Poisoned)
35330        ));
35331        assert!(matches!(
35332            session.published_range_keys(&lease),
35333            Err(SemanticTransitionError::Poisoned)
35334        ));
35335        assert!(matches!(
35336            session.published_tensor(&lease, SemanticStateRole::SlowWeights, 0, 1),
35337            Err(SemanticTransitionError::Poisoned)
35338        ));
35339        assert!(matches!(
35340            session.published_prefix(&lease, 1),
35341            Err(SemanticTransitionError::Poisoned)
35342        ));
35343        assert!(matches!(
35344            session.guard_published_content(&lease, &[(SemanticStateRole::SlowWeights, 0)], 1),
35345            Err(SemanticTransitionError::Poisoned)
35346        ));
35347        assert!(matches!(
35348            session.capture_tensor_content(&lease, vec![refused_capture], 1),
35349            Err(SemanticTransitionError::Poisoned)
35350        ));
35351        assert!(matches!(
35352            session.verify_tensor_content(&lease, &witness, vec![refused_verify], 1),
35353            Err(SemanticTransitionError::Poisoned)
35354        ));
35355        assert!(matches!(
35356            session.capture(),
35357            Err(SemanticTransitionError::Poisoned)
35358        ));
35359        assert!(matches!(
35360            session.launch(),
35361            Err(SemanticTransitionError::Poisoned)
35362        ));
35363        assert!(matches!(
35364            session.bind_task_evaluation(task_binding_tests::task_spec([0, 1, 1], vec![])),
35365            Err(SemanticTransitionError::Poisoned)
35366        ));
35367        assert!(session.is_poisoned());
35368        println!("{COMPLETED}");
35369        std::io::Write::flush(&mut std::io::stdout()).unwrap();
35370        // Abort deliberately keeps historical owners unusable and retained.
35371        // Isolate their teardown from every other test; a panic is not success.
35372        std::process::exit(0);
35373    }
35374
35375    // Codec-only sample: it intentionally has no native publication authority.
35376    // Actual hashes and replayable graph content are checked by restore on GPU.
35377    fn publication_material_sample() -> PublicationMaterial {
35378        let mut counts = [1u64; 55];
35379        counts[15] = 3;
35380        let layouts: BTreeMap<_, _> = (1..=55)
35381            .filter(|&role| is_tensor_role(role))
35382            .map(|role| {
35383                (
35384                    (role, 0),
35385                    SemanticTensorLayout {
35386                        role,
35387                        index: 0,
35388                        scalar_type: 6,
35389                        element_bytes: 4,
35390                        rank: 2,
35391                        logical_axis: u64::MAX,
35392                        dimensions: [1, 1, 0, 0],
35393                        strides_bytes: [4, 4, 0, 0],
35394                    },
35395                )
35396            })
35397            .collect();
35398        let mut ranges = Vec::new();
35399        for (ordinal, &count) in counts.iter().enumerate() {
35400            for index in 0..count {
35401                let role = ordinal as u64 + 1;
35402                let bytes = if role == 55 {
35403                    tensor_table_bytes(&layouts.values().copied().collect::<Vec<_>>(), false, &[])
35404                        .unwrap()
35405                } else if role == 44 {
35406                    let mut bytes = vec![0; 104];
35407                    bytes.extend_from_slice(&[44, index as u8, 0x80, 0xff]);
35408                    bytes
35409                } else if role == 32 {
35410                    publication_abi_bytes(&[AcknowledgementQueueHeader {
35411                        abi: 1,
35412                        payload_capacity_bytes: 128,
35413                        ..AcknowledgementQueueHeader::default()
35414                    }])
35415                } else {
35416                    vec![role as u8, index as u8, 0x80, 0xff]
35417                };
35418                ranges.push(PublicationMaterialRange {
35419                    range: PublicationRange {
35420                        role,
35421                        index,
35422                        generation: 1,
35423                        length_bytes: bytes.len() as u64,
35424                        storage_slot: ranges.len() as u64,
35425                        ..PublicationRange::default()
35426                    },
35427                    capacity: bytes.len() + 128,
35428                    bytes,
35429                });
35430            }
35431        }
35432        let header = PublicationHeader {
35433            abi: 1,
35434            model_generation: 7,
35435            authority_generation: 3,
35436            sealed_epoch: 8,
35437            publication_word: 16,
35438            range_count: ranges.len() as u64,
35439            state_digest: Identity256::from_bytes([29; 32]),
35440            ..PublicationHeader::default()
35441        };
35442        let mut model_memory = ModelMemoryGeometry::default();
35443        let mut model_allocations = Vec::new();
35444        for range in ranges
35445            .iter_mut()
35446            .filter(|range| matches!(range.range.role, 18..=25))
35447        {
35448            let ordinal = model_allocations.len() as u64;
35449            let mut bytes = vec![0; range.capacity];
35450            bytes[..range.bytes.len()].copy_from_slice(&range.bytes);
35451            range.range.backing_digest = Identity256::from_bytes(Sha256::digest(&bytes).into());
35452            model_memory.allocation_bytes.push(bytes.len() as u64);
35453            model_memory.storages.push(SemanticModelStorage {
35454                allocation: ordinal,
35455                byte_offset: 0,
35456                span_bytes: bytes.len() as u64,
35457            });
35458            model_memory.views.push(SemanticModelView {
35459                role: range.range.role,
35460                index: range.range.index,
35461                storage: ordinal,
35462                byte_offset: 0,
35463            });
35464            model_allocations.push(bytes);
35465        }
35466        let mut material = PublicationMaterial {
35467            bank: PublicationBank {
35468                header,
35469                source: [SemanticTextSlot::default(); 32],
35470                state: DeviceState::default(),
35471                receipts: [SemanticTransitionReceipt::default(); COMPONENT_COUNT],
35472            },
35473            contract: PublicationContract {
35474                abi: 1,
35475                model_generation: 7,
35476                authority_generation: 3,
35477                window_capacity: 32,
35478                role_count: 55,
35479                range_capacity: ranges.len() as u64,
35480                terminal_token_count: 1,
35481                model_contract_layout: SemanticModelContractLayout {
35482                    schema_begin: 104,
35483                    schema_bytes: 4,
35484                    schema_digest_offset: 0,
35485                    generation_offset: 32,
35486                    numerical_digest_offset: 40,
35487                    identity_offset: 72,
35488                },
35489                ..PublicationContract::default()
35490            },
35491            role_counts: counts,
35492            terminals: vec![3],
35493            layouts,
35494            model_memory,
35495            model_allocations,
35496            ranges,
35497            graph: SemanticRootMaterial {
35498                records: SemanticAdmissionRecords {
35499                    predicates: vec![],
35500                    records: vec![],
35501                    supports: vec![],
35502                },
35503                symbols: vec![],
35504                insertions: vec![],
35505                digest: [0; 32],
35506                extents: [0; 3],
35507                admission_base_digest: [0; 32],
35508                admission_base_extents: [0; 3],
35509            },
35510            learning_phases: Vec::new(),
35511        };
35512        publication_material_sample_runtime(&mut material);
35513        for range in &mut material.ranges {
35514            if !is_tensor_role(range.range.role) {
35515                range.range.digest = range.original_record_digest();
35516            }
35517        }
35518        material.bank.header.descriptor_digest = material.original_descriptor_digest();
35519        material
35520    }
35521
35522    // Build the fixture's cold contract only after its allocation geometry is
35523    // chosen. This helper is not a repair operation on imported material.
35524    fn publication_material_sample_runtime(material: &mut PublicationMaterial) {
35525        material.bank.header.model_geometry_digest =
35526            material.model_memory.digest(&material.layouts).unwrap();
35527        let runtime = initial_runtime_contract_record(
35528            material.contract,
35529            &material.role_counts,
35530            &material.terminals,
35531            &material.layouts,
35532            material
35533                .ranges
35534                .iter()
35535                .filter(|item| item.range.role != 43)
35536                .map(|item| (item.range.role, item.range.index, item.capacity))
35537                .collect(),
35538            b"codec sample numerical mode",
35539            &material.model_memory,
35540        )
35541        .unwrap();
35542        let record = material
35543            .ranges
35544            .iter_mut()
35545            .find(|item| item.range.role == 43)
35546            .unwrap();
35547        record.capacity = runtime.capacity_bytes;
35548        record.bytes = runtime.bytes;
35549        record.range.length_bytes = record.bytes.len() as u64;
35550        record.range.digest = record.original_record_digest();
35551    }
35552
35553    #[test]
35554    fn publication_material_codec_preserves_all_ranges_and_rejects_incomplete_content() {
35555        let material = publication_material_sample();
35556        let bytes = material.encode().unwrap();
35557        let decoded = PublicationMaterial::decode(&bytes).unwrap();
35558        assert_eq!(decoded.encode().unwrap(), bytes);
35559        assert_eq!(decoded.ranges.len(), material.ranges.len());
35560        for (saved, actual) in material.ranges.iter().zip(&decoded.ranges) {
35561            assert_eq!(saved.bytes, actual.bytes);
35562            assert_eq!(saved.capacity, actual.capacity);
35563        }
35564        for boundary in [
35565            0,
35566            25,
35567            26,
35568            29,
35569            30,
35570            61,
35571            62,
35572            100,
35573            bytes.len() / 2,
35574            bytes.len() - 1,
35575        ] {
35576            assert!(PublicationMaterial::decode(&bytes[..boundary]).is_err());
35577        }
35578        let mut changed = bytes.clone();
35579        changed.push(0);
35580        assert!(PublicationMaterial::decode(&changed).is_err());
35581        changed = bytes.clone();
35582        changed[30] ^= 1;
35583        assert!(PublicationMaterial::decode(&changed).is_err());
35584        let mut incomplete = publication_material_sample();
35585        incomplete.ranges.pop();
35586        assert!(incomplete.encode().is_err());
35587        let mut reordered = publication_material_sample();
35588        reordered.ranges.swap(0, 1);
35589        assert!(reordered.encode().is_err());
35590        let mut address = publication_material_sample();
35591        address.contract.terminal_tokens = 0x1000;
35592        assert!(address.encode().is_err());
35593        let mut mismatched = publication_material_sample();
35594        mismatched.layouts.get_mut(&(4, 0)).unwrap().scalar_type = 2;
35595        assert!(mismatched.encode().is_err());
35596    }
35597
35598    #[test]
35599    fn publication_material_runtime_preserves_mode_and_exact_self_capacity() {
35600        let material = publication_material_sample();
35601        let bytes = material.encode().unwrap();
35602        let restored = PublicationMaterial::decode(&bytes).unwrap();
35603        assert_eq!(
35604            restored.model_numerical_mode().unwrap(),
35605            b"codec sample numerical mode"
35606        );
35607        let record = restored
35608            .ranges
35609            .iter()
35610            .find(|item| item.range.role == 43)
35611            .unwrap();
35612        assert_eq!(record.capacity, record.bytes.len());
35613        assert_eq!(restored.encode().unwrap(), bytes);
35614        let capacities = material
35615            .ranges
35616            .iter()
35617            .map(|item| (item.range.role, item.range.index, item.capacity))
35618            .collect::<Vec<_>>();
35619        let mut relocated = material.contract;
35620        relocated.terminal_tokens = 0x1020304050607080;
35621        relocated.role_counts = 0x8070605040302010;
35622        relocated.semantic_owner = 99;
35623        let original = runtime_contract_bytes(
35624            relocated,
35625            &material.role_counts,
35626            &material.terminals,
35627            &material.layouts,
35628            &capacities,
35629            material.model_numerical_mode().unwrap(),
35630            &material.model_memory,
35631        )
35632        .unwrap();
35633        assert_eq!(
35634            original, record.bytes,
35635            "runtime addresses and owner handles are not portable identity"
35636        );
35637        assert_ne!(
35638            runtime_contract_bytes(
35639                relocated,
35640                &material.role_counts,
35641                &material.terminals,
35642                &material.layouts,
35643                &capacities,
35644                b"different complete mode",
35645                &material.model_memory
35646            )
35647            .unwrap(),
35648            original
35649        );
35650        assert!(runtime_contract_bytes(
35651            relocated,
35652            &material.role_counts,
35653            &material.terminals,
35654            &material.layouts,
35655            &capacities,
35656            b"",
35657            &material.model_memory
35658        )
35659        .is_err());
35660        assert!(
35661            initial_runtime_contract_record(
35662                relocated,
35663                &material.role_counts,
35664                &material.terminals,
35665                &material.layouts,
35666                capacities,
35667                b"mode",
35668                &material.model_memory
35669            )
35670            .is_err(),
35671            "caller runtime entry cannot be inserted twice"
35672        );
35673    }
35674
35675    #[test]
35676    fn publication_material_runtime_binds_logical_contract_and_terminals() {
35677        let mut changed = publication_material_sample();
35678        changed.contract.max_position += 1;
35679        assert!(
35680            changed.encode().is_err(),
35681            "runtime record must bind the actual position contract"
35682        );
35683        let mut changed = publication_material_sample();
35684        changed.terminals[0] += 1;
35685        assert!(
35686            changed.encode().is_err(),
35687            "runtime record must retain actual terminal values"
35688        );
35689    }
35690
35691    #[test]
35692    fn publication_material_runtime_binds_allocation_capacity() {
35693        let mut changed = publication_material_sample();
35694        changed
35695            .ranges
35696            .iter_mut()
35697            .find(|range| range.range.role == 2)
35698            .unwrap()
35699            .capacity += 1;
35700        assert!(
35701            changed.encode().is_err(),
35702            "runtime record must bind actual cold capacity"
35703        );
35704    }
35705
35706    #[test]
35707    fn publication_material_runtime_rejects_changed_original_layout_table() {
35708        let material = publication_material_sample();
35709        assert_eq!(
35710            material.model_numerical_mode().unwrap(),
35711            b"codec sample numerical mode"
35712        );
35713        let table_index = material
35714            .ranges
35715            .iter()
35716            .position(|item| item.range.role == 55)
35717            .unwrap();
35718        for byte in 0..material.ranges[table_index].bytes.len() {
35719            let mut changed = publication_material_sample();
35720            changed.ranges[table_index].bytes[byte] ^= 1;
35721            assert!(
35722                changed.model_numerical_mode().is_err(),
35723                "changed table byte {byte}"
35724            );
35725        }
35726    }
35727
35728    #[test]
35729    fn publication_material_runtime_rejects_resealed_layout_disagreement() {
35730        let mut changed = publication_material_sample();
35731        let table = changed
35732            .ranges
35733            .iter_mut()
35734            .find(|item| item.range.role == 55)
35735            .unwrap();
35736        let (_, mut layouts, active) = decode_tensor_table(&table.bytes).unwrap();
35737        layouts[0].scalar_type = 2;
35738        table.bytes = tensor_table_bytes(&layouts, active.computed, &active.rows).unwrap();
35739        table.range.digest = table.original_record_digest();
35740        assert!(changed.model_numerical_mode().is_err());
35741    }
35742
35743    #[test]
35744    fn publication_material_runtime_allows_sealed_active_table_changes() {
35745        let mut changed = publication_material_sample();
35746        let mode = changed.model_numerical_mode().unwrap().to_vec();
35747        let table = changed
35748            .ranges
35749            .iter_mut()
35750            .find(|item| item.range.role == 55)
35751            .unwrap();
35752        let (_, layouts, _) = decode_tensor_table(&table.bytes).unwrap();
35753        table.bytes = tensor_table_bytes(&layouts, true, &[]).unwrap();
35754        table.range.digest = table.original_record_digest();
35755        assert_eq!(changed.model_numerical_mode().unwrap(), mode);
35756    }
35757
35758    #[test]
35759    fn publication_material_runtime_refuses_opaque_replacement_even_if_resealed() {
35760        let mut changed = publication_material_sample();
35761        let runtime = changed
35762            .ranges
35763            .iter_mut()
35764            .find(|range| range.range.role == 43)
35765            .unwrap();
35766        runtime.bytes.fill(0);
35767        runtime.range.digest = runtime.original_record_digest();
35768        changed.bank.header.descriptor_digest = changed.original_descriptor_digest();
35769        assert!(
35770            changed.encode().is_err(),
35771            "opaque caller bytes are not the native runtime contract"
35772        );
35773    }
35774
35775    #[test]
35776    fn capacity_prefix_export_preserves_extent_without_narrowing_shape() {
35777        let mut range = PublicationRange {
35778            role: 1,
35779            index: 0,
35780            generation: 1,
35781            length_bytes: 128,
35782            logical_begin: 0,
35783            logical_end: 2,
35784            ..PublicationRange::default()
35785        };
35786        let layout = committed_prefix_layout(&range, 8).unwrap();
35787        assert_eq!(layout.dimensions, [8, 8, 0, 0]);
35788        assert_eq!(tensor_layout_bytes(&layout).unwrap(), 512);
35789        assert_eq!(
35790            (range.logical_begin, range.logical_end, range.length_bytes),
35791            (0, 2, 128)
35792        );
35793        range.logical_end = 0;
35794        range.length_bytes = 0;
35795        assert_eq!(
35796            committed_prefix_layout(&range, 8).unwrap().dimensions,
35797            [8, 8, 0, 0]
35798        );
35799        assert!(committed_prefix_layout(
35800            &PublicationRange {
35801                logical_end: 9,
35802                length_bytes: 576,
35803                ..range
35804            },
35805            8
35806        )
35807        .is_err());
35808    }
35809
35810    #[test]
35811    fn capacity_export_stream_rejects_ambiguous_default_handles() {
35812        assert!(dlpack_consumer_stream(0).is_err());
35813        assert!(dlpack_consumer_stream(2).is_err());
35814        assert!(dlpack_consumer_stream(1).unwrap().is_null());
35815        // Resolving a handle does not assert that the stream exists. The
35816        // driver checks the concrete handle during the ordered handoff.
35817        assert_eq!(dlpack_consumer_stream(4096).unwrap() as usize, 4096);
35818    }
35819
35820    #[test]
35821    fn capacity_export_bounds_keep_seal_and_allocation_limits_distinct() {
35822        let range = PublicationRange {
35823            role: 1,
35824            index: 0,
35825            generation: 1,
35826            offset_bytes: 64,
35827            length_bytes: 128,
35828            logical_begin: 0,
35829            logical_end: 2,
35830            ..PublicationRange::default()
35831        };
35832        let layout = SemanticTensorLayout {
35833            role: 1,
35834            index: 0,
35835            scalar_type: 3,
35836            element_bytes: 8,
35837            rank: 2,
35838            logical_axis: 0,
35839            dimensions: [8, 8, 0, 0],
35840            strides_bytes: [64, 8, 0, 0],
35841        };
35842        assert_eq!(
35843            publication_export_span(&range, &layout, 576).unwrap(),
35844            64..576
35845        );
35846        assert!(publication_export_span(&range, &layout, 575).is_err());
35847        assert_eq!(
35848            (range.length_bytes, range.logical_begin, range.logical_end),
35849            (128, 0, 2)
35850        );
35851        for wrong in [
35852            PublicationRange {
35853                generation: 2,
35854                ..range
35855            },
35856            PublicationRange {
35857                offset_bytes: 65,
35858                ..range
35859            },
35860            PublicationRange {
35861                offset_bytes: u64::MAX - 7,
35862                ..range
35863            },
35864            PublicationRange {
35865                length_bytes: 513,
35866                ..range
35867            },
35868            PublicationRange {
35869                logical_end: 9,
35870                ..range
35871            },
35872            PublicationRange { index: 1, ..range },
35873        ] {
35874            assert!(publication_export_span(&wrong, &layout, 576).is_err());
35875        }
35876        let tensor = SemanticTensorLayout {
35877            role: 4,
35878            rank: 4,
35879            logical_axis: 2,
35880            dimensions: [1, 2, 8, 2],
35881            strides_bytes: [128, 64, 8, 4],
35882            scalar_type: 6,
35883            element_bytes: 4,
35884            ..layout
35885        };
35886        let tensor_range = PublicationRange {
35887            role: 4,
35888            offset_bytes: 0,
35889            length_bytes: 128,
35890            ..range
35891        };
35892        assert_eq!(
35893            publication_export_span(&tensor_range, &tensor, 128).unwrap(),
35894            0..128
35895        );
35896        let model = SemanticTensorLayout {
35897            role: 18,
35898            logical_axis: u64::MAX,
35899            ..tensor
35900        };
35901        assert_eq!(
35902            publication_export_span(
35903                &PublicationRange {
35904                    role: 18,
35905                    logical_begin: 0,
35906                    logical_end: 0,
35907                    ..tensor_range
35908                },
35909                &model,
35910                128
35911            )
35912            .unwrap(),
35913            0..128
35914        );
35915        assert!(publication_export_span(
35916            &PublicationRange {
35917                role: 18,
35918                length_bytes: 16,
35919                logical_begin: 0,
35920                logical_end: 0,
35921                ..tensor_range
35922            },
35923            &model,
35924            128
35925        )
35926        .is_err());
35927    }
35928
35929    #[test]
35930    fn committed_prefix_export_layout_preserves_native_rows_and_empty_extent() {
35931        let range = PublicationRange {
35932            role: SemanticStateRole::PrefixSource as u64,
35933            index: 0,
35934            generation: 1,
35935            offset_bytes: 64,
35936            length_bytes: 128,
35937            logical_begin: 0,
35938            logical_end: 2,
35939            ..PublicationRange::default()
35940        };
35941        let layout = committed_prefix_layout(&range, 2).unwrap();
35942        assert_eq!(
35943            (layout.scalar_type, layout.element_bytes, layout.rank),
35944            (3, 8, 2)
35945        );
35946        assert_eq!(layout.dimensions, [2, 8, 0, 0]);
35947        assert_eq!(layout.strides_bytes, [64, 8, 0, 0]);
35948        assert_eq!(tensor_layout_bytes(&layout).unwrap(), 128);
35949        let row = SemanticTextSlot {
35950            token: 71,
35951            logical_position: 1,
35952            kind: 1,
35953            provenance: 2,
35954            valid: 1,
35955            committed: 1,
35956            recomputed: 1,
35957            provenance_record: 19,
35958        };
35959        let words = publication_abi_bytes(&[row])
35960            .as_chunks::<8>()
35961            .0
35962            .iter()
35963            .map(|bytes| u64::from_ne_bytes(*bytes))
35964            .collect::<Vec<_>>();
35965        assert_eq!(words, [71, 1, 1, 2, 1, 1, 1, 19]);
35966        let empty = committed_prefix_layout(
35967            &PublicationRange {
35968                length_bytes: 0,
35969                logical_end: 0,
35970                ..range
35971            },
35972            0,
35973        )
35974        .unwrap();
35975        assert_eq!(empty.dimensions, [0, 8, 0, 0]);
35976        assert_eq!(empty.strides_bytes, [64, 8, 0, 0]);
35977        assert_eq!(tensor_layout_bytes(&empty).unwrap(), 0);
35978    }
35979
35980    #[test]
35981    fn committed_prefix_export_rejects_inconsistent_or_unaligned_extent() {
35982        let valid = PublicationRange {
35983            role: 1,
35984            index: 0,
35985            generation: 1,
35986            length_bytes: 128,
35987            logical_begin: 0,
35988            logical_end: 2,
35989            ..PublicationRange::default()
35990        };
35991        for wrong in [
35992            PublicationRange { role: 2, ..valid },
35993            PublicationRange { index: 1, ..valid },
35994            PublicationRange {
35995                offset_bytes: 1,
35996                ..valid
35997            },
35998            PublicationRange {
35999                logical_begin: 1,
36000                ..valid
36001            },
36002            PublicationRange {
36003                logical_end: 3,
36004                ..valid
36005            },
36006            PublicationRange {
36007                length_bytes: 64,
36008                ..valid
36009            },
36010            PublicationRange {
36011                length_bytes: 192,
36012                ..valid
36013            },
36014        ] {
36015            assert!(committed_prefix_layout(&wrong, 2).is_err());
36016        }
36017        assert!(committed_prefix_layout(&valid, u64::MAX).is_err());
36018        assert!(committed_prefix_layout(&valid, 0).is_err());
36019    }
36020
36021    #[test]
36022    fn publication_material_decode_checks_original_descriptor_before_relocation() {
36023        let material = publication_material_sample();
36024        let original = material.encode().unwrap();
36025        assert!(PublicationMaterial::decode(&original).is_ok());
36026
36027        for field in 0..4 {
36028            let mut changed = publication_material_sample();
36029            match field {
36030                0 => changed.bank.header.instance = Identity256::from_bytes([71; 32]),
36031                1 => changed.bank.header.recovered_instance = Identity256::from_bytes([72; 32]),
36032                2 => changed.bank.header.semantic_owner ^= 1,
36033                3 => changed.ranges[0].range.storage_slot ^= 1,
36034                _ => unreachable!(),
36035            }
36036            assert!(
36037                PublicationMaterial::decode(&changed.encode().unwrap()).is_err(),
36038                "cold decoding accepted changed original descriptor field {field}"
36039            );
36040        }
36041    }
36042
36043    #[test]
36044    fn publication_material_decode_checks_original_record_bytes() {
36045        // These records contain origin coordinates omitted by normalized state
36046        // hashing. A saved descriptor is insufficient without their raw seals.
36047        for role in [2, 14, 15, 30, 33, 48] {
36048            let mut changed = publication_material_sample();
36049            let record = changed
36050                .ranges
36051                .iter_mut()
36052                .find(|item| item.range.role == role)
36053                .unwrap();
36054            record.bytes[0] ^= 1;
36055            assert!(
36056                PublicationMaterial::decode(&changed.encode().unwrap()).is_err(),
36057                "cold decoding accepted altered original record {role}"
36058            );
36059        }
36060        for word in [1, 5, 6, 39] {
36061            let mut changed = publication_material_sample();
36062            let record = changed
36063                .ranges
36064                .iter_mut()
36065                .find(|item| item.range.role == 33)
36066                .unwrap();
36067            record.bytes = publication_abi_bytes(&[AttemptReceipt::default()]);
36068            record.range.length_bytes = record.bytes.len() as u64;
36069            record.capacity = record.bytes.len();
36070            record.range.digest = record.original_record_digest();
36071            publication_material_sample_runtime(&mut changed);
36072            changed.bank.header.descriptor_digest = changed.original_descriptor_digest();
36073            assert!(PublicationMaterial::decode(&changed.encode().unwrap()).is_ok());
36074            changed
36075                .ranges
36076                .iter_mut()
36077                .find(|item| item.range.role == 33)
36078                .unwrap()
36079                .bytes[word * 8] ^= 1;
36080            assert!(
36081                PublicationMaterial::decode(&changed.encode().unwrap()).is_err(),
36082                "cold decoding accepted altered normalized-out attempt word {word}"
36083            );
36084        }
36085    }
36086
36087    #[test]
36088    fn checkpoint_projection_uses_validated_original_publication() {
36089        let material = publication_material_sample();
36090        let header = material.bank.header;
36091        let projection =
36092            SemanticTransitionSession::state_material_projection(&material.encode().unwrap())
36093                .unwrap();
36094        assert_eq!(projection.publication.instance, header.instance);
36095        assert_eq!(projection.publication.word, header.publication_word);
36096        assert_eq!(projection.publication.logical_digest, header.logical_digest);
36097        assert_eq!(projection.publication.state_digest, header.state_digest);
36098        assert_eq!(projection.semantic_root, header.semantic_digest);
36099        assert_eq!(projection.model_generation, header.model_generation);
36100    }
36101
36102    // Fixed native ABI records exercise the cold evidence parser. They are not
36103    // claimed to be a device execution or historical publication authority.
36104    fn replay_material_sample() -> (PublicationMaterial, PublicationReplayEvidence) {
36105        let mut predecessor = publication_material_sample();
36106        predecessor.bank.header.instance = Identity256::from_bytes([11; 32]);
36107        predecessor.bank.header.logical_digest = Identity256::from_bytes([12; 32]);
36108        for (role, bytes) in [
36109            (
36110                30,
36111                publication_abi_bytes(&[IntentQueueHeader {
36112                    abi: 1,
36113                    ..IntentQueueHeader::default()
36114                }]),
36115            ),
36116            (33, publication_abi_bytes(&[AttemptReceipt::default()])),
36117        ] {
36118            let item = predecessor
36119                .ranges
36120                .iter_mut()
36121                .find(|item| item.range.role == role)
36122                .unwrap();
36123            item.range.length_bytes = bytes.len() as u64;
36124            item.capacity = bytes.len();
36125            item.bytes = bytes;
36126        }
36127        // The sample's final allocation capacities precede its cold contract,
36128        // exactly as in initial publication. Imported evidence is never resealed.
36129        publication_material_sample_runtime(&mut predecessor);
36130        for item in &mut predecessor.ranges {
36131            if !is_tensor_role(item.range.role) {
36132                item.range.digest = item.original_record_digest();
36133            }
36134        }
36135        predecessor.bank.header.descriptor_digest = predecessor.original_descriptor_digest();
36136        let mut evidence = PublicationReplayEvidence {
36137            successor: SemanticPublishedIdentity {
36138                instance: predecessor.bank.header.instance,
36139                word: 19,
36140                logical_digest: Identity256::from_bytes([13; 32]),
36141                state_digest: Identity256::default(),
36142            },
36143            ranges: predecessor
36144                .ranges
36145                .iter()
36146                .filter(|item| REPLAY_EVIDENCE_ROLES.contains(&item.range.role))
36147                .cloned()
36148                .collect(),
36149        };
36150        let attempt = AttemptReceipt {
36151            abi: 2,
36152            transition_kind: 2,
36153            instance: evidence.successor.instance,
36154            base_word: predecessor.bank.header.publication_word,
36155            next_word: evidence.successor.word,
36156            logical_digest: evidence.successor.logical_digest,
36157            action_receipts_digest: Identity256::from_bytes(Sha256::digest([]).into()),
36158            semantic_receipts_digest: Identity256::from_bytes([14; 32]),
36159            coverage_digest: Identity256::from_bytes([15; 32]),
36160            replay_head_digest: evidence.range(27).unwrap().logical_record_digest().unwrap(),
36161            intent_head_digest: evidence.range(30).unwrap().logical_record_digest().unwrap(),
36162            acknowledgement_head_digest: evidence
36163                .range(32)
36164                .unwrap()
36165                .logical_record_digest()
36166                .unwrap(),
36167            previous_attempt_digest: predecessor
36168                .ranges
36169                .iter()
36170                .find(|item| item.range.role == 33)
36171                .unwrap()
36172                .logical_record_digest()
36173                .unwrap(),
36174            ..AttemptReceipt::default()
36175        };
36176        evidence.ranges.last_mut().unwrap().bytes = publication_abi_bytes(&[attempt]);
36177        seal_replay_sample(&mut evidence);
36178        (predecessor, evidence)
36179    }
36180
36181    fn seal_replay_sample(evidence: &mut PublicationReplayEvidence) {
36182        let item = evidence.ranges.last_mut().unwrap();
36183        let mut attempt = item.attempt().unwrap();
36184        attempt.receipt_digest = item.logical_record_digest().unwrap();
36185        item.bytes = publication_abi_bytes(&[attempt]);
36186        for item in &mut evidence.ranges {
36187            item.range.digest = item.original_record_digest();
36188        }
36189        evidence.successor.state_digest = evidence.state_digest().unwrap();
36190    }
36191
36192    #[test]
36193    fn selected_recompute_requires_the_current_sealed_native_attempt() {
36194        let (mut selected, mut evidence) = replay_material_sample();
36195        let current_coverage = CompletionCoverage {
36196            abi: 1,
36197            model_generation: selected.bank.header.model_generation,
36198            ..CompletionCoverage::default()
36199        };
36200        let coverage_range = selected
36201            .ranges
36202            .iter_mut()
36203            .find(|item| item.range.role == 14)
36204            .unwrap();
36205        coverage_range.bytes = publication_abi_bytes(&[current_coverage]);
36206        coverage_range.capacity = coverage_range.bytes.len();
36207        coverage_range.range.length_bytes = coverage_range.bytes.len() as u64;
36208        coverage_range.range.digest = coverage_range.original_record_digest();
36209        let coverage = coverage_range.logical_record_digest().unwrap();
36210        let attempt_range = evidence.ranges.last_mut().unwrap();
36211        let mut attempt = attempt_range.attempt().unwrap();
36212        attempt.coverage_digest = coverage;
36213        attempt_range.bytes = publication_abi_bytes(&[attempt]);
36214        seal_replay_sample(&mut evidence);
36215        let previous_word = selected.bank.header.publication_word;
36216        selected.bank.header.base_word = previous_word;
36217        selected.bank.header.publication_word = evidence.successor.word;
36218        selected.bank.header.logical_digest = evidence.successor.logical_digest;
36219        selected.bank.header.state_digest = evidence.successor.state_digest;
36220        selected.bank.header.terminal = 0;
36221        for replacement in &evidence.ranges {
36222            let original = selected
36223                .ranges
36224                .iter_mut()
36225                .find(|item| {
36226                    (item.range.role, item.range.index)
36227                        == (replacement.range.role, replacement.range.index)
36228                })
36229                .unwrap();
36230            *original = replacement.clone();
36231        }
36232        assert!(selected.require_successful_recompute().is_ok());
36233        let attempt_range = selected
36234            .ranges
36235            .iter_mut()
36236            .find(|item| item.range.role == 33)
36237            .unwrap();
36238        let original_attempt = attempt_range.bytes.clone();
36239        let mut update = attempt_range.attempt().unwrap();
36240        update.transition_kind = 4;
36241        attempt_range.bytes = publication_abi_bytes(&[update]);
36242        assert!(selected.require_successful_recompute().is_err());
36243        selected
36244            .ranges
36245            .iter_mut()
36246            .find(|item| item.range.role == 33)
36247            .unwrap()
36248            .bytes = original_attempt;
36249        selected.bank.header.publication_word += 2;
36250        assert!(selected.require_successful_recompute().is_err());
36251    }
36252
36253    #[test]
36254    fn semantic_replay_material_requires_complete_linked_evidence() {
36255        let (predecessor, evidence) = replay_material_sample();
36256        let bytes = predecessor.encode().unwrap();
36257        let parse = |evidence: &[u8]| {
36258            SemanticReplayMaterial::decode(
36259                &bytes,
36260                evidence,
36261                predecessor.bank.header.logical_digest,
36262                evidence_successor_logical(),
36263            )
36264        };
36265        let decoded = parse(&evidence.encode().unwrap()).unwrap();
36266        assert_eq!(
36267            decoded.predecessor_identity().instance,
36268            predecessor.bank.header.instance
36269        );
36270        assert_eq!(decoded.successor_identity(), evidence.successor);
36271        assert_eq!(decoded.transition_kind(), SemanticTransitionKind::Recompute);
36272        assert!(parse(&bytes).is_err());
36273        assert!(parse(&[]).is_err());
36274        let mut truncated = evidence.encode().unwrap();
36275        truncated.pop();
36276        assert!(parse(&truncated).is_err());
36277        let mut trailing = evidence.encode().unwrap();
36278        trailing.push(0);
36279        assert!(parse(&trailing).is_err());
36280        for change in 0..5 {
36281            let (_, mut changed) = replay_material_sample();
36282            match change {
36283                0 => changed.successor.instance = Identity256::from_bytes([90; 32]),
36284                1 => changed.successor.word += 4,
36285                2 => changed.successor.state_digest = Identity256::default(),
36286                3 => {
36287                    changed.ranges.remove(0);
36288                }
36289                4 => {
36290                    let item = changed.ranges.last_mut().unwrap();
36291                    let mut attempt = item.attempt().unwrap();
36292                    attempt.previous_attempt_digest = Identity256::from_bytes([91; 32]);
36293                    item.bytes = publication_abi_bytes(&[attempt]);
36294                    seal_replay_sample(&mut changed);
36295                }
36296                _ => unreachable!(),
36297            }
36298            assert!(
36299                parse(&changed.encode().unwrap()).is_err(),
36300                "accepted altered native evidence {change}"
36301            );
36302        }
36303    }
36304
36305    fn evidence_successor_logical() -> Identity256 {
36306        Identity256::from_bytes([13; 32])
36307    }
36308
36309    #[test]
36310    fn semantic_replay_provenance_preserves_original_authority_and_decision() {
36311        let (predecessor, evidence) = replay_material_sample();
36312        let replay = SemanticReplayMaterial::decode(
36313            &predecessor.encode().unwrap(),
36314            &evidence.encode().unwrap(),
36315            predecessor.bank.header.logical_digest,
36316            evidence.successor.logical_digest,
36317        )
36318        .unwrap();
36319        let authority = predecessor
36320            .ranges
36321            .iter()
36322            .find(|item| item.range.role == 38)
36323            .unwrap()
36324            .clone();
36325        let mut decision = predecessor
36326            .ranges
36327            .iter()
36328            .find(|item| item.range.role == 39)
36329            .unwrap()
36330            .clone();
36331        decision.bytes[0] ^= 1;
36332        decision.range.digest = decision.original_record_digest();
36333        let mut provenance = PublicationReplayProvenance {
36334            predecessor: replay.predecessor_identity(),
36335            authority,
36336            decision,
36337        };
36338        let bytes = provenance.encode().unwrap();
36339        assert_eq!(
36340            replay.verify_provenance(&bytes).unwrap(),
36341            provenance.decision.bytes
36342        );
36343        assert!(replay.verify_provenance(&bytes[..bytes.len() - 1]).is_err());
36344        let mut trailing = bytes.clone();
36345        trailing.push(0);
36346        assert!(replay.verify_provenance(&trailing).is_err());
36347        assert!(replay
36348            .verify_provenance(&predecessor.encode().unwrap())
36349            .is_err());
36350        provenance.predecessor.word += 2;
36351        assert!(replay
36352            .verify_provenance(&provenance.encode().unwrap())
36353            .is_err());
36354        provenance.predecessor = replay.predecessor_identity();
36355        provenance.authority.bytes[0] ^= 1;
36356        provenance.authority.range.digest = provenance.authority.original_record_digest();
36357        assert!(replay
36358            .verify_provenance(&provenance.encode().unwrap())
36359            .is_err());
36360        provenance.authority = predecessor
36361            .ranges
36362            .iter()
36363            .find(|item| item.range.role == 38)
36364            .unwrap()
36365            .clone();
36366        provenance.decision.bytes[0] ^= 1;
36367        assert!(replay
36368            .verify_provenance(&provenance.encode().unwrap())
36369            .is_err());
36370    }
36371
36372    #[test]
36373    fn semantic_replay_material_normalizes_only_native_audit_words() {
36374        let (_, evidence) = replay_material_sample();
36375        let mut attempt = evidence.range(33).unwrap().clone();
36376        let original = attempt.logical_record_digest().unwrap();
36377        for word in [1, 4, 5, 6, 39, 42] {
36378            attempt.bytes[word * 8] ^= 1;
36379        }
36380        assert_eq!(attempt.logical_record_digest().unwrap(), original);
36381        assert_ne!(
36382            attempt.original_record_digest(),
36383            evidence.range(33).unwrap().original_record_digest()
36384        );
36385        attempt.bytes[7 * 8] ^= 1;
36386        assert_ne!(attempt.logical_record_digest().unwrap(), original);
36387        for role in [27, 28, 31, 32] {
36388            let mut item = evidence.range(role).unwrap().clone();
36389            let original = item.logical_record_digest().unwrap();
36390            item.bytes[0] ^= 1;
36391            assert_ne!(
36392                item.logical_record_digest().unwrap(),
36393                original,
36394                "normalized opaque role {role}"
36395            );
36396        }
36397    }
36398
36399    fn replay_codebook_sample() -> PublicationMaterialRange {
36400        let mut words: Vec<u64> = (0..28).collect();
36401        words[8] = 25 * 8;
36402        words[9] = 3 * 8;
36403        let bytes = publication_abi_bytes(&words);
36404        let mut item = PublicationMaterialRange {
36405            range: PublicationRange {
36406                role: 48,
36407                generation: 1,
36408                length_bytes: bytes.len() as u64,
36409                ..PublicationRange::default()
36410            },
36411            capacity: bytes.len(),
36412            bytes,
36413        };
36414        item.range.digest = item.original_record_digest();
36415        item
36416    }
36417
36418    #[test]
36419    fn semantic_replay_receipt_hashes_preserve_every_nonruntime_field() {
36420        let codebook = replay_codebook_sample();
36421        let receipts = [SemanticTransitionReceipt {
36422            catalogue_generation: CATALOGUE_GENERATION,
36423            admission_binding: Identity256::from_bytes([17; 32]),
36424            choice: 5,
36425            ..SemanticTransitionReceipt::default()
36426        }];
36427        let expected = publication_action_receipts_digest(&codebook, &receipts).unwrap();
36428        for word in 0..codebook.bytes.len() / 8 {
36429            if matches!(word, 8 | 9) {
36430                continue;
36431            }
36432            let mut changed = codebook.clone();
36433            changed.bytes[word * 8] ^= 1;
36434            let equal =
36435                publication_action_receipts_digest(&changed, &receipts).unwrap() == expected;
36436            assert_eq!(
36437                equal,
36438                matches!(word, 14..=16 | 21..=24),
36439                "codebook word {word}"
36440            );
36441        }
36442        let mut changed = receipts;
36443        changed[0].admission_binding = Identity256::from_bytes([18; 32]);
36444        assert_eq!(
36445            publication_action_receipts_digest(&codebook, &changed).unwrap(),
36446            expected
36447        );
36448        changed[0].choice += 1;
36449        assert_ne!(
36450            publication_action_receipts_digest(&codebook, &changed).unwrap(),
36451            expected
36452        );
36453        let mut legacy = receipts;
36454        legacy[0].catalogue_generation = 0;
36455        let legacy_digest = publication_action_receipts_digest(&codebook, &legacy).unwrap();
36456        legacy[0].admission_binding = Identity256::from_bytes([18; 32]);
36457        assert_ne!(
36458            publication_action_receipts_digest(&codebook, &legacy).unwrap(),
36459            legacy_digest
36460        );
36461        assert_eq!(
36462            publication_action_receipts_digest(&codebook, &[]).unwrap(),
36463            Identity256::from_bytes(Sha256::digest([]).into())
36464        );
36465        let semantic = [[0u64; 42]; 7];
36466        let expected = publication_semantic_receipts_digest(&semantic);
36467        for ordinal in 0..semantic.len() {
36468            for word in 0..42 {
36469                let mut changed = semantic;
36470                changed[ordinal][word] = 1;
36471                assert_eq!(
36472                    publication_semantic_receipts_digest(&changed) == expected,
36473                    matches!(word, 3..=12 | 34..=41),
36474                    "semantic receipt {ordinal} word {word}"
36475                );
36476            }
36477        }
36478        let header = IntentQueueHeader {
36479            abi: 1,
36480            count: 2,
36481            capacity: 2,
36482            ..IntentQueueHeader::default()
36483        };
36484        let mut bytes = publication_abi_bytes(&[header]);
36485        bytes.extend(publication_abi_bytes(&[IntentEntry::default(); 2]));
36486        let intent = PublicationMaterialRange {
36487            range: PublicationRange {
36488                role: 30,
36489                logical_end: 2,
36490                length_bytes: bytes.len() as u64,
36491                ..PublicationRange::default()
36492            },
36493            capacity: bytes.len(),
36494            bytes,
36495        };
36496        let expected = intent.logical_record_digest().unwrap();
36497        for ordinal in 0..2 {
36498            for word in 0..43 {
36499                let mut changed = intent.clone();
36500                changed.bytes[size_of::<IntentQueueHeader>()
36501                    + ordinal * size_of::<IntentEntry>()
36502                    + word * 8] ^= 1;
36503                assert_eq!(
36504                    changed.logical_record_digest().unwrap() == expected,
36505                    matches!(word, 30..=34),
36506                    "intent entry {ordinal} word {word}"
36507                );
36508            }
36509        }
36510    }
36511
36512    #[test]
36513    fn semantic_replay_observed_attempt_checks_actual_receipts_and_coverage() {
36514        let (predecessor, mut evidence) = replay_material_sample();
36515        let mut bank = predecessor.bank;
36516        bank.header.instance = evidence.successor.instance;
36517        bank.header.base_word = predecessor.bank.header.publication_word;
36518        bank.header.publication_word = evidence.successor.word;
36519        bank.header.sealed_epoch = evidence.successor.word >> 1;
36520        bank.header.logical_digest = evidence.successor.logical_digest;
36521        bank.header.proposal = predecessor.bank.header.proposal + 1;
36522        bank.state.proposal = predecessor.bank.header.proposal;
36523        bank.state.next_proposal = bank.header.proposal;
36524        bank.state.blocks = COMPONENT_COUNT as u64;
36525        bank.receipts[0].catalogue_generation = CATALOGUE_GENERATION;
36526        let codebook = replay_codebook_sample();
36527        let component_receipts_digest =
36528            publication_action_receipts_digest(&codebook, &bank.receipts).unwrap();
36529        let semantic_receipts_digest =
36530            publication_semantic_receipts_digest(&bank.state.semantic_receipts);
36531        bank.state.action_batch = SemanticActionBatchReceipt {
36532            abi: 1,
36533            proposal: bank.state.proposal,
36534            stream_serial: bank.state.stream_serial,
36535            family_id: u64::from(bank.state.family_id),
36536            action_law_generation: bank.state.catalogue_generation,
36537            model_generation: u64::from(bank.state.model_generation),
36538            actor_eligible: bank.state.actor_eligible,
36539            component_count: COMPONENT_COUNT as u64,
36540            candidate_count: 3,
36541            winner: bank.state.task_evaluation.winner,
36542            total_return_bits: bank.state.task_evaluation.return_value as u64,
36543            base_word: bank.header.base_word,
36544            next_word: bank.header.publication_word,
36545            rng_base: bank.state.proposal * COMPONENT_COUNT as u64,
36546            rng_span: COMPONENT_COUNT as u64,
36547            rng_successor: bank.state.next_proposal * COMPONENT_COUNT as u64,
36548            catalogue_digest: bank.state.catalogue_digest,
36549            component_receipts_digest,
36550            semantic_receipts_digest,
36551            candidate_roots: [Identity256::default(); 3],
36552            base_logical_digest: predecessor.bank.header.logical_digest,
36553            execution_work: bank.state.execution_work,
36554        };
36555        bank.state.action_batch_root = publication_action_batch_root(&bank.state.action_batch);
36556        let mut completion = CompletionCoverage {
36557            abi: 1,
36558            instance: bank.header.instance,
36559            base_word: bank.header.base_word,
36560            ..CompletionCoverage::default()
36561        };
36562        let bytes = publication_abi_bytes(&[completion]);
36563        let mut coverage = PublicationMaterialRange {
36564            range: PublicationRange {
36565                role: 14,
36566                generation: 1,
36567                length_bytes: bytes.len() as u64,
36568                ..PublicationRange::default()
36569            },
36570            capacity: bytes.len(),
36571            bytes,
36572        };
36573        completion.receipt_digest = coverage.logical_record_digest().unwrap();
36574        coverage.bytes = publication_abi_bytes(&[completion]);
36575        coverage.range.digest = coverage.original_record_digest();
36576        let item = evidence.ranges.last_mut().unwrap();
36577        let mut attempt = item.attempt().unwrap();
36578        attempt.transition_kind = 1;
36579        attempt.action_receipts_digest = bank.state.action_batch_root;
36580        attempt.semantic_receipts_digest = semantic_receipts_digest;
36581        attempt.coverage_digest = coverage.logical_record_digest().unwrap();
36582        item.bytes = publication_abi_bytes(&[attempt]);
36583        seal_replay_sample(&mut evidence);
36584        bank.header.state_digest = evidence.successor.state_digest;
36585        assert_eq!(
36586            evidence.validate(&predecessor).unwrap(),
36587            SemanticTransitionKind::Proposal
36588        );
36589        evidence
36590            .validate_observed(&predecessor, &bank, &coverage, &codebook)
36591            .unwrap();
36592
36593        let mut changed = bank;
36594        changed.receipts[0].choice += 1;
36595        assert!(evidence
36596            .validate_observed(&predecessor, &changed, &coverage, &codebook)
36597            .is_err());
36598        changed = bank;
36599        changed.state.semantic_receipts[0][13] += 1;
36600        assert!(evidence
36601            .validate_observed(&predecessor, &changed, &coverage, &codebook)
36602            .is_err());
36603        changed = bank;
36604        changed.state.semantic_receipts[0][3] += 1;
36605        evidence
36606            .validate_observed(&predecessor, &changed, &coverage, &codebook)
36607            .unwrap();
36608        changed = bank;
36609        changed.state.blocks = 0;
36610        assert!(evidence
36611            .validate_observed(&predecessor, &changed, &coverage, &codebook)
36612            .is_err());
36613        changed = bank;
36614        changed.header.base_word += 2;
36615        assert!(evidence
36616            .validate_observed(&predecessor, &changed, &coverage, &codebook)
36617            .is_err());
36618        let mut changed_coverage = coverage.clone();
36619        changed_coverage.bytes[6 * 8] ^= 1;
36620        changed_coverage.range.digest = changed_coverage.original_record_digest();
36621        assert!(evidence
36622            .validate_observed(&predecessor, &bank, &changed_coverage, &codebook)
36623            .is_err());
36624        let mut changed_codebook = codebook.clone();
36625        changed_codebook.bytes[25 * 8] ^= 1;
36626        changed_codebook.range.digest = changed_codebook.original_record_digest();
36627        assert!(evidence
36628            .validate_observed(&predecessor, &bank, &coverage, &changed_codebook)
36629            .is_err());
36630        let item = evidence.ranges.last_mut().unwrap();
36631        let mut attempt = item.attempt().unwrap();
36632        attempt.semantic_receipts_digest = Identity256::from_bytes([92; 32]);
36633        item.bytes = publication_abi_bytes(&[attempt]);
36634        seal_replay_sample(&mut evidence);
36635        bank.header.state_digest = evidence.successor.state_digest;
36636        evidence.validate(&predecessor).unwrap();
36637        assert!(evidence
36638            .validate_observed(&predecessor, &bank, &coverage, &codebook)
36639            .is_err());
36640    }
36641
36642    #[test]
36643    fn publication_material_codebooks_relocate_only_runtime_coordinates() {
36644        let original: Vec<u64> = (0..48).collect();
36645        let mut actual = original.clone();
36646        for word in (14..=16).chain(21..=24) {
36647            actual[word] += 500;
36648        }
36649        let saved = publication_abi_bytes(&original);
36650        assert_eq!(
36651            relocate_publication_codebooks(&saved, &actual).unwrap(),
36652            publication_abi_bytes(&actual)
36653        );
36654        for word in (0..14).chain(17..=20).chain(25..48) {
36655            let mut corrupt = actual.clone();
36656            corrupt[word] += 1;
36657            assert!(
36658                relocate_publication_codebooks(&saved, &corrupt).is_err(),
36659                "logical word {word}"
36660            );
36661        }
36662        assert!(relocate_publication_codebooks(&saved[..saved.len() - 1], &actual).is_err());
36663        assert!(relocate_publication_codebooks(&saved, &actual[..47]).is_err());
36664        assert!(relocate_publication_codebooks(&[], &[]).is_err());
36665    }
36666
36667    type StepInputGeometryFixture = (
36668        [Vec<PublicationRange>; 2],
36669        BTreeMap<(u64, u64), SemanticTensorLayout>,
36670        Vec<usize>,
36671    );
36672
36673    fn step_input_geometry_fixture() -> StepInputGeometryFixture {
36674        let mut layouts = BTreeMap::new();
36675        let mut banks = [Vec::new(), Vec::new()];
36676        let mut sizes = Vec::new();
36677        for (role, index) in std::iter::once(1)
36678            .chain(3..=13)
36679            .chain(15..=17)
36680            .chain(std::iter::once(44))
36681            .flat_map(|role| (0..if role == 16 { 3 } else { 1 }).map(move |index| (role, index)))
36682        {
36683            let layout = if role == 1 {
36684                SemanticTensorLayout {
36685                    role,
36686                    index: 0,
36687                    scalar_type: 3,
36688                    element_bytes: 8,
36689                    rank: 2,
36690                    logical_axis: 0,
36691                    dimensions: [64, 8, 0, 0],
36692                    strides_bytes: [64, 8, 0, 0],
36693                }
36694            } else {
36695                canonical_tensor_layout(SemanticTensorLayout {
36696                    role,
36697                    index: 0,
36698                    scalar_type: if role == 7 { 5 } else { 6 },
36699                    element_bytes: if role == 7 { 2 } else { 4 },
36700                    rank: 4,
36701                    logical_axis: if role <= 5 { 2 } else { u64::MAX },
36702                    dimensions: [1, 2, 64, 3],
36703                    strides_bytes: [0; 4],
36704                })
36705                .unwrap()
36706            };
36707            if (4..=13).contains(&role) {
36708                layouts.insert((role, 0), layout);
36709            }
36710            let capacity = if role == 3 {
36711                32
36712            } else if role == 44 {
36713                108
36714            } else if role == 15 {
36715                2 * size_of::<RawFeedbackRecord>()
36716            } else if matches!(role, 16 | 17) {
36717                40 + index as usize * 8
36718            } else {
36719                tensor_layout_bytes(&layout).unwrap()
36720            };
36721            let shared = matches!(role, 1 | 16 | 17);
36722            let first_slot = sizes.len();
36723            sizes.push(capacity);
36724            if !shared {
36725                sizes.push(capacity);
36726            }
36727            for (bank, directory) in banks.iter_mut().enumerate() {
36728                directory.push(PublicationRange {
36729                    role,
36730                    index,
36731                    storage_slot: (first_slot + usize::from(!shared) * bank) as u64,
36732                    generation: 1,
36733                    length_bytes: if role == 1 {
36734                        64
36735                    } else if role == 4 || role == 5 {
36736                        24
36737                    } else {
36738                        capacity as u64
36739                    },
36740                    logical_end: u64::from(matches!(role, 1 | 4 | 5 | 15)),
36741                    ..PublicationRange::default()
36742                });
36743            }
36744        }
36745        (banks, layouts, sizes)
36746    }
36747
36748    #[test]
36749    fn step_input_geometry_preserves_exact_roster_and_full_shared_capacity() {
36750        let (banks, layouts, sizes) = step_input_geometry_fixture();
36751        let plan = plan_step_inputs(&banks, &layouts, 64, &sizes).unwrap();
36752        assert_eq!(
36753            plan.iter()
36754                .map(|input| (input.role, input.index))
36755                .collect::<Vec<_>>(),
36756            std::iter::once((1, 0))
36757                .chain((3..=13).map(|role| (role, 0)))
36758                .chain([(15, 0), (16, 0), (16, 1), (16, 2), (17, 0), (44, 0),])
36759                .collect::<Vec<_>>()
36760        );
36761        assert_eq!(plan[0].banks[0].span.len(), 64 * size_of::<SourceSlot>());
36762        assert_eq!(plan[1].banks[0].span.len(), 32);
36763        for input in plan.iter().filter(|input| matches!(input.role, 4 | 5)) {
36764            assert_eq!(input.banks[0].span.len(), 2 * 64 * 3 * 4);
36765        }
36766        assert_eq!(size_of::<PublicationStepInput>(), 160);
36767    }
36768
36769    #[test]
36770    fn step_input_geometry_retains_raw_feedback_and_every_statement_record() {
36771        let (banks, layouts, sizes) = step_input_geometry_fixture();
36772        let plan = plan_step_inputs(&banks, &layouts, 64, &sizes).unwrap();
36773        let records = plan
36774            .iter()
36775            .filter(|input| matches!(input.role, 15..=17))
36776            .collect::<Vec<_>>();
36777        assert_eq!(
36778            records
36779                .iter()
36780                .map(|input| (input.role, input.index, input.banks[0].span.len()))
36781                .collect::<Vec<_>>(),
36782            vec![
36783                (15, 0, 768),
36784                (16, 0, 40),
36785                (16, 1, 48),
36786                (16, 2, 56),
36787                (17, 0, 40),
36788            ]
36789        );
36790        assert!(records
36791            .iter()
36792            .all(|input| input.layout.scalar_type == 1 && input.layout.element_bytes == 1));
36793        let mut missing = banks.clone();
36794        missing[1].retain(|range| (range.role, range.index) != (16, 2));
36795        assert!(plan_step_inputs(&missing, &layouts, 64, &sizes).is_err());
36796        let mut gapped = banks.clone();
36797        for bank in &mut gapped {
36798            bank.iter_mut()
36799                .find(|range| (range.role, range.index) == (16, 1))
36800                .unwrap()
36801                .index = 3;
36802        }
36803        assert!(plan_step_inputs(&gapped, &layouts, 64, &sizes).is_err());
36804        let mut shared_raw = banks;
36805        let slot = shared_raw[0]
36806            .iter()
36807            .find(|range| range.role == 15)
36808            .unwrap()
36809            .storage_slot;
36810        shared_raw[1]
36811            .iter_mut()
36812            .find(|range| range.role == 15)
36813            .unwrap()
36814            .storage_slot = slot;
36815        assert!(plan_step_inputs(&shared_raw, &layouts, 64, &sizes).is_err());
36816    }
36817
36818    #[test]
36819    fn feedback_record_material_preserves_original_seal_and_rejects_changed_content() {
36820        let mut original = PublicationMaterialRange {
36821            range: PublicationRange {
36822                role: 15,
36823                generation: 1,
36824                length_bytes: 768,
36825                logical_end: 1,
36826                ..PublicationRange::default()
36827            },
36828            capacity: 768,
36829            bytes: vec![0; 768],
36830        };
36831        original.range.digest = original.original_record_digest();
36832        let material = original.clone().into_feedback_record().unwrap();
36833        assert_eq!(material.identity, original.range.digest);
36834        assert_eq!(
36835            (
36836                material.logical_begin,
36837                material.logical_end,
36838                material.capacity_bytes
36839            ),
36840            (0, 1, 768)
36841        );
36842        assert_eq!(material.bytes, original.bytes);
36843        let mut changed = original.clone();
36844        changed.bytes[0] ^= 1;
36845        assert!(changed.into_feedback_record().is_err());
36846        let mut changed = original.clone();
36847        changed.range.logical_end = 2;
36848        assert!(changed.into_feedback_record().is_err());
36849        let mut changed = original;
36850        changed.range.role = 18;
36851        assert!(changed.into_feedback_record().is_err());
36852    }
36853
36854    #[test]
36855    fn step_input_geometry_rejects_missing_duplicate_and_noncanonical_coordinates() {
36856        let (banks, layouts, sizes) = step_input_geometry_fixture();
36857        let mut missing = banks.clone();
36858        missing[1].remove(4);
36859        assert!(plan_step_inputs(&missing, &layouts, 64, &sizes).is_err());
36860        let mut duplicate = banks.clone();
36861        let repeated = duplicate[0][4];
36862        duplicate[0].push(repeated);
36863        assert!(plan_step_inputs(&duplicate, &layouts, 64, &sizes).is_err());
36864        let mut wrong_index = banks;
36865        wrong_index[0][4].index = 1;
36866        assert!(plan_step_inputs(&wrong_index, &layouts, 64, &sizes).is_err());
36867    }
36868
36869    #[test]
36870    fn step_input_geometry_requires_shared_prefix_and_isolated_key_value_caches() {
36871        let (banks, layouts, sizes) = step_input_geometry_fixture();
36872        {
36873            let role = 1;
36874            let mut changed = banks.clone();
36875            changed[1]
36876                .iter_mut()
36877                .find(|range| range.role == role)
36878                .unwrap()
36879                .storage_slot += 1;
36880            assert!(plan_step_inputs(&changed, &layouts, 64, &sizes).is_err());
36881        }
36882        for role in [4, 5].into_iter().chain(std::iter::once(3)).chain(6..=13) {
36883            let mut changed = banks.clone();
36884            let slot = changed[0]
36885                .iter()
36886                .find(|range| range.role == role)
36887                .unwrap()
36888                .storage_slot;
36889            changed[1]
36890                .iter_mut()
36891                .find(|range| range.role == role)
36892                .unwrap()
36893                .storage_slot = slot;
36894            assert!(plan_step_inputs(&changed, &layouts, 64, &sizes).is_err());
36895        }
36896    }
36897
36898    #[test]
36899    fn step_input_geometry_checks_canonical_dtype_spans_and_allocation_bounds() {
36900        let (banks, layouts, sizes) = step_input_geometry_fixture();
36901        let plan = plan_step_inputs(&banks, &layouts, 64, &sizes).unwrap();
36902        let bf16 = plan.iter().find(|input| input.role == 7).unwrap();
36903        assert_eq!(
36904            (
36905                bf16.layout.scalar_type,
36906                bf16.layout.element_bytes,
36907                bf16.banks[0].span.len()
36908            ),
36909            (5, 2, 768)
36910        );
36911        let mut wrong = layouts.clone();
36912        wrong.get_mut(&(7, 0)).unwrap().strides_bytes[2] += 2;
36913        assert!(plan_step_inputs(&banks, &wrong, 64, &sizes).is_err());
36914        let mut short = sizes;
36915        short[banks[1]
36916            .iter()
36917            .find(|range| range.role == 7)
36918            .unwrap()
36919            .storage_slot as usize] -= 1;
36920        assert!(plan_step_inputs(&banks, &layouts, 64, &short).is_err());
36921        assert!(
36922            step_input_overlap(104, 0, 100, 8).unwrap(),
36923            "empty native aliases must still preserve their origin"
36924        );
36925        assert!(!step_input_overlap(108, 0, 100, 8).unwrap());
36926        assert!(step_input_overlap(96, 8, 100, 8).unwrap());
36927        assert!(step_input_overlap(u64::MAX, 2, 100, 8).is_err());
36928    }
36929
36930    #[test]
36931    #[ignore = "requires an explicitly authorized remote CUDA run"]
36932    fn step_inputs_keep_private_values_after_reader_retirement_and_current_bank_reuse() {
36933        let (provider, domain) = publication_test_provider();
36934        let mut session = publication_test_session(Arc::clone(&provider), &domain);
36935        session
36936            .bind_parent(publication_test_parent(&provider))
36937            .unwrap();
36938        let mut lease = session.acquire().unwrap();
36939        let context = session.published_model_context(&lease, 1).unwrap();
36940        let cache = session
36941            .published_tensor(&lease, SemanticStateRole::from_code(8).unwrap(), 0, 1)
36942            .unwrap();
36943        let inputs = Arc::clone(session.steps[&lease.token].inputs.as_ref().unwrap());
36944        let mut feedback_before = Vec::new();
36945        for (&(role, index), view) in inputs
36946            .views
36947            .first()
36948            .expect("two publication input banks")
36949            .iter()
36950            .filter(|(key, _)| matches!(key.0, 15..=17))
36951        {
36952            feedback_before.push((
36953                (role, index),
36954                session.publication_read(view.clone()).unwrap(),
36955            ));
36956        }
36957        assert_eq!(feedback_before.len(), 4);
36958        drop(inputs);
36959        let source_pointer = context.source.as_ptr();
36960        let cache_pointer = cache.as_ptr();
36961        let source_address = unsafe { (*source_pointer).dl_tensor.data as u64 };
36962        let cache_address = unsafe { (*cache_pointer).dl_tensor.data as u64 };
36963        let storage = Arc::clone(session.publication.as_ref().unwrap());
36964        assert!(!storage
36965            .banks
36966            .iter()
36967            .any(|bank| source_address >= bank.device_ptr_value()
36968                && source_address < bank.device_ptr_value() + size_of::<PublicationBank>() as u64));
36969        assert!(!storage
36970            .allocations
36971            .iter()
36972            .any(|allocation| cache_address >= allocation.device_ptr_value()
36973                && cache_address < allocation.device_ptr_value() + allocation.len() as u64));
36974        let again = session.published_source(&lease, 1).unwrap();
36975        assert_eq!(
36976            unsafe { (*again.as_ptr()).dl_tensor.data as u64 },
36977            source_address
36978        );
36979        let source_layout = SemanticTensorLayout {
36980            role: 0,
36981            index: 0,
36982            scalar_type: 3,
36983            element_bytes: 8,
36984            rank: 2,
36985            logical_axis: u64::MAX,
36986            dimensions: [32, 8, 0, 0],
36987            strides_bytes: [64, 8, 0, 0],
36988        };
36989        let source_input = |tensor| SemanticTensorInput {
36990            layout: source_layout,
36991            logical_begin: 0,
36992            logical_end: 0,
36993            tensor,
36994            native_allocation: None,
36995        };
36996        let original_source = source_input(session.published_source(&lease, 1).unwrap());
36997        let original_cache = publication_test_alias(
36998            &mut session,
36999            &lease,
37000            SemanticStateRole::from_code(8).unwrap(),
37001            1,
37002        );
37003        let later_source = source_input(session.published_source(&lease, 1).unwrap());
37004        let later_cache = publication_test_alias(
37005            &mut session,
37006            &lease,
37007            SemanticStateRole::from_code(8).unwrap(),
37008            1,
37009        );
37010        let witness = session
37011            .capture_tensor_content(&lease, vec![original_source, original_cache], 1)
37012            .unwrap();
37013        let TensorContentSeals::Captured(origins) =
37014            &session.steps[&lease.token].content[witness.index].seals
37015        else {
37016            panic!("native input origins");
37017        };
37018        assert!(
37019            origins
37020                .iter()
37021                .all(|origin| matches!(origin, CapturedTensorDigest::Publication(_))),
37022            "capture must retain the original native input seals"
37023        );
37024        session
37025            .guard_published_content(&lease, &[(SemanticStateRole::from_code(8).unwrap(), 0)], 1)
37026            .unwrap();
37027        publication_test_recompute(&mut session, &lease, &provider);
37028        session.release_published_reader(&mut lease, &[1]).unwrap();
37029        for _ in 0..2 {
37030            let mut current = session.acquire().unwrap();
37031            let current_context = session.published_model_context(&current, 1).unwrap();
37032            let inputs = Arc::clone(session.steps[&current.token].inputs.as_ref().unwrap());
37033            let copied_header = session.publication_read(inputs.header.view()).unwrap()[0];
37034            assert_eq!(copied_header.publication_word, current.identity.word);
37035            assert_ne!(
37036                unsafe { (*current_context.source.as_ptr()).dl_tensor.data as u64 },
37037                source_address
37038            );
37039            drop(current_context);
37040            publication_test_recompute(&mut session, &current, &provider);
37041            session.release(&mut current, &[1]).unwrap();
37042        }
37043        let inputs = Arc::clone(session.steps[&lease.token].inputs.as_ref().unwrap());
37044        assert_eq!(
37045            session.publication_read(inputs.header.view()).unwrap()[0].publication_word,
37046            lease.identity.word
37047        );
37048        for (key, bytes) in feedback_before {
37049            assert_eq!(session.publication_read(inputs.views[0][&key].clone()).unwrap(), bytes,
37050                "raw feedback and its original statements/provenance must survive physical bank reuse");
37051        }
37052        let before = session.host_io_stats();
37053        session
37054            .verify_tensor_content(&lease, &witness, vec![later_source, later_cache], 1)
37055            .unwrap();
37056        assert_eq!(session.host_io_stats(), before);
37057        drop(witness);
37058        assert!(session.release(&mut lease, &[1]).is_err());
37059        drop(context);
37060        drop(cache);
37061        drop(again);
37062        drop(storage);
37063        drop(inputs);
37064        session.release(&mut lease, &[1]).unwrap();
37065        drop(session);
37066        provider.memory().reap_pending_deallocations().unwrap();
37067        assert_eq!(provider.memory().allocated_bytes(), 0);
37068    }
37069
37070    #[test]
37071    fn model_context_joins_exact_acquired_header_prefix_and_ring() {
37072        let identity = |byte| Identity256::from_bytes([byte; 32]);
37073        let mut lease = SemanticPublishedLease {
37074            issuer: Arc::new(()),
37075            token: 7,
37076            active: true,
37077            identity: SemanticPublishedIdentity {
37078                instance: identity(1),
37079                word: 12,
37080                logical_digest: identity(2),
37081                state_digest: identity(3),
37082            },
37083            header: PublicationHeader {
37084                abi: 1,
37085                instance: identity(1),
37086                publication_word: 12,
37087                sealed_epoch: 6,
37088                logical_digest: identity(2),
37089                state_digest: identity(3),
37090                descriptor_digest: identity(4),
37091                semantic_owner: 5,
37092                semantic_slot: 6,
37093                semantic_generation: 7,
37094                semantic_digest: identity(8),
37095                semantic_extents: [9, 10, 11],
37096                prefix_extent: 2,
37097                ring_head: 17,
37098                model_generation: 12,
37099                neural_bank: 1,
37100                neural_generation: 13,
37101                cache_generation: 14,
37102                authority_generation: 15,
37103                ..PublicationHeader::default()
37104            },
37105            source: source_rows(),
37106            directory: Vec::new(),
37107        };
37108        let context = lease.model_context_header().unwrap();
37109        assert_eq!(context.descriptor_digest, identity(4));
37110        assert_eq!(
37111            (
37112                context.semantic_owner,
37113                context.semantic_slot,
37114                context.semantic_generation,
37115                context.semantic_digest,
37116                context.semantic_extents
37117            ),
37118            (5, 6, 7, identity(8), [9, 10, 11])
37119        );
37120        assert_eq!(context.ring_head, 17);
37121        assert_eq!(context.prefix_extent, 2);
37122        assert_eq!(
37123            (
37124                context.model_generation,
37125                context.neural_bank,
37126                context.neural_generation,
37127                context.cache_generation,
37128                context.authority_generation
37129            ),
37130            (12, 1, 13, 14, 15)
37131        );
37132        lease.header.state_digest = identity(19);
37133        assert!(lease.model_context_header().is_err());
37134    }
37135
37136    #[test]
37137    fn publication_bank_views_use_original_fields_and_slot_order() {
37138        let header = PublicationHeader {
37139            prefix_extent: 23,
37140            ring_head: 17,
37141            ..PublicationHeader::default()
37142        };
37143        let source = source_rows();
37144        let mut bytes = publication_abi_bytes(&[header]);
37145        bytes.extend(publication_abi_bytes(&source));
37146        let (range, shape, strides) = PublicationBankField::Source.layout();
37147        assert_eq!(range.start, std::mem::offset_of!(PublicationBank, source));
37148        assert_eq!(range.len(), size_of::<[SourceSlot; 32]>());
37149        assert_eq!((shape, strides), (vec![32, 8], vec![8, 1]));
37150        assert_eq!(&bytes[range], publication_abi_bytes(&source));
37151        for (field, value) in [
37152            (PublicationBankField::PrefixExtent, 23u64),
37153            (PublicationBankField::RingHead, 17u64),
37154        ] {
37155            let (range, shape, strides) = field.layout();
37156            assert_eq!(range.start % size_of::<u64>(), 0);
37157            assert_eq!(range.len(), size_of::<u64>());
37158            assert_eq!((shape, strides), (vec![1], vec![1]));
37159            assert_eq!(&bytes[range], value.to_ne_bytes());
37160        }
37161    }
37162
37163    #[test]
37164    fn active_row_table_requires_independent_publication_banks() {
37165        assert!(publication_mutable_role(
37166            SemanticStateRole::TensorLayout as u64
37167        ));
37168    }
37169
37170    #[test]
37171    fn active_text_rows_include_the_reserved_window_before_feedback_positions() {
37172        for position in [63, 64, 95, 96] {
37173            let mut source = [SourceSlot::default(); 32];
37174            source[7] = SourceSlot {
37175                token: MASK_TOKEN as u64,
37176                logical_position: position,
37177                kind: 2,
37178                valid: 1,
37179                ..SourceSlot::default()
37180            };
37181            let admitted = validate_text_parent(&source, 0, 64, 2, 262144, 0, 0);
37182            assert_eq!(admitted.is_ok(), position < 96);
37183        }
37184    }
37185
37186    #[test]
37187    fn active_table_keeps_computed_empty_distinct_from_uncomputed() {
37188        let layouts = [SemanticTensorLayout {
37189            role: 51,
37190            rank: 4,
37191            logical_axis: 2,
37192            element_bytes: 2,
37193            scalar_type: 4,
37194            dimensions: [1, 2, 35, 4],
37195            strides_bytes: [560, 280, 8, 2],
37196            ..SemanticTensorLayout::default()
37197        }];
37198        let cold = tensor_table_bytes(&layouts, false, &[]).unwrap();
37199        let empty = tensor_table_bytes(&layouts, true, &[]).unwrap();
37200        assert_ne!(cold, empty);
37201        assert_eq!(
37202            decode_tensor_table(&cold).unwrap().2,
37203            SemanticActiveRows {
37204                computed: false,
37205                rows: vec![]
37206            }
37207        );
37208        assert_eq!(
37209            decode_tensor_table(&empty).unwrap().2,
37210            SemanticActiveRows {
37211                computed: true,
37212                rows: vec![]
37213            }
37214        );
37215        assert_eq!(decode_tensor_table(&empty).unwrap().1, layouts);
37216        assert!(decode_tensor_table(&publication_abi_bytes(&layouts)).is_err());
37217        let mut invalid = empty.clone();
37218        invalid[16..24].copy_from_slice(&2u64.to_ne_bytes());
37219        assert!(decode_tensor_table(&invalid).is_err());
37220        invalid = empty.clone();
37221        invalid[24..32].copy_from_slice(&1u64.to_ne_bytes());
37222        assert!(decode_tensor_table(&invalid).is_err());
37223        assert!(decode_tensor_table(&empty[..empty.len() - 1]).is_err());
37224        let row = SemanticActiveRow {
37225            physical_row: 0,
37226            source_slot: 0,
37227            logical_position: 0,
37228            kind: 2,
37229        };
37230        assert!(tensor_table_bytes(&layouts, false, &[row]).is_err());
37231        assert!(tensor_table_capacity(usize::MAX, 35).is_err());
37232    }
37233
37234    #[test]
37235    fn active_tensor_geometry_preserves_full_physical_capacity() {
37236        let producer = SemanticTensorLayout {
37237            role: 51,
37238            rank: 4,
37239            logical_axis: 2,
37240            element_bytes: 2,
37241            scalar_type: 4,
37242            dimensions: [1, 2, 35, 4],
37243            strides_bytes: [560, 2, 16, 4],
37244            ..SemanticTensorLayout::default()
37245        };
37246        let cold = canonical_tensor_layout(producer).unwrap();
37247        assert!(validate_active_capacity(&cold, 35).is_ok());
37248        assert!(validate_active_capacity(&cold, 34).is_err());
37249        let pending = continuation_tensor_layout(&producer, 0, 35, &cold).unwrap();
37250        assert_eq!(pending.dimensions, producer.dimensions);
37251        assert_eq!(pending.strides_bytes, [560, 280, 8, 2]);
37252        assert!(tensor_copy_plan(&producer, &pending).is_ok());
37253        assert!(continuation_tensor_layout(&producer, 8, 9, &cold).is_err());
37254        assert!(continuation_tensor_layout(&producer, 0, 3, &cold).is_err());
37255        let linear = SemanticTensorLayout {
37256            role: 53,
37257            rank: 3,
37258            logical_axis: 0,
37259            element_bytes: 4,
37260            scalar_type: 6,
37261            dimensions: [35, 4, 2, 0],
37262            strides_bytes: [32, 8, 4, 0],
37263            ..SemanticTensorLayout::default()
37264        };
37265        assert!(validate_active_capacity(&linear, 35).is_ok());
37266        assert!(validate_active_capacity(
37267            &SemanticTensorLayout {
37268                logical_axis: u64::MAX,
37269                ..linear
37270            },
37271            35
37272        )
37273        .is_err());
37274    }
37275
37276    #[test]
37277    fn publication_rng_binding_uses_only_the_actual_header_coordinates() {
37278        let header = PublicationHeader {
37279            model_generation: 17,
37280            family_id: 29,
37281            stream_serial: (1u64 << 56) - 1,
37282            proposal: u64::from(u32::MAX),
37283            ..PublicationHeader::default()
37284        };
37285        assert_eq!(
37286            header.rng_binding().unwrap(),
37287            SemanticRngBinding {
37288                model_generation: 17,
37289                family_id: 29,
37290                stream_serial: (1u64 << 56) - 1,
37291                proposal: u32::MAX,
37292            }
37293        );
37294        for invalid in [
37295            PublicationHeader {
37296                model_generation: 1u64 << 32,
37297                ..header
37298            },
37299            PublicationHeader {
37300                family_id: 256,
37301                ..header
37302            },
37303            PublicationHeader {
37304                stream_serial: 1u64 << 56,
37305                ..header
37306            },
37307            PublicationHeader {
37308                proposal: 1u64 << 32,
37309                ..header
37310            },
37311        ] {
37312            assert!(invalid.rng_binding().is_err());
37313        }
37314    }
37315
37316    #[test]
37317    fn cold_continuation_layouts_match_original_fixed_output_snapshots() {
37318        let prefix = canonical_tensor_layout(SemanticTensorLayout {
37319            role: 4,
37320            rank: 4,
37321            logical_axis: 2,
37322            element_bytes: 2,
37323            scalar_type: 4,
37324            dimensions: [1, 2, 128, 4],
37325            ..SemanticTensorLayout::default()
37326        })
37327        .unwrap();
37328        let active = canonical_tensor_layout(SemanticTensorLayout {
37329            role: 51,
37330            rank: 4,
37331            logical_axis: 2,
37332            element_bytes: 2,
37333            scalar_type: 4,
37334            dimensions: [1, 2, 35, 4],
37335            ..SemanticTensorLayout::default()
37336        })
37337        .unwrap();
37338        let state = canonical_tensor_layout(SemanticTensorLayout {
37339            role: 6,
37340            rank: 2,
37341            logical_axis: u64::MAX,
37342            element_bytes: 4,
37343            scalar_type: 6,
37344            dimensions: [4, 128, 0, 0],
37345            ..SemanticTensorLayout::default()
37346        })
37347        .unwrap();
37348        let mut layouts = Vec::new();
37349        for (model, extent) in [(prefix, 32), (active, 35), (state, 0)] {
37350            let cold = continuation_capacity_layout(model).unwrap();
37351            let mut producer = cold;
37352            if model.role != 6 {
37353                // The original can be transposed; only the owned destination
37354                // has the immutable canonical transport strides.
37355                producer.strides_bytes = [extent * 16, 2, 16, 4];
37356            }
37357            assert_eq!(
37358                continuation_tensor_layout(&producer, 0, extent, &model).unwrap(),
37359                cold
37360            );
37361            assert!(tensor_copy_plan(&producer, &cold).is_ok());
37362            layouts.push(cold);
37363        }
37364        assert_eq!(layouts[0].dimensions, [1, 2, 32, 4]);
37365        assert_eq!(layouts[1], active);
37366        assert_eq!(layouts[2], state);
37367        let table = tensor_table_bytes(&layouts, true, &[]).unwrap();
37368        let (_, decoded, rows) = decode_tensor_table(&table).unwrap();
37369        assert_eq!(decoded, layouts);
37370        assert_eq!(
37371            rows,
37372            SemanticActiveRows {
37373                computed: true,
37374                rows: vec![]
37375            }
37376        );
37377        assert!(continuation_capacity_layout(SemanticTensorLayout { role: 3, ..state }).is_err());
37378        assert!(continuation_capacity_layout(SemanticTensorLayout {
37379            logical_axis: 1,
37380            ..active
37381        })
37382        .is_err());
37383    }
37384
37385    #[test]
37386    fn continuation_services_preserve_original_device_roster_and_capacity() {
37387        let layouts = continuation_service_layouts(9, 66, None).unwrap();
37388        let expected = [
37389            (3, 8, [32, 2, 0, 0]),
37390            (3, 8, [1, 0, 0, 0]),
37391            (8, 1, [32, 0, 0, 0]),
37392            (3, 8, [66, 4, 0, 0]),
37393            (3, 8, [1, 0, 0, 0]),
37394            (8, 1, [1, 0, 0, 0]),
37395        ];
37396        for (ordinal, (layout, (scalar_type, element_bytes, dimensions))) in
37397            layouts.iter().zip(expected).enumerate()
37398        {
37399            assert_eq!((layout.role, layout.index), (0, 9 + ordinal as u64));
37400            assert_eq!(
37401                (layout.scalar_type, layout.element_bytes, layout.dimensions),
37402                (scalar_type, element_bytes, dimensions)
37403            );
37404            assert_eq!(layout.logical_axis, u64::MAX);
37405            let bytes = tensor_layout_bytes(layout).unwrap();
37406            let range = tensor_content_range(layout, 0, 0, bytes).unwrap();
37407            assert_eq!(range.index, layout.index);
37408        }
37409        assert!(continuation_service_layouts(usize::MAX, 66, None).is_err());
37410        assert!(continuation_service_layouts(0, 0, None).is_err());
37411        let proposal = continuation_service_layouts(9, 66, Some(2)).unwrap();
37412        assert_eq!(proposal.len(), 7);
37413        assert_eq!(proposal[6].index, 15);
37414        assert_eq!(proposal[6].scalar_type, 9);
37415        assert_eq!(proposal[6].element_bytes, 8);
37416        assert_eq!(proposal[6].dimensions, [2, 2, 3, 0]);
37417        assert_eq!(tensor_layout_bytes(&proposal[6]).unwrap(), 96);
37418    }
37419
37420    #[test]
37421    fn block_roster_comes_from_the_original_model_contract_schema() {
37422        let schema = br#"{"counter_encoding":"u32-hex8","model":{"physical":{"head":{"kind":"parameter"},"state":{"kind":"buffer"},"trunk":{"kind":"parameter"}}}}"#;
37423        let mut record = vec![0u8; 104];
37424        record.extend_from_slice(schema);
37425        let layout = SemanticModelContractLayout {
37426            schema_begin: 104,
37427            schema_bytes: schema.len() as u64,
37428            schema_digest_offset: 0,
37429            generation_offset: 32,
37430            numerical_digest_offset: 40,
37431            identity_offset: 72,
37432        };
37433        assert_eq!(
37434            model_physical_parameter_roster(&record, layout).unwrap(),
37435            Some(vec!["head".into(), "trunk".into()])
37436        );
37437        let mut invalid = record;
37438        let location = invalid
37439            .windows(6)
37440            .position(|window| window == b"buffer")
37441            .unwrap();
37442        invalid[location..location + 6].copy_from_slice(b"broken");
37443        assert!(model_physical_parameter_roster(&invalid, layout).is_err());
37444    }
37445
37446    #[test]
37447    fn continuation_transport_does_not_rebase_original_suffix_or_nonpositional_outputs() {
37448        let suffix = canonical_tensor_layout(SemanticTensorLayout {
37449            role: 4,
37450            rank: 4,
37451            logical_axis: 2,
37452            element_bytes: 2,
37453            scalar_type: 4,
37454            dimensions: [1, 2, 32, 4],
37455            ..SemanticTensorLayout::default()
37456        })
37457        .unwrap();
37458        let cold = prefix_capacity_layout(
37459            SemanticTensorLayout {
37460                dimensions: [1, 2, 0, 4],
37461                ..suffix
37462            },
37463            16,
37464        )
37465        .unwrap();
37466        for (prefix, end) in [(0, 0), (3, 5), (16, 16)] {
37467            let pending = continuation_tensor_layout(&suffix, 0, 32, &cold).unwrap();
37468            assert_eq!(pending, suffix);
37469            assert!(continuation_tensor_layout(&suffix, prefix, end, &cold).is_err());
37470        }
37471        let state = canonical_tensor_layout(SemanticTensorLayout {
37472            role: 6,
37473            rank: 2,
37474            logical_axis: u64::MAX,
37475            element_bytes: 4,
37476            scalar_type: 6,
37477            dimensions: [4, 128, 0, 0],
37478            ..SemanticTensorLayout::default()
37479        })
37480        .unwrap();
37481        assert_eq!(
37482            continuation_tensor_layout(&state, 0, 0, &state).unwrap(),
37483            state
37484        );
37485        assert!(continuation_tensor_layout(&state, 3, 5, &state).is_err());
37486    }
37487
37488    #[test]
37489    fn cold_intent_owner_constructs_an_empty_queue_with_the_actual_effect() {
37490        let effect = b"deliver the committed token sequence to the request output";
37491        let records = initial_intent_records(effect, 2, 4096, 1024).unwrap();
37492        assert_eq!(records[0].role, SemanticStateRole::IntentEntries);
37493        assert_eq!(records[0].bytes.len(), size_of::<IntentQueueHeader>());
37494        assert_eq!(
37495            records[0].capacity_bytes,
37496            size_of::<IntentQueueHeader>() + 2 * size_of::<IntentEntry>()
37497        );
37498        // SAFETY: the production builder returned a complete padding-free header.
37499        let header = unsafe {
37500            records[0]
37501                .bytes
37502                .as_ptr()
37503                .cast::<IntentQueueHeader>()
37504                .read_unaligned()
37505        };
37506        assert_eq!((header.abi, header.count, header.capacity), (1, 0, 2));
37507        assert_eq!(header.chain_head, Identity256::default());
37508        assert_eq!(
37509            (header.effect_offset_bytes, header.effect_length_bytes),
37510            (0, effect.len() as u64)
37511        );
37512        assert_eq!(header.payload_used_bytes, effect.len() as u64);
37513        assert_eq!(header.payload_capacity_bytes, 4096);
37514        assert_eq!(records[1].role, SemanticStateRole::IntentPayload);
37515        assert_eq!(records[1].bytes, effect);
37516        assert_eq!(records[1].capacity_bytes, 4096);
37517        assert!(initial_intent_records(&[], 2, 4096, 1024).is_err());
37518        assert!(initial_intent_records(effect, 0, 4096, 1024).is_err());
37519        assert!(initial_intent_records(effect, u64::MAX, 4096, 1024).is_err());
37520        assert!(initial_intent_records(effect, 2, effect.len() + 1023, 1024).is_err());
37521    }
37522
37523    #[test]
37524    fn checkpoint_intent_projection_rechecks_the_native_key_and_chain() {
37525        let effect = b"record result";
37526        let output = 1u64.to_le_bytes();
37527        let mut material = publication_material_sample();
37528        let mut entry = IntentEntry {
37529            checkpoint_lineage: Identity256::from_bytes([1; 32]),
37530            base_logical: Identity256::from_bytes([2; 32]),
37531            effective_delta: Identity256::from_bytes([3; 32]),
37532            result_logical: Identity256::from_bytes([4; 32]),
37533            effect_digest: Identity256::from_bytes(Sha256::digest(effect).into()),
37534            payload_digest: Identity256::from_bytes(Sha256::digest(output).into()),
37535            payload_offset: effect.len() as u64,
37536            payload_len: output.len() as u64,
37537            ..IntentEntry::default()
37538        };
37539        let mut key = Sha256::new();
37540        key.update(0x786c6f67696e7431u64.to_le_bytes());
37541        for part in [
37542            entry.checkpoint_lineage,
37543            entry.base_logical,
37544            entry.effective_delta,
37545            entry.result_logical,
37546            entry.effect_digest,
37547            entry.payload_digest,
37548        ] {
37549            key.update(part.as_bytes());
37550        }
37551        entry.stable_identity = Identity256::from_bytes(key.finalize().into());
37552        entry.chain = publication_fold_digest(Identity256::default(), 30, 0, entry.stable_identity);
37553        let header = IntentQueueHeader {
37554            abi: 1,
37555            count: 1,
37556            capacity: 2,
37557            payload_used_bytes: (effect.len() + output.len()) as u64,
37558            payload_capacity_bytes: 64,
37559            effect_offset_bytes: 0,
37560            effect_length_bytes: effect.len() as u64,
37561            chain_head: entry.chain,
37562        };
37563        for range in &mut material.ranges {
37564            match range.range.role {
37565                30 => {
37566                    range.bytes = publication_abi_bytes(&[header]);
37567                    range.bytes.extend(publication_abi_bytes(&[entry]));
37568                    range.capacity = size_of::<IntentQueueHeader>() + 2 * size_of::<IntentEntry>();
37569                }
37570                31 => {
37571                    range.bytes = [effect.as_slice(), output.as_slice()].concat();
37572                    range.capacity = 64;
37573                }
37574                _ => continue,
37575            }
37576            range.range.length_bytes = range.bytes.len() as u64;
37577            range.range.digest = range.original_record_digest();
37578        }
37579        publication_material_sample_runtime(&mut material);
37580        material.bank.header.descriptor_digest = material.original_descriptor_digest();
37581        let encoded = material.encode().unwrap();
37582        let projected = output_intents_from_publication_material(&encoded).unwrap();
37583        assert_eq!(projected.len(), 1);
37584        assert_eq!(projected[0].stable_identity, entry.stable_identity);
37585        assert_eq!(projected[0].effect, effect);
37586        assert_eq!(projected[0].payload, output);
37587
37588        let entry_range = material
37589            .ranges
37590            .iter_mut()
37591            .find(|item| item.range.role == 30)
37592            .unwrap();
37593        let last = entry_range.bytes.last_mut().unwrap();
37594        *last ^= 1;
37595        entry_range.range.digest = entry_range.original_record_digest();
37596        material.bank.header.descriptor_digest = material.original_descriptor_digest();
37597        assert!(output_intents_from_publication_material(&material.encode().unwrap()).is_err());
37598    }
37599
37600    #[test]
37601    fn semantic_tensor_admission_preserves_original_type_strides_and_bounds() {
37602        let layout = SemanticTensorLayout {
37603            role: SemanticStateRole::AttentionKeys as u64,
37604            index: 0,
37605            element_bytes: 2,
37606            scalar_type: 4,
37607            rank: 4,
37608            logical_axis: 2,
37609            dimensions: [1, 2, 3, 4],
37610            strides_bytes: [48, 24, 8, 2],
37611        };
37612        let metadata = TensorMetadata {
37613            device_type: crate::dlpack::K_DLCUDA,
37614            device_id: 0,
37615            dtype: crate::dlpack::DLDataType {
37616                code: 2,
37617                bits: 16,
37618                lanes: 1,
37619            },
37620            shape: &[1, 2, 3, 4],
37621            strides: None,
37622            data: 0x1000,
37623            byte_offset: 2,
37624        };
37625        assert_eq!(
37626            validate_tensor_metadata(&layout, &metadata, 0).unwrap(),
37627            (0x1002, 48)
37628        );
37629        let mut wrong = metadata;
37630        wrong.dtype.code = 4; // BF16 is not F16 despite equal element width.
37631        assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37632        wrong = metadata;
37633        wrong.strides = Some(&[0, 0, 0, 0]);
37634        assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37635        wrong = metadata;
37636        wrong.device_id = 1;
37637        assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37638        wrong = metadata;
37639        wrong.data = u64::MAX - 1;
37640        assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37641        wrong = metadata;
37642        wrong.byte_offset = 1;
37643        assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37644        let mut transposed = layout;
37645        transposed.strides_bytes = [48, 2, 16, 4];
37646        let mut strided = metadata;
37647        strided.strides = Some(&[24, 1, 8, 2]);
37648        assert_eq!(
37649            validate_tensor_metadata(&transposed, &strided, 0).unwrap(),
37650            (0x1002, 48)
37651        );
37652        let mut empty = layout;
37653        empty.dimensions[2] = 0;
37654        empty.strides_bytes = [0, 0, 8, 2];
37655        let mut empty_metadata = metadata;
37656        empty_metadata.shape = &[1, 2, 0, 4];
37657        empty_metadata.data = 0;
37658        empty_metadata.byte_offset = 0;
37659        assert_eq!(
37660            validate_tensor_metadata(&empty, &empty_metadata, 0).unwrap(),
37661            (0, 0)
37662        );
37663    }
37664
37665    #[test]
37666    fn semantic_tensor_scalar_keeps_one_cell_and_original_rank() {
37667        for (scalar_type, element_bytes, code) in [
37668            (1, 1, 1),
37669            (2, 4, 1),
37670            (3, 8, 1),
37671            (4, 2, 2),
37672            (5, 2, 4),
37673            (6, 4, 2),
37674            (7, 8, 0),
37675            (8, 1, 6),
37676            (9, 8, 2),
37677        ] {
37678            let layout = SemanticTensorLayout {
37679                role: 18,
37680                index: 0,
37681                scalar_type,
37682                element_bytes,
37683                rank: 0,
37684                logical_axis: u64::MAX,
37685                dimensions: [0; 4],
37686                strides_bytes: [0; 4],
37687            };
37688            let metadata = TensorMetadata {
37689                device_type: crate::dlpack::K_DLCUDA,
37690                device_id: 0,
37691                dtype: crate::dlpack::DLDataType {
37692                    code,
37693                    bits: (element_bytes * 8) as u8,
37694                    lanes: 1,
37695                },
37696                shape: &[],
37697                strides: None,
37698                data: 4096,
37699                byte_offset: element_bytes,
37700            };
37701            assert_eq!(
37702                validate_tensor_metadata(&layout, &metadata, 0).unwrap(),
37703                (4096 + element_bytes, element_bytes as usize)
37704            );
37705            assert_eq!(
37706                tensor_layout_bytes(&layout).unwrap(),
37707                element_bytes as usize
37708            );
37709            assert_eq!(canonical_tensor_layout(layout).unwrap(), layout);
37710            assert_eq!(
37711                tensor_copy_plan(&layout, &layout).unwrap(),
37712                vec![(0, 0, element_bytes as usize)]
37713            );
37714            let mut wrong = metadata;
37715            wrong.data = 0;
37716            assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37717            wrong = metadata;
37718            wrong.shape = &[1];
37719            assert!(validate_tensor_metadata(&layout, &wrong, 0).is_err());
37720            let mut malformed = layout;
37721            malformed.logical_axis = 0;
37722            assert!(tensor_layout_bytes(&malformed).is_err());
37723            malformed = layout;
37724            malformed.dimensions[0] = 1;
37725            assert!(tensor_layout_bytes(&malformed).is_err());
37726            malformed = layout;
37727            malformed.strides_bytes[0] = element_bytes;
37728            assert!(tensor_layout_bytes(&malformed).is_err());
37729        }
37730    }
37731
37732    #[test]
37733    fn publication_material_scalar_layout_survives_cold_codec() {
37734        let mut material = publication_material_sample();
37735        let layout = material.layouts.get_mut(&(18, 0)).unwrap();
37736        layout.rank = 0;
37737        layout.dimensions = [0; 4];
37738        layout.strides_bytes = [0; 4];
37739        let scalar = *layout;
37740        let table = material
37741            .ranges
37742            .iter_mut()
37743            .find(|item| item.range.role == 55)
37744            .unwrap();
37745        table.bytes = tensor_table_bytes(
37746            &material.layouts.values().copied().collect::<Vec<_>>(),
37747            false,
37748            &[],
37749        )
37750        .unwrap();
37751        table.range.digest = table.original_record_digest();
37752        publication_material_sample_runtime(&mut material);
37753        material.bank.header.descriptor_digest = material.original_descriptor_digest();
37754        let encoded = material.encode().unwrap();
37755        let restored = PublicationMaterial::decode(&encoded).unwrap();
37756        assert_eq!(restored.layouts[&(18, 0)], scalar);
37757        let original = material
37758            .ranges
37759            .iter()
37760            .find(|item| item.range.role == 18)
37761            .unwrap();
37762        let actual = restored
37763            .ranges
37764            .iter()
37765            .find(|item| item.range.role == 18)
37766            .unwrap();
37767        assert_eq!(actual.bytes, original.bytes);
37768        assert_eq!(actual.bytes.len(), scalar.element_bytes as usize);
37769        assert_eq!(restored.encode().unwrap(), encoded);
37770    }
37771
37772    #[test]
37773    fn semantic_tensor_scalar_metadata_allows_null_zero_rank_arrays() {
37774        // Only the importer's metadata boundary runs here, not a device import.
37775        let mut value = 3.5f32;
37776        let mut descriptor = crate::dlpack::DLTensor {
37777            data: (&mut value as *mut f32).cast(),
37778            device: crate::dlpack::DLDevice {
37779                device_type: crate::dlpack::K_DLCUDA,
37780                device_id: 0,
37781            },
37782            ndim: 0,
37783            dtype: crate::dlpack::DLDataType {
37784                code: 2,
37785                bits: 32,
37786                lanes: 1,
37787            },
37788            shape: std::ptr::null_mut(),
37789            strides: std::ptr::null_mut(),
37790            byte_offset: 0,
37791        };
37792        let layout = SemanticTensorLayout {
37793            role: 18,
37794            index: 0,
37795            element_bytes: 4,
37796            scalar_type: 6,
37797            rank: 0,
37798            logical_axis: u64::MAX,
37799            dimensions: [0; 4],
37800            strides_bytes: [0; 4],
37801        };
37802        // SAFETY: zero-rank metadata has no array entries to dereference.
37803        let actual = unsafe { semantic_tensor_metadata(&descriptor) }.unwrap();
37804        assert!(actual.shape.is_empty());
37805        assert!(actual.strides.is_none());
37806        assert_eq!(
37807            validate_tensor_metadata(&layout, &actual, 0).unwrap(),
37808            ((&value as *const f32) as usize as u64, size_of::<f32>())
37809        );
37810        for ndim in [-1, 1, 4, 5] {
37811            descriptor.ndim = ndim;
37812            // SAFETY: invalid rank/null shape is rejected before any array read.
37813            assert!(unsafe { semantic_tensor_metadata(&descriptor) }.is_err());
37814        }
37815    }
37816
37817    #[test]
37818    fn publication_material_empty_model_buffer_keeps_zero_capacity() {
37819        for role in 18..=20 {
37820            let mut material = publication_material_sample();
37821            let layout = material.layouts.get_mut(&(role, 0)).unwrap();
37822            layout.rank = 3;
37823            layout.dimensions = [2, 0, 3, 0];
37824            layout.strides_bytes = [12, 12, 4, 0];
37825            let empty = *layout;
37826            let buffer = material
37827                .ranges
37828                .iter_mut()
37829                .find(|item| item.range.role == role)
37830                .unwrap();
37831            buffer.bytes.clear();
37832            buffer.capacity = 0;
37833            buffer.range.length_bytes = 0;
37834            let (allocation, offset) = material.model_memory.location(role, 0).unwrap();
37835            assert_eq!(offset, 0);
37836            material.model_allocations[allocation].clear();
37837            material.model_memory.allocation_bytes[allocation] = 0;
37838            material
37839                .model_memory
37840                .storages
37841                .iter_mut()
37842                .find(|storage| storage.allocation == allocation as u64)
37843                .unwrap()
37844                .span_bytes = 0;
37845            buffer.range.backing_digest = Identity256::from_bytes(Sha256::digest(b"").into());
37846            let table = material
37847                .ranges
37848                .iter_mut()
37849                .find(|item| item.range.role == 55)
37850                .unwrap();
37851            table.bytes = tensor_table_bytes(
37852                &material.layouts.values().copied().collect::<Vec<_>>(),
37853                false,
37854                &[],
37855            )
37856            .unwrap();
37857            table.range.digest = table.original_record_digest();
37858            publication_material_sample_runtime(&mut material);
37859            material.bank.header.descriptor_digest = material.original_descriptor_digest();
37860            let encoded = material.encode().unwrap();
37861            let restored = PublicationMaterial::decode(&encoded).unwrap();
37862            assert_eq!(restored.layouts[&(role, 0)], empty);
37863            let actual = restored
37864                .ranges
37865                .iter()
37866                .find(|item| item.range.role == role)
37867                .unwrap();
37868            assert!(actual.bytes.is_empty());
37869            assert_eq!(actual.capacity, 0);
37870            assert_eq!(tensor_layout_bytes(&empty).unwrap(), 0);
37871            assert!(tensor_copy_plan(&empty, &empty).unwrap().is_empty());
37872            assert_eq!(restored.encode().unwrap(), encoded);
37873            for (capacity, begin, end) in [(1, 0, 0), (0, 1, 1), (0, 0, 1)] {
37874                let buffer = material
37875                    .ranges
37876                    .iter_mut()
37877                    .find(|item| item.range.role == role)
37878                    .unwrap();
37879                buffer.capacity = capacity;
37880                buffer.range.logical_begin = begin;
37881                buffer.range.logical_end = end;
37882                publication_material_sample_runtime(&mut material);
37883                material.bank.header.descriptor_digest = material.original_descriptor_digest();
37884                assert!(
37885                    material.encode().is_err(),
37886                    "empty buffer accepted a fictitious capacity or interval"
37887                );
37888            }
37889            let buffer = material
37890                .ranges
37891                .iter_mut()
37892                .find(|item| item.range.role == role)
37893                .unwrap();
37894            buffer.capacity = 0;
37895            buffer.range.logical_begin = 0;
37896            buffer.range.logical_end = 0;
37897            publication_material_sample_runtime(&mut material);
37898            material.bank.header.descriptor_digest = material.original_descriptor_digest();
37899            material.layouts.get_mut(&(role, 0)).unwrap().dimensions[1] = 1;
37900            assert!(
37901                material.encode().is_err(),
37902                "nonempty model cells acquired zero capacity"
37903            );
37904        }
37905    }
37906
37907    #[test]
37908    fn feedback_payload_preserves_qualifiers_without_service_headers() {
37909        use crate::semantic_hypergraph::SemanticRecordEncoding;
37910        use crate::SemanticTypedRecord;
37911        use xlog_core::RelId;
37912
37913        let atom = |header: u8, value: u32| {
37914            let mut bytes = vec![header; 55];
37915            bytes.extend_from_slice(&17u32.to_le_bytes());
37916            bytes.extend_from_slice(&1u32.to_le_bytes());
37917            let start = bytes.len();
37918            bytes.push(1); // Canonical U32 argument tag.
37919            bytes.extend_from_slice(&value.to_le_bytes());
37920            let end = bytes.len();
37921            SemanticRecordEncoding {
37922                bytes,
37923                arguments: std::iter::once(start..end).collect(),
37924            }
37925        };
37926        let record = |qualifiers| SemanticTypedRecord {
37927            predicate: RelId(17),
37928            arguments: vec![crate::SemanticArgument::U32(1)],
37929            qualifiers,
37930        };
37931        let records = SemanticAdmissionRecords {
37932            predicates: vec![],
37933            records: vec![record(vec![1, 2]), record(vec![]), record(vec![])],
37934            supports: vec![],
37935        };
37936        let encoded = vec![atom(0xA5, 1), atom(0xA5, 2), atom(0xA5, 3)];
37937        let payload = feedback_statement_payload(&records, &encoded, 0).unwrap();
37938        let changed_headers = vec![atom(0x5A, 1), atom(0x5A, 2), atom(0x5A, 3)];
37939        assert_eq!(
37940            payload,
37941            feedback_statement_payload(&records, &changed_headers, 0).unwrap()
37942        );
37943        assert_eq!(&payload[..8], &13u64.to_le_bytes());
37944        assert_eq!(&payload[8..12], &17u32.to_le_bytes());
37945        assert_eq!(&payload[21..25], &2u32.to_le_bytes());
37946        let changed_values = vec![atom(0xA5, 1), atom(0xA5, 9), atom(0xA5, 3)];
37947        assert_ne!(
37948            payload,
37949            feedback_statement_payload(&records, &changed_values, 0).unwrap()
37950        );
37951        let mut reordered = records;
37952        reordered.records[0].qualifiers.reverse();
37953        assert_ne!(
37954            payload,
37955            feedback_statement_payload(&reordered, &encoded, 0).unwrap()
37956        );
37957    }
37958
37959    #[test]
37960    fn publication_tensor_layout_keeps_dtype_distinct_from_byte_width() {
37961        assert_eq!(size_of::<SemanticTensorLayout>(), 112);
37962    }
37963
37964    fn source_rows() -> [SourceSlot; 32] {
37965        let mut rows = [SourceSlot::default(); 32];
37966        // Source slots deliberately differ from logical and packed row order.
37967        rows[5] = SourceSlot {
37968            token: 40,
37969            logical_position: 0,
37970            kind: 1,
37971            provenance: 1,
37972            valid: 1,
37973            committed: 0,
37974            recomputed: 0,
37975            provenance_record: 0,
37976        };
37977        rows[1] = SourceSlot {
37978            token: MASK_TOKEN as u64,
37979            logical_position: 1,
37980            kind: 2,
37981            provenance: 0,
37982            valid: 1,
37983            committed: 0,
37984            recomputed: 0,
37985            provenance_record: 0,
37986        };
37987        rows[12] = SourceSlot {
37988            token: 42,
37989            logical_position: 2,
37990            kind: 1,
37991            provenance: 2,
37992            valid: 1,
37993            committed: 0,
37994            recomputed: 0,
37995            provenance_record: 2,
37996        };
37997        rows
37998    }
37999
38000    #[test]
38001    fn initial_source_ledger_derives_tokens_and_private_provenance_without_changing_geometry() {
38002        let mut ring = [SourceSlot::default(); 32];
38003        ring[7] = SourceSlot {
38004            token: 41,
38005            logical_position: 3,
38006            kind: 1,
38007            provenance: 1,
38008            valid: 1,
38009            ..SourceSlot::default()
38010        };
38011        ring[2] = SourceSlot {
38012            token: MASK_TOKEN as u64,
38013            logical_position: 4,
38014            kind: 2,
38015            valid: 1,
38016            ..SourceSlot::default()
38017        };
38018        let prefix = vec![SourceSlot {
38019            token: 40,
38020            logical_position: 0,
38021            kind: 1,
38022            provenance: 1,
38023            valid: 1,
38024            committed: 1,
38025            ..SourceSlot::default()
38026        }];
38027        let sources = [SemanticObservedSource {
38028            identity: "observation".into(),
38029            tokens: vec![40, 41],
38030            origin: b"complete admitted observation and manifest".to_vec(),
38031        }];
38032        let mapping = [
38033            SemanticSourceMapping {
38034                source: "observation".into(),
38035                offset: 0,
38036                logical_position: 0,
38037            },
38038            SemanticSourceMapping {
38039                source: "observation".into(),
38040                offset: 1,
38041                logical_position: 3,
38042            },
38043        ];
38044        let (actual, committed, ledger) = initial_source_ledger(
38045            ring,
38046            prefix.clone(),
38047            &sources,
38048            &mapping,
38049            b"complete task authority",
38050            3,
38051            34,
38052        )
38053        .unwrap();
38054        assert_eq!(
38055            (
38056                actual[7].token,
38057                actual[7].logical_position,
38058                actual[7].provenance_record
38059            ),
38060            (41, 3, 1)
38061        );
38062        assert_eq!(committed[0].provenance_record, 0);
38063        assert_eq!(actual[2].provenance, 0);
38064        assert_eq!(ledger.bytes.len(), 2 * size_of::<TokenProvenance>());
38065        assert_eq!(ledger.capacity_bytes, 34 * size_of::<TokenProvenance>());
38066        // SAFETY: production emitted two complete initialized integral records.
38067        let record = unsafe {
38068            ledger
38069                .bytes
38070                .as_ptr()
38071                .add(size_of::<TokenProvenance>())
38072                .cast::<TokenProvenance>()
38073                .read_unaligned()
38074        };
38075        assert_eq!(
38076            (
38077                record.source_slot,
38078                record.logical_position,
38079                record.token,
38080                record.ordinal,
38081                record.authority_generation
38082            ),
38083            (7, 3, 41, 1, 3)
38084        );
38085        assert_eq!(record.action_receipt_digest, Identity256::default());
38086        assert_ne!(record.origin_logical_digest, Identity256::default());
38087        assert_ne!(record.authority_closure_digest, Identity256::default());
38088        assert_ne!(record.record_digest, Identity256::default());
38089        for field in 0..7 {
38090            let mut changed = ring;
38091            let mut links = mapping.to_vec();
38092            match field {
38093                0 => changed[7].token = 42,
38094                1 => changed[7].provenance = 2,
38095                2 => changed[7].provenance_record = 99,
38096                3 => links[1].offset = 2,
38097                4 => links[1].logical_position = 4,
38098                5 => links[1].source = "foreign".into(),
38099                _ => links[1].logical_position = 0,
38100            }
38101            assert!(
38102                initial_source_ledger(
38103                    changed,
38104                    prefix.clone(),
38105                    &sources,
38106                    &links,
38107                    b"complete task authority",
38108                    3,
38109                    34
38110                )
38111                .is_err(),
38112                "mutation {field}"
38113            );
38114        }
38115    }
38116
38117    #[test]
38118    fn initial_source_layout_preserves_admitted_tokens_across_prefix_and_ring() {
38119        let sources = [SemanticObservedSource {
38120            identity: "observation".into(),
38121            tokens: (0..40).collect(),
38122            origin: b"complete admitted observation and manifest".to_vec(),
38123        }];
38124        let mapping = (0..40)
38125            .map(|position| SemanticSourceMapping {
38126                source: "observation".into(),
38127                offset: position,
38128                logical_position: position,
38129            })
38130            .collect::<Vec<_>>();
38131        let layout = initial_source_layout(
38132            &sources,
38133            &mapping,
38134            b"complete task authority",
38135            3,
38136            72,
38137            64,
38138            3,
38139            262144,
38140            248000,
38141        )
38142        .unwrap();
38143        assert_eq!(layout.prefill_tokens, (0..8).collect::<Vec<_>>());
38144        assert_eq!(layout.prefix.len(), 8);
38145        assert_eq!(layout.prefix[7].token, 7);
38146        assert_eq!(layout.prefix[7].committed, 1);
38147        assert_eq!(layout.source[0].token, 8);
38148        assert_eq!(layout.source[0].logical_position, 8);
38149        assert_eq!(layout.source[31].token, 39);
38150        assert_eq!(layout.source[31].logical_position, 39);
38151        assert_eq!(layout.source[31].committed, 0);
38152        assert_eq!(layout.ring_head, 0);
38153        assert_eq!(
38154            validate_text_parent(&layout.source, 8, 64, 3, 262144, layout.ring_head, 40).unwrap(),
38155            40
38156        );
38157    }
38158
38159    #[test]
38160    fn short_admitted_source_needs_no_model_prefill_stage() {
38161        let sources = [SemanticObservedSource {
38162            identity: "observation".into(),
38163            tokens: vec![7, 8],
38164            origin: b"complete admitted observation".to_vec(),
38165        }];
38166        let mapping = (0..2)
38167            .map(|position| SemanticSourceMapping {
38168                source: "observation".into(),
38169                offset: position,
38170                logical_position: position,
38171            })
38172            .collect::<Vec<_>>();
38173        let layout = initial_source_layout(
38174            &sources,
38175            &mapping,
38176            b"complete task authority",
38177            1,
38178            64,
38179            64,
38180            2,
38181            262144,
38182            248000,
38183        )
38184        .unwrap();
38185        assert!(layout.prefix.is_empty());
38186        assert!(layout.prefill_tokens.is_empty());
38187        assert_eq!(layout.source[0].token, 7);
38188        assert_eq!(layout.source[1].token, 8);
38189        assert_eq!(layout.ring_head, 2);
38190        assert_eq!(
38191            validate_text_parent(&layout.source, 0, 64, 2, 262144, 2, 2).unwrap(),
38192            2
38193        );
38194    }
38195
38196    #[test]
38197    fn initial_source_layout_rejects_uncovered_prefix_and_over_capacity() {
38198        let sources = [SemanticObservedSource {
38199            identity: "observation".into(),
38200            tokens: (0..40).collect(),
38201            origin: b"complete admitted observation and manifest".to_vec(),
38202        }];
38203        let mut mapping = (0..40)
38204            .map(|position| SemanticSourceMapping {
38205                source: "observation".into(),
38206                offset: position,
38207                logical_position: position,
38208            })
38209            .collect::<Vec<_>>();
38210        assert!(initial_source_layout(
38211            &sources,
38212            &mapping,
38213            b"complete task authority",
38214            3,
38215            72,
38216            7,
38217            3,
38218            262144,
38219            248000,
38220        )
38221        .is_err());
38222        assert!(initial_source_layout(
38223            &sources,
38224            &mapping,
38225            b"complete task authority",
38226            3,
38227            72,
38228            8,
38229            3,
38230            262144,
38231            248000,
38232        )
38233        .is_err());
38234        mapping.remove(3);
38235        assert!(initial_source_layout(
38236            &sources,
38237            &mapping,
38238            b"complete task authority",
38239            3,
38240            72,
38241            64,
38242            3,
38243            262144,
38244            248000,
38245        )
38246        .is_err());
38247    }
38248
38249    #[test]
38250    fn initial_prefill_input_requires_the_exact_model_token_tensor_layout() {
38251        let expected = SemanticTensorLayout {
38252            role: 0,
38253            index: 0,
38254            element_bytes: 8,
38255            scalar_type: 7,
38256            rank: 2,
38257            logical_axis: 1,
38258            dimensions: [1, 8, 0, 0],
38259            strides_bytes: [64, 8, 0, 0],
38260        };
38261        assert!(validate_initial_prefill_input_layout(&expected, 8).is_ok());
38262        for changed in [
38263            SemanticTensorLayout {
38264                scalar_type: 3,
38265                ..expected
38266            },
38267            SemanticTensorLayout {
38268                dimensions: [1, 7, 0, 0],
38269                ..expected
38270            },
38271            SemanticTensorLayout {
38272                dimensions: [2, 8, 0, 0],
38273                ..expected
38274            },
38275            SemanticTensorLayout {
38276                strides_bytes: [64, 16, 0, 0],
38277                ..expected
38278            },
38279        ] {
38280            assert!(validate_initial_prefill_input_layout(&changed, 8).is_err());
38281        }
38282        assert!(validate_initial_prefill_input_layout(&expected, 0).is_err());
38283    }
38284
38285    #[test]
38286    fn initial_prefill_content_witness_rejects_foreign_or_stale_owners() {
38287        let issuer = Arc::new(());
38288        let scope = Arc::new(());
38289        let identity = Identity256::from_bytes([7; 32]);
38290        let witness = SemanticInitialPrefillContentWitness {
38291            issuer: Arc::clone(&issuer),
38292            scope: Arc::clone(&scope),
38293            task_identity: identity,
38294            task_epoch: 3,
38295            model_generation: 5,
38296            slot: InitialPrefillContentSlot::Captured(1),
38297        };
38298        assert!(witness.matches(&issuer, &scope, identity, 3, 5, 2));
38299        assert!(!witness.matches(&Arc::new(()), &scope, identity, 3, 5, 2));
38300        assert!(!witness.matches(&issuer, &Arc::new(()), identity, 3, 5, 2));
38301        assert!(!witness.matches(&issuer, &scope, Identity256::from_bytes([8; 32]), 3, 5, 2,));
38302        assert!(!witness.matches(&issuer, &scope, identity, 4, 5, 2));
38303        assert!(!witness.matches(&issuer, &scope, identity, 3, 6, 2));
38304        assert!(!witness.matches(&issuer, &scope, identity, 3, 5, 1));
38305        let model = SemanticInitialPrefillContentWitness {
38306            slot: InitialPrefillContentSlot::Model,
38307            ..witness
38308        };
38309        assert!(model.matches(&issuer, &scope, identity, 3, 5, 0));
38310    }
38311
38312    #[test]
38313    fn initial_prefill_parent_can_add_only_native_source_ledger_indices() {
38314        let expected = SemanticTextSlot {
38315            token: 17,
38316            logical_position: 3,
38317            kind: 1,
38318            provenance: 1,
38319            valid: 1,
38320            committed: 1,
38321            ..SemanticTextSlot::default()
38322        };
38323        let actual = SemanticTextSlot {
38324            provenance_record: 9,
38325            ..expected
38326        };
38327        assert!(same_initial_source_rows(&[expected], &[actual]));
38328        assert!(!same_initial_source_rows(
38329            &[expected],
38330            &[SemanticTextSlot {
38331                token: 18,
38332                ..actual
38333            }],
38334        ));
38335        assert!(!same_initial_source_rows(&[expected], &[]));
38336    }
38337
38338    #[test]
38339    fn cold_text_parent_derives_only_contiguous_acquired_filled_coverage() {
38340        let rows = source_rows();
38341        assert_eq!(
38342            validate_text_parent(&rows, 0, 64, 2, 262144, 0, 3).unwrap(),
38343            1
38344        );
38345        assert_eq!(rows[1].kind, 2);
38346        assert_eq!(rows[12].logical_position, 2);
38347        assert_eq!(size_of::<SourceSlot>(), 64);
38348    }
38349
38350    #[test]
38351    fn cold_mask_source_keeps_the_sentinel_without_fabricated_token_provenance() {
38352        let mut rows = [SourceSlot::default(); 32];
38353        rows[7] = SourceSlot {
38354            token: 248078,
38355            kind: 2,
38356            valid: 1,
38357            ..SourceSlot::default()
38358        };
38359        assert_eq!(
38360            validate_text_parent(&rows, 0, 64, 2, 262144, 0, 0).unwrap(),
38361            0
38362        );
38363        rows[7].token = 0;
38364        assert!(validate_text_parent(&rows, 0, 64, 2, 262144, 0, 0).is_err());
38365        rows[7].token = 248078;
38366        rows[7].provenance_record = 1;
38367        assert!(validate_text_parent(&rows, 0, 64, 2, 262144, 0, 2).is_err());
38368    }
38369
38370    #[test]
38371    fn cold_text_parent_rejects_inconsistent_kind_and_source_metadata() {
38372        for field in 0..7 {
38373            let mut rows = source_rows();
38374            match field {
38375                0 => rows[1].provenance = 1,
38376                1 => rows[1].recomputed = 1,
38377                2 => rows[5].valid = 0,
38378                3 => rows[5].committed = 1,
38379                4 => rows[12].logical_position = 0,
38380                5 => rows[0].logical_position = 8,
38381                _ => rows[1].provenance_record = 3,
38382            }
38383            assert!(validate_text_parent(&rows, 0, 64, 2, 262144, 0, 3).is_err());
38384        }
38385    }
38386
38387    #[test]
38388    fn cold_text_parent_checks_prefix_and_reserved_position_capacity() {
38389        let rows = source_rows();
38390        assert!(validate_text_parent(&rows, 0, 0, 2, 262144, 0, 3).is_err());
38391        assert!(validate_text_parent(&rows, 1, 64, 2, 262144, 0, 3).is_err());
38392        assert!(validate_text_parent(&rows, 0, 64, 2, 97, 0, 3).is_err());
38393        assert!(validate_text_parent(&rows, 0, 64, 2, 262144, 32, 3).is_err());
38394        assert!(validate_text_parent(&rows, 0, u64::MAX, 2, 262144, 0, 3).is_err());
38395    }
38396}
38397
38398#[cfg(test)]
38399pub(crate) mod task_binding_tests {
38400    use super::*;
38401    use crate::{
38402        SemanticArgument, SemanticPolarity, SemanticPredicateRecord, SemanticSupportRecord,
38403        SemanticTypedRecord,
38404    };
38405    use xlog_core::{RelId, ScalarType, Schema};
38406
38407    #[derive(Debug)]
38408    struct ArithmeticProgram;
38409
38410    impl SemanticTaskProgram for ArithmeticProgram {
38411        fn observe(
38412            &self,
38413            _provider: Arc<CudaKernelProvider>,
38414        ) -> Result<SemanticTaskObservation, SemanticTransitionError> {
38415            Ok(arithmetic_observation())
38416        }
38417    }
38418
38419    pub(crate) fn arithmetic_observation() -> SemanticTaskObservation {
38420        let inputs = [[1u32, 1u32], [0u32, 1u32], [1u32, 0u32]];
38421        let results = inputs.map(|[left, right]| (left + right) / 2);
38422        SemanticTaskObservation {
38423            program_source: b"fn observe(left: u32, right: u32) -> u32 { (left + right) / 2 }"
38424                .to_vec(),
38425            input_bytes: inputs
38426                .into_iter()
38427                .flatten()
38428                .flat_map(u32::to_le_bytes)
38429                .collect(),
38430            result_bytes: results.into_iter().flat_map(u32::to_le_bytes).collect(),
38431            expected_truth: results.map(|result| {
38432                if result == 1 {
38433                    crate::SemanticTruth::True
38434                } else {
38435                    crate::SemanticTruth::False
38436                }
38437            }),
38438        }
38439    }
38440
38441    pub(crate) fn task_spec(
38442        statement_records: [u32; 3],
38443        allowed_support_records: Vec<u32>,
38444    ) -> SemanticTaskEvaluationSpec {
38445        SemanticTaskEvaluationSpec {
38446            statement_records,
38447            allowed_support_records,
38448            program: Arc::new(ArithmeticProgram),
38449            scoring: SemanticTaskScoring {
38450                correct_weight: 14,
38451                all_correct_weight: 7,
38452                work_weight: 1,
38453                improvement_weight: 45,
38454                refusal_weight: 15,
38455                spent_weight: 1,
38456            },
38457            priority_levels: Vec::new(),
38458            admissible_truth_masks: [7, 7, 7],
38459            actor_eligible: true,
38460            training_domain: None,
38461        }
38462    }
38463
38464    fn carry_records() -> SemanticAdmissionRecords {
38465        let mut records = SemanticAdmissionRecords {
38466            predicates: vec![SemanticPredicateRecord {
38467                predicate: RelId(17),
38468                role: SemanticRecordRole::Statement,
38469                schema: Schema::new(vec![
38470                    ("left".into(), ScalarType::U32),
38471                    ("right".into(), ScalarType::U32),
38472                ])
38473                .with_sort_labels(vec!["bit".into(), "bit".into()])
38474                .unwrap(),
38475            }],
38476            records: vec![
38477                SemanticTypedRecord {
38478                    predicate: RelId(17),
38479                    arguments: vec![SemanticArgument::U32(1), SemanticArgument::U32(1)],
38480                    qualifiers: vec![],
38481                },
38482                SemanticTypedRecord {
38483                    predicate: RelId(17),
38484                    arguments: vec![SemanticArgument::U32(0), SemanticArgument::U32(1)],
38485                    qualifiers: vec![],
38486                },
38487            ],
38488            supports: vec![SemanticSupportRecord {
38489                statement: 0,
38490                polarity: SemanticPolarity::Pro,
38491                provenance: 2,
38492                source: 3,
38493                context: 4,
38494                scope: 5,
38495            }],
38496        };
38497        for (index, role) in [
38498            SemanticRecordRole::Provenance,
38499            SemanticRecordRole::Source,
38500            SemanticRecordRole::Context,
38501            SemanticRecordRole::Scope,
38502        ]
38503        .into_iter()
38504        .enumerate()
38505        {
38506            let predicate = RelId(18 + index as u32);
38507            records.predicates.push(SemanticPredicateRecord {
38508                predicate,
38509                role,
38510                schema: Schema::new(vec![]),
38511            });
38512            records.records.push(SemanticTypedRecord {
38513                predicate,
38514                arguments: vec![],
38515                qualifiers: vec![],
38516            });
38517        }
38518        records
38519    }
38520
38521    #[test]
38522    fn task_query_validation_does_not_interpret_argument_values() {
38523        let mut records = carry_records();
38524        records.records[0].arguments = vec![SemanticArgument::U32(17), SemanticArgument::U32(23)];
38525        task_spec([0, 1, 1], vec![0])
38526            .validate_records(&records)
38527            .unwrap();
38528    }
38529
38530    #[test]
38531    fn application_observer_retains_input_and_output_bytes() {
38532        let observation = arithmetic_observation();
38533        assert_eq!(
38534            observation.input_bytes,
38535            [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,]
38536        );
38537        assert_eq!(
38538            observation.result_bytes,
38539            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
38540        );
38541        assert_eq!(
38542            observation.expected_truth,
38543            [
38544                crate::SemanticTruth::True,
38545                crate::SemanticTruth::False,
38546                crate::SemanticTruth::False,
38547            ]
38548        );
38549    }
38550
38551    #[test]
38552    fn cold_content_matches_final_task_without_scoring_or_authority_inputs() {
38553        let admission = crate::semantic_hypergraph::tests::admit_material_records(carry_records());
38554        let cold = TaskEvaluationBinding::cold_content(
38555            &admission,
38556            [0, 1, 1],
38557            &[0],
38558            None,
38559            arithmetic_observation(),
38560        )
38561        .unwrap();
38562        let mut spec = task_spec([0, 1, 1], vec![0]);
38563        let bound = TaskEvaluationBinding::bind(&admission, spec.clone(), arithmetic_observation())
38564            .unwrap();
38565        assert_eq!(cold, bound.content());
38566
38567        spec.scoring.correct_weight += 1;
38568        spec.actor_eligible = false;
38569        assert_eq!(
38570            cold,
38571            TaskEvaluationBinding::bind(&admission, spec, arithmetic_observation())
38572                .unwrap()
38573                .content(),
38574        );
38575
38576        let mut changed = arithmetic_observation();
38577        changed.result_bytes.push(0);
38578        assert_ne!(
38579            cold,
38580            TaskEvaluationBinding::cold_content(&admission, [0, 1, 1], &[0], None, changed)
38581                .unwrap(),
38582        );
38583
38584        let mut changed_query = arithmetic_observation();
38585        changed_query.input_bytes.push(0);
38586        assert_ne!(
38587            cold,
38588            TaskEvaluationBinding::cold_content(&admission, [0, 1, 1], &[0], None, changed_query,)
38589                .unwrap(),
38590        );
38591    }
38592
38593    #[test]
38594    #[cfg(feature = "semantic-policy")]
38595    fn task_result_material_binds_native_observer_program_and_results() {
38596        let admission = crate::semantic_hypergraph::tests::admit_material_records(carry_records());
38597        let original_observation = arithmetic_observation();
38598        let binding = TaskEvaluationBinding::bind(
38599            &admission,
38600            task_spec([0, 1, 1], vec![0]),
38601            arithmetic_observation(),
38602        )
38603        .unwrap();
38604        let material = binding.completed_result_material();
38605        assert_eq!(
38606            Sha256::digest(&material.bytes).as_slice(),
38607            material.identity.as_bytes()
38608        );
38609        assert!(material
38610            .bytes
38611            .windows(original_observation.result_bytes.len())
38612            .any(|part| part == original_observation.result_bytes));
38613
38614        let mut changed = original_observation;
38615        changed.program_source.push(b' ');
38616        let changed =
38617            TaskEvaluationBinding::bind(&admission, task_spec([0, 1, 1], vec![0]), changed)
38618                .unwrap();
38619        assert_ne!(
38620            changed.completed_result_material().identity,
38621            material.identity
38622        );
38623    }
38624
38625    #[test]
38626    fn task_binding_identity_seals_observer_execution_and_configuration() {
38627        let admission = crate::semantic_hypergraph::tests::admit_material_records(carry_records());
38628        let identity = |spec, observation| {
38629            TaskEvaluationBinding::bind(&admission, spec, observation)
38630                .unwrap()
38631                .identity()
38632        };
38633        let original = identity(task_spec([0, 1, 1], vec![0]), arithmetic_observation());
38634        assert_eq!(
38635            original,
38636            identity(task_spec([0, 1, 1], vec![0]), arithmetic_observation()),
38637            "independent bindings with identical bytes must have the same identity"
38638        );
38639        for changed in 0..15 {
38640            let mut spec = task_spec([0, 1, 1], vec![0]);
38641            let mut observation = arithmetic_observation();
38642            let field = match changed {
38643                0 => {
38644                    observation.program_source.push(b' ');
38645                    "program source"
38646                }
38647                1 => {
38648                    observation.input_bytes.push(0);
38649                    "observer inputs"
38650                }
38651                2 => {
38652                    observation.result_bytes.push(0);
38653                    "observer results"
38654                }
38655                3 => {
38656                    observation.expected_truth[0] = crate::SemanticTruth::Both;
38657                    "first expected truth"
38658                }
38659                4 => {
38660                    observation.expected_truth[1] = crate::SemanticTruth::Neither;
38661                    "second expected truth"
38662                }
38663                5 => {
38664                    observation.expected_truth[2] = crate::SemanticTruth::Neither;
38665                    "third expected truth"
38666                }
38667                6 => {
38668                    spec.scoring.correct_weight += 1;
38669                    "correct weight"
38670                }
38671                7 => {
38672                    spec.scoring.all_correct_weight += 1;
38673                    "all-correct weight"
38674                }
38675                8 => {
38676                    spec.scoring.work_weight += 1;
38677                    "work weight"
38678                }
38679                9 => {
38680                    spec.scoring.improvement_weight += 1;
38681                    "improvement weight"
38682                }
38683                10 => {
38684                    spec.scoring.refusal_weight += 1;
38685                    "refusal weight"
38686                }
38687                11 => {
38688                    spec.scoring.spent_weight += 1;
38689                    "spent weight"
38690                }
38691                12 => {
38692                    spec.admissible_truth_masks[0] = 15;
38693                    "first truth mask"
38694                }
38695                13 => {
38696                    spec.admissible_truth_masks[1] = 15;
38697                    "second truth mask"
38698                }
38699                _ => {
38700                    spec.admissible_truth_masks[2] = 15;
38701                    "third truth mask"
38702                }
38703            };
38704            assert_ne!(
38705                original,
38706                identity(spec, observation),
38707                "identity omitted {field}"
38708            );
38709        }
38710    }
38711
38712    #[test]
38713    fn task_truth_eligibility_requires_nonempty_four_valued_masks() {
38714        let admission = crate::semantic_hypergraph::tests::admit_material_records(carry_records());
38715        for slot in 0..3 {
38716            for mask in [0, 16, 128, 255] {
38717                let mut spec = task_spec([0, 1, 1], vec![0]);
38718                spec.admissible_truth_masks[slot] = mask;
38719                let result =
38720                    TaskEvaluationBinding::bind(&admission, spec, arithmetic_observation());
38721                assert!(
38722                    matches!(result, Err(SemanticTransitionError::InvalidInput { detail })
38723                    if detail.contains("nonempty four-valued mask")),
38724                    "slot {slot}, mask {mask}"
38725                );
38726            }
38727            for mask in 1..=15 {
38728                let mut spec = task_spec([0, 1, 1], vec![0]);
38729                spec.admissible_truth_masks[slot] = mask;
38730                TaskEvaluationBinding::bind(&admission, spec, arithmetic_observation()).unwrap();
38731            }
38732        }
38733    }
38734
38735    #[test]
38736    fn rule_codebook_covers_the_complete_admitted_binary_schema() {
38737        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
38738
38739        let admission = admit_material_records(root_material_records());
38740        let program = crate::SemanticProgramAdmission {
38741            predicate_count: 5,
38742            initial_facts: vec![],
38743            initial_rules: vec![],
38744            queries: [
38745                crate::SemanticProgramFact {
38746                    predicate: 4,
38747                    first: 1,
38748                    second: 3,
38749                },
38750                crate::SemanticProgramFact {
38751                    predicate: 4,
38752                    first: 1,
38753                    second: 4,
38754                },
38755                crate::SemanticProgramFact {
38756                    predicate: 4,
38757                    first: 4,
38758                    second: 3,
38759                },
38760            ],
38761        };
38762        let generic = ActionCodebooks::derive(&admission, 1, None).unwrap();
38763        let books = ActionCodebooks::derive(&admission, 1, Some(&program)).unwrap();
38764        assert_eq!(books.targets[..generic.targets.len()], generic.targets);
38765        assert_eq!(
38766            books.targets[generic.targets.len()..]
38767                .iter()
38768                .filter_map(|descriptor| match descriptor {
38769                    SemanticActionDescriptor::RulePredicate { predicate } => Some(*predicate),
38770                    _ => None,
38771                })
38772                .collect::<Vec<_>>(),
38773            (0..5).collect::<Vec<_>>()
38774        );
38775        assert_eq!(books.qualifiers.len(), generic.qualifiers.len());
38776        assert_eq!(books.leaves.len(), generic.leaves.len());
38777        assert_eq!(books.operands[..generic.operands.len()], generic.operands);
38778        assert_eq!(
38779            books.operands[generic.operands.len()..]
38780                .iter()
38781                .filter_map(|descriptor| match descriptor {
38782                    SemanticActionDescriptor::RulePredicate { predicate } => Some(*predicate),
38783                    _ => None,
38784                })
38785                .collect::<Vec<_>>(),
38786            (0..5).collect::<Vec<_>>()
38787        );
38788        assert_eq!(
38789            books.operands[generic.operands.len()..]
38790                .iter()
38791                .filter_map(|descriptor| match descriptor {
38792                    SemanticActionDescriptor::RuleVariable { index } => Some(*index),
38793                    _ => None,
38794                })
38795                .collect::<Vec<_>>(),
38796            (0..4).collect::<Vec<_>>()
38797        );
38798        for field in 3..=10 {
38799            assert_eq!(
38800                books.components[32 + field].cardinality as usize,
38801                books.operands.len() + 1
38802            );
38803        }
38804        for field in 7..=10 {
38805            assert_eq!(generic.components[32 + field].cardinality, 1);
38806        }
38807        assert_ne!(books.binding.digest, generic.binding.digest);
38808
38809        let mut changed_program = program.clone();
38810        changed_program
38811            .initial_facts
38812            .push(crate::SemanticProgramFact {
38813                predicate: 0,
38814                first: 10,
38815                second: 11,
38816            });
38817        let changed = ActionCodebooks::derive(&admission, 1, Some(&changed_program)).unwrap();
38818        assert_ne!(books.binding.digest, changed.binding.digest);
38819
38820        let predicate = |index| generic.operands.len() as u32 + 1 + index;
38821        let variable = |index| generic.operands.len() as u32 + 6 + index;
38822        let mut choices = [0u32; 18];
38823        choices[0] = 1;
38824        choices[1] = 2;
38825        choices[2] = generic.targets.len() as u32 + 5;
38826        choices[3] = predicate(0);
38827        choices[4] = predicate(1);
38828        choices[5] = variable(0);
38829        choices[6] = variable(2);
38830        choices[7] = variable(0);
38831        choices[8] = variable(1);
38832        choices[9] = variable(1);
38833        choices[10] = variable(2);
38834        let decoded = books.decoded_rule_insertion(&program, &choices).unwrap();
38835        assert_eq!(decoded.rule.head_predicate, 4);
38836        assert_eq!(decoded.rule.head_variables, [0, 2]);
38837        assert!(decoded.bytes.starts_with(b"XLOG-DECODED-RULE-INSERTION\0"));
38838        choices[6] = variable(3);
38839        assert!(books.decoded_rule_insertion(&program, &choices).is_err());
38840        choices[6] = variable(2);
38841        choices[3] = 1;
38842        assert!(books.decoded_rule_insertion(&program, &choices).is_err());
38843
38844        let mut too_many_predicates = program;
38845        too_many_predicates.predicate_count = 65_536;
38846        assert!(ActionCodebooks::derive(&admission, 1, Some(&too_many_predicates)).is_err());
38847    }
38848
38849    #[test]
38850    fn action_leaf_categories_preserve_equal_original_supports() {
38851        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
38852        let mut records = root_material_records();
38853        records.supports.push(records.supports[0].clone());
38854        records.supports.push(records.supports[0].clone());
38855        records.supports.last_mut().unwrap().statement = 1;
38856        let original_count = records.supports.len();
38857        let admission = admit_material_records(records);
38858        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
38859        assert_eq!(books.leaves.len(), original_count);
38860        assert_eq!(books.words[7], original_count as u64 + 1);
38861        let mut seen = BTreeSet::new();
38862        for (category, meaning) in books.leaves.iter().enumerate() {
38863            let SemanticActionDescriptor::SupportEvent { source_record } = meaning else {
38864                panic!("wrong leaf meaning")
38865            };
38866            assert!(seen.insert(*source_record));
38867            assert_eq!(
38868                books.words[books.words[6] as usize + 18 * (category + 1) + 17],
38869                u64::from(*source_record)
38870            );
38871        }
38872        assert_eq!(seen, (0..original_count as u32).collect());
38873        let layout = SemanticPolicyLayout::from_components(&books.components).unwrap();
38874        assert_eq!(layout.fields[17].cardinality, original_count + 1);
38875        assert_eq!(layout.fields[17].embeddings.len(), original_count * 128);
38876    }
38877
38878    #[test]
38879    #[cfg(feature = "semantic-policy")]
38880    fn policy_producer_geometry_keeps_full_mask_rows_and_boolean_support() {
38881        let layouts = policy_producer_layouts(97, 129).unwrap();
38882        let metadata = TensorMetadata {
38883            device_type: 2,
38884            device_id: 0,
38885            dtype: crate::dlpack::DLDataType {
38886                code: 2,
38887                bits: 32,
38888                lanes: 1,
38889            },
38890            shape: &[32, TEXT_CARDINALITY as i64],
38891            strides: None,
38892            data: 4096,
38893            byte_offset: 4,
38894        };
38895        assert_eq!(
38896            validate_tensor_metadata(&layouts[0], &metadata, 0).unwrap(),
38897            (4100, 32 * TEXT_CARDINALITY * 4)
38898        );
38899        let mut malformed = metadata;
38900        malformed.shape = &[1, TEXT_CARDINALITY as i64];
38901        assert!(validate_tensor_metadata(&layouts[0], &malformed, 0).is_err());
38902        malformed.shape = &[32 * TEXT_CARDINALITY as i64];
38903        assert!(validate_tensor_metadata(&layouts[0], &malformed, 0).is_err());
38904        malformed.shape = &[32, TEXT_CARDINALITY as i64];
38905        malformed.strides = Some(&[TEXT_CARDINALITY as i64 + 1, 1]);
38906        assert!(validate_tensor_metadata(&layouts[0], &malformed, 0).is_err());
38907        let support = TensorMetadata {
38908            device_type: 2,
38909            device_id: 0,
38910            dtype: crate::dlpack::DLDataType {
38911                code: 6,
38912                bits: 8,
38913                lanes: 1,
38914            },
38915            shape: &[97],
38916            strides: Some(&[1]),
38917            data: 4096,
38918            byte_offset: 0,
38919        };
38920        assert_eq!(
38921            validate_tensor_metadata(&layouts[1], &support, 0).unwrap(),
38922            (4096, 97)
38923        );
38924        let mut wrong_dtype = support;
38925        wrong_dtype.dtype.code = 1;
38926        assert!(validate_tensor_metadata(&layouts[1], &wrong_dtype, 0).is_err());
38927        assert_eq!(layouts[2].dimensions, [129, 0, 0, 0]);
38928    }
38929
38930    #[test]
38931    fn policy_support_reserves_every_original_category_span() {
38932        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
38933        let admission = admit_material_records(root_material_records());
38934        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
38935        let (spans, cells) = books.support_layout();
38936        assert_eq!(spans.len(), COMPONENT_COUNT);
38937        let mut cursor = 0;
38938        for (span, component) in spans.iter().zip(&books.components) {
38939            assert_eq!(span.start, cursor);
38940            assert_eq!(span.start, component.offset as usize);
38941            assert_eq!(span.len(), component.cardinality as usize);
38942            cursor = span.end;
38943        }
38944        assert_eq!(cells, cursor);
38945        assert_eq!(cells, books.input_cells);
38946        for lane in 0..2 {
38947            for slot in 0..32 {
38948                assert_eq!(spans[lane * 68 + slot].len(), TEXT_CARDINALITY);
38949            }
38950        }
38951    }
38952
38953    #[test]
38954    fn action_codebooks_retain_typed_reconstruction_sources() {
38955        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
38956        let admission = admit_material_records(root_material_records());
38957        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
38958        assert_eq!(
38959            books.words[4] - books.words[2],
38960            6 * books.words[3],
38961            "operand bank lost original argument reconstruction references"
38962        );
38963        assert_eq!(
38964            books.words[6] - books.words[4],
38965            3 * books.words[5],
38966            "qualifier bank lost original bundle reconstruction references"
38967        );
38968        for (category, meaning) in books.operands.iter().enumerate() {
38969            let SemanticActionDescriptor::Operand { encoded_value, .. } = meaning else {
38970                panic!("wrong operand meaning")
38971            };
38972            let row = books.words[2] as usize + 6 * (category + 1);
38973            let source = &admission.encoded_records[books.words[row + 4] as usize];
38974            assert_eq!(
38975                &source.bytes[source.arguments[books.words[row + 5] as usize].clone()],
38976                encoded_value
38977            );
38978        }
38979        for (category, meaning) in books.qualifiers.iter().enumerate() {
38980            let SemanticActionDescriptor::QualifierBundle { records } = meaning else {
38981                panic!("wrong qualifier meaning")
38982            };
38983            let source = books.words[books.words[4] as usize + 3 * (category + 1) + 2];
38984            if records.is_empty() {
38985                assert_eq!(source, u64::from(u32::MAX));
38986            } else {
38987                assert_eq!(
38988                    &admission.records().records[source as usize].qualifiers,
38989                    records
38990                );
38991            }
38992        }
38993    }
38994
38995    #[cfg(feature = "semantic-policy")]
38996    #[test]
38997    fn completed_action_law_and_codebook_materials_match_native_bindings() {
38998        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
38999
39000        let catalogue = SemanticActionCatalogue::current();
39001        let law = catalogue.completed_material();
39002        assert_eq!(law.identity, catalogue.binding().digest);
39003        assert_eq!(law.bytes, catalogue.canonical_bytes());
39004        assert_eq!(
39005            Sha256::digest(&law.bytes).as_slice(),
39006            law.identity.as_bytes()
39007        );
39008
39009        let admission = admit_material_records(root_material_records());
39010        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
39011        let codebook = books.completed_material();
39012        assert_eq!(codebook.identity, books.binding.digest);
39013        assert_eq!(codebook.bytes, publication_abi_bytes(&books.words));
39014        assert_ne!(codebook.identity, law.identity);
39015        assert_ne!(codebook.bytes, law.bytes);
39016
39017        let roster = books.completed_roster_material();
39018        assert_eq!(
39019            Sha256::digest(&roster.bytes).as_slice(),
39020            roster.identity.as_bytes()
39021        );
39022        assert_eq!(
39023            &roster.bytes[b"xlog.semantic-action-roster.v1\0".len()
39024                ..b"xlog.semantic-action-roster.v1\0".len() + 32],
39025            books.binding.digest.as_bytes()
39026        );
39027        assert_eq!(books.components.len(), COMPONENT_COUNT);
39028        let roster_rows = &roster.bytes[b"xlog.semantic-action-roster.v1\0".len() + 32 + 8..];
39029        assert_eq!(roster_rows.len(), COMPONENT_COUNT * 7 * 8);
39030        for (row, component) in roster_rows.chunks_exact(7 * 8).zip(&books.components) {
39031            let values: Vec<u64> = row
39032                .chunks_exact(8)
39033                .map(|word| u64::from_le_bytes(word.try_into().unwrap()))
39034                .collect();
39035            assert_eq!(
39036                values,
39037                [
39038                    component.offset,
39039                    component.ordinal as u64,
39040                    component.lane as u64,
39041                    component.slot as u64,
39042                    component.field as u64,
39043                    component.kind as u64,
39044                    component.cardinality as u64,
39045                ]
39046            );
39047        }
39048        assert_ne!(roster.identity, codebook.identity);
39049        let other_owner_books = ActionCodebooks::derive(&admission, 2, None).unwrap();
39050        assert_ne!(
39051            other_owner_books.completed_material().identity,
39052            codebook.identity
39053        );
39054        assert_ne!(
39055            other_owner_books.completed_roster_material().identity,
39056            roster.identity
39057        );
39058    }
39059
39060    #[test]
39061    #[cfg(feature = "semantic-policy")]
39062    fn decoded_support_insertion_matches_admitted_native_identity() {
39063        use crate::semantic_hypergraph::tests::{
39064            admit_material_records, reconstructed_material_statement, root_material_records,
39065        };
39066
39067        let admission = admit_material_records(root_material_records());
39068        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
39069        let mut choices = [0u32; 18];
39070        choices[0] = 1;
39071        choices[1] = 1;
39072        choices[2] = 1;
39073        choices[3] = 1;
39074        choices[11] = 1;
39075        choices[17] = 1;
39076        let decoded = books
39077            .decoded_support_insertion(&admission, &choices)
39078            .unwrap()
39079            .unwrap();
39080        let statement =
39081            reconstructed_material_statement(&admission, None, &decoded.reconstruction).unwrap();
39082        assert_eq!(decoded.statement, statement.identity());
39083        assert_eq!(
39084            decoded.support,
39085            admission
39086                .support_event(decoded.source_event)
39087                .unwrap()
39088                .identity(decoded.statement)
39089        );
39090        assert!(decoded
39091            .bytes
39092            .starts_with(b"XLOG-DECODED-SUPPORT-INSERTION\0"));
39093        choices[0] = 0;
39094        assert!(books
39095            .decoded_support_insertion(&admission, &choices)
39096            .unwrap()
39097            .is_none());
39098    }
39099
39100    #[test]
39101    #[cfg(feature = "semantic-policy")]
39102    fn completed_theory_delta_requires_an_attempted_native_insertion() {
39103        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
39104
39105        let admission = admit_material_records(root_material_records());
39106        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
39107        let mut choices = [0u32; 18];
39108        choices[0] = 1;
39109        choices[1] = 1;
39110        choices[2] = 1;
39111        choices[3] = 1;
39112        choices[11] = 1;
39113        choices[17] = 1;
39114        let decoded = books
39115            .decoded_support_insertion(&admission, &choices)
39116            .unwrap()
39117            .unwrap();
39118        let owner = Identity256::from_bytes([3; 32]);
39119        let predecessor = Identity256::from_bytes([4; 32]);
39120        let mut hard_decode = [0u64; 42];
39121        hard_decode[1] = 1;
39122        hard_decode[20..24].copy_from_slice(&identity_words(*decoded.statement.as_bytes()));
39123        hard_decode[24..28].copy_from_slice(&identity_words(*decoded.support.as_bytes()));
39124        let admission_receipt = [0u64; 42];
39125        let components = [SemanticTransitionReceipt::default(); 18];
39126        let delta = completed_theory_delta_for_slot(
39127            &books,
39128            &admission,
39129            None,
39130            Identity256::from_bytes([0; 32]),
39131            owner,
39132            predecessor,
39133            0,
39134            0,
39135            &choices,
39136            None,
39137            &hard_decode,
39138            &admission_receipt,
39139            &components,
39140            0,
39141        )
39142        .unwrap()
39143        .unwrap();
39144        assert_eq!(delta.kind, "fact");
39145        assert_eq!(delta.theory_generation, predecessor);
39146        assert_eq!(delta.verdict, "accepted");
39147        assert!(delta
39148            .delta
39149            .bytes
39150            .windows(decoded.bytes.len())
39151            .any(|part| part == decoded.bytes));
39152        hard_decode[20] ^= 1;
39153        assert!(completed_theory_delta_for_slot(
39154            &books,
39155            &admission,
39156            None,
39157            Identity256::from_bytes([0; 32]),
39158            owner,
39159            predecessor,
39160            0,
39161            0,
39162            &choices,
39163            None,
39164            &hard_decode,
39165            &admission_receipt,
39166            &components,
39167            0,
39168        )
39169        .is_err());
39170        hard_decode[1] = 0;
39171        assert!(completed_theory_delta_for_slot(
39172            &books,
39173            &admission,
39174            None,
39175            Identity256::from_bytes([0; 32]),
39176            owner,
39177            predecessor,
39178            0,
39179            0,
39180            &choices,
39181            None,
39182            &hard_decode,
39183            &admission_receipt,
39184            &components,
39185            1,
39186        )
39187        .unwrap()
39188        .is_none());
39189    }
39190
39191    #[test]
39192    #[cfg(feature = "semantic-policy")]
39193    fn decoded_rule_delta_seals_every_structural_field_and_prior_edit() {
39194        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
39195
39196        let admission = admit_material_records(root_material_records());
39197        let program = crate::SemanticProgramAdmission {
39198            predicate_count: 3,
39199            initial_facts: vec![],
39200            initial_rules: vec![],
39201            queries: [
39202                crate::SemanticProgramFact {
39203                    predicate: 2,
39204                    first: 1,
39205                    second: 3,
39206                },
39207                crate::SemanticProgramFact {
39208                    predicate: 2,
39209                    first: 1,
39210                    second: 4,
39211                },
39212                crate::SemanticProgramFact {
39213                    predicate: 2,
39214                    first: 4,
39215                    second: 3,
39216                },
39217            ],
39218        };
39219        let generic = ActionCodebooks::derive(&admission, 1, None).unwrap();
39220        let books = ActionCodebooks::derive(&admission, 1, Some(&program)).unwrap();
39221        let predicate = |index| generic.operands.len() as u32 + 1 + index;
39222        let variable = |index| generic.operands.len() as u32 + 4 + index;
39223        let mut choices = [0u32; 18];
39224        choices[0] = 1;
39225        choices[1] = 2;
39226        choices[2] = generic.targets.len() as u32 + 3;
39227        choices[3] = predicate(0);
39228        choices[4] = predicate(1);
39229        choices[5] = variable(0);
39230        choices[6] = variable(2);
39231        choices[7] = variable(0);
39232        choices[8] = variable(1);
39233        choices[9] = variable(1);
39234        choices[10] = variable(2);
39235        let decoded = books.decoded_rule_insertion(&program, &choices).unwrap();
39236        assert_eq!(decoded.rule.head_predicate, 2);
39237        assert_eq!(decoded.rule.head_variables, [0, 2]);
39238        let owner = Identity256::from_bytes([3; 32]);
39239        let predecessor = Identity256::from_bytes([4; 32]);
39240        let task = Identity256::from_bytes([9; 32]);
39241        let mut hard_decode = [0u64; 42];
39242        hard_decode[1] = 3;
39243        hard_decode[2] = 1;
39244        hard_decode[4..8].copy_from_slice(&identity_words(*task.as_bytes()));
39245        hard_decode[8..12].copy_from_slice(&identity_words(*books.binding.digest.as_bytes()));
39246        hard_decode[12..22].copy_from_slice(&semantic_program_rule_words(decoded.rule));
39247        let admission_receipt = [0u64; 42];
39248        let components = [SemanticTransitionReceipt::default(); 18];
39249        let project = |receipt: &[u64; 42], slot, previous| {
39250            completed_theory_delta_for_slot(
39251                &books,
39252                &admission,
39253                Some(&program),
39254                task,
39255                owner,
39256                predecessor,
39257                0,
39258                slot,
39259                &choices,
39260                previous,
39261                receipt,
39262                &admission_receipt,
39263                &components,
39264                0,
39265            )
39266        };
39267        let delta = project(&hard_decode, 0, None).unwrap().unwrap();
39268        assert_eq!(delta.kind, "rule");
39269        assert_eq!(
39270            delta.theory_generation,
39271            ActionCodebooks::program_binding(&program)
39272        );
39273        for field in 12..22 {
39274            let mut changed = hard_decode;
39275            changed[field] ^= 1;
39276            assert!(
39277                project(&changed, 0, None).is_err(),
39278                "unsealed rule field {field}"
39279            );
39280        }
39281        let mut second = hard_decode;
39282        second[3] = 1;
39283        second[24] = 1;
39284        second[25..35].copy_from_slice(&semantic_program_rule_words(decoded.rule));
39285        let second_delta = project(&second, 1, Some(&choices)).unwrap().unwrap();
39286        assert_ne!(second_delta.theory_generation, delta.theory_generation);
39287        second[25] ^= 1;
39288        assert!(project(&second, 1, Some(&choices)).is_err());
39289        let mut invalid = choices;
39290        invalid[6] = variable(3);
39291        assert!(books.decoded_rule_insertion(&program, &invalid).is_err());
39292        invalid = choices;
39293        invalid[3] = 1;
39294        assert!(books.decoded_rule_insertion(&program, &invalid).is_err());
39295
39296        let mut fact_choices = [0u32; 18];
39297        fact_choices[0] = 1;
39298        fact_choices[1] = 1;
39299        fact_choices[2] = 1;
39300        fact_choices[3] = 1;
39301        fact_choices[11] = 1;
39302        fact_choices[17] = 1;
39303        let fact = books
39304            .decoded_support_insertion(&admission, &fact_choices)
39305            .unwrap()
39306            .unwrap();
39307        let mut fact_receipt = [0u64; 42];
39308        fact_receipt[1] = 1;
39309        fact_receipt[20..24].copy_from_slice(&identity_words(*fact.statement.as_bytes()));
39310        fact_receipt[24..28].copy_from_slice(&identity_words(*fact.support.as_bytes()));
39311        assert!(completed_theory_delta_for_slot(
39312            &books,
39313            &admission,
39314            Some(&program),
39315            task,
39316            owner,
39317            predecessor,
39318            0,
39319            0,
39320            &fact_choices,
39321            None,
39322            &fact_receipt,
39323            &admission_receipt,
39324            &components,
39325            0,
39326        )
39327        .is_err());
39328    }
39329
39330    #[test]
39331    fn program_query_receipts_bind_each_executed_query_to_the_program() {
39332        use crate::semantic_hypergraph::tests::{admit_material_records, root_material_records};
39333
39334        let admission = admit_material_records(root_material_records());
39335        let fact = crate::SemanticProgramFact {
39336            predicate: 0,
39337            first: 1,
39338            second: 2,
39339        };
39340        let program = crate::SemanticProgramAdmission {
39341            predicate_count: 1,
39342            initial_facts: vec![fact],
39343            initial_rules: vec![],
39344            queries: [fact; 3],
39345        };
39346        let books = ActionCodebooks::derive(&admission, 1, Some(&program)).unwrap();
39347        let task = Identity256::from_bytes([7; 32]);
39348        let edits = [[[0u32; 18]; 2]; 2];
39349        let mut state = DeviceState {
39350            binding_digest: books.binding.digest,
39351            ..DeviceState::default()
39352        };
39353        state.task_evaluation.query_count = 9;
39354        for slot in 0..3 {
39355            state.task_evaluation.facts[slot].truth = [1; 3];
39356            for query in 0..3 {
39357                let receipt = &mut state.task_evaluation.query_receipts[slot][query];
39358                receipt[1] = 0x5850524f47515545;
39359                receipt[2] = 1;
39360                receipt[3] = slot as u64;
39361                receipt[4] = query as u64;
39362                receipt[5..9].copy_from_slice(&identity_words(*task.as_bytes()));
39363                receipt[9..13].copy_from_slice(&identity_words(*books.binding.digest.as_bytes()));
39364                receipt[34..37].copy_from_slice(&[0, 1, 2]);
39365                receipt[38] = 1;
39366                receipt[41] = 1;
39367            }
39368        }
39369        assert!(validate_program_query_receipts(&program, task, &books, &state, &edits).is_ok());
39370        state.task_evaluation.query_receipts[2][1][34] = 1;
39371        assert!(validate_program_query_receipts(&program, task, &books, &state, &edits).is_err());
39372        state.task_evaluation.query_receipts[2][1][34] = 0;
39373        let mut fact_edit = edits;
39374        fact_edit[0][0][0] = 1;
39375        fact_edit[0][0][1] = 1;
39376        assert!(
39377            validate_program_query_receipts(&program, task, &books, &state, &fact_edit).is_err()
39378        );
39379
39380        let generic = ActionCodebooks::derive(&admission, 1, None).unwrap();
39381        let predicate = generic.operands.len() as u32 + 1;
39382        let first = predicate + 1;
39383        let second = first + 1;
39384        let mut rule_choice = [0u32; 18];
39385        rule_choice[0..11].copy_from_slice(&[
39386            1,
39387            2,
39388            generic.targets.len() as u32 + 1,
39389            predicate,
39390            predicate,
39391            first,
39392            second,
39393            first,
39394            second,
39395            first,
39396            second,
39397        ]);
39398        let rule = books
39399            .decoded_rule_insertion(&program, &rule_choice)
39400            .unwrap()
39401            .rule;
39402        let mut rule_edits = edits;
39403        rule_edits[0] = [rule_choice; 2];
39404        for query in 0..3 {
39405            let receipt = &mut state.task_evaluation.query_receipts[1][query];
39406            receipt[13] = 2;
39407            receipt[14..24].copy_from_slice(&semantic_program_rule_words(rule));
39408            receipt[24..34].copy_from_slice(&semantic_program_rule_words(rule));
39409            receipt[37] = 2;
39410        }
39411        state.work[0].edit_commands = 2;
39412        assert!(
39413            validate_program_query_receipts(&program, task, &books, &state, &rule_edits).is_ok()
39414        );
39415        state.task_evaluation.query_receipts[1][2][25] ^= 1;
39416        assert!(
39417            validate_program_query_receipts(&program, task, &books, &state, &rule_edits).is_err()
39418        );
39419
39420        let mut hard_decode = [0u64; 42];
39421        hard_decode[1] = 3;
39422        hard_decode[2] = 1;
39423        hard_decode[4..8].copy_from_slice(&identity_words(*task.as_bytes()));
39424        hard_decode[8..12].copy_from_slice(&identity_words(*books.binding.digest.as_bytes()));
39425        hard_decode[12..22].copy_from_slice(&semantic_program_rule_words(rule));
39426        hard_decode[22] = 1;
39427        assert_eq!(
39428            validated_rule_receipt(
39429                &books,
39430                &program,
39431                task,
39432                0,
39433                0,
39434                &rule_choice,
39435                None,
39436                &hard_decode,
39437            )
39438            .unwrap()
39439            .0
39440            .rule,
39441            rule
39442        );
39443        hard_decode[12] ^= 1;
39444        assert!(validated_rule_receipt(
39445            &books,
39446            &program,
39447            task,
39448            0,
39449            0,
39450            &rule_choice,
39451            None,
39452            &hard_decode,
39453        )
39454        .is_err());
39455    }
39456
39457    #[test]
39458    #[cfg(feature = "semantic-policy")]
39459    fn completed_task_scoring_matches_native_work_and_selection() {
39460        let scoring = task_spec([0, 1, 0], vec![]).scoring;
39461        let facts = [
39462            SemanticTaskFacts {
39463                g: 1,
39464                v: 14,
39465                eligible: 1,
39466                ..SemanticTaskFacts::default()
39467            },
39468            SemanticTaskFacts {
39469                g: 2,
39470                c: 3,
39471                v: 25,
39472                eligible: 1,
39473                ..SemanticTaskFacts::default()
39474            },
39475            SemanticTaskFacts::default(),
39476        ];
39477        let work = [
39478            SemanticTransitionWork {
39479                edit_commands: 1,
39480                added_supports: 1,
39481                defined_truth_changes: 1,
39482            },
39483            SemanticTransitionWork::default(),
39484        ];
39485        assert!(validate_completed_task_scoring(
39486            scoring,
39487            false,
39488            &[],
39489            &facts,
39490            &work,
39491            [0, 1],
39492            6,
39493            1,
39494            474,
39495        ));
39496        let mut changed = facts;
39497        changed[1].c = 2;
39498        assert!(!validate_completed_task_scoring(
39499            scoring,
39500            false,
39501            &[],
39502            &changed,
39503            &work,
39504            [0, 1],
39505            6,
39506            1,
39507            474,
39508        ));
39509        changed = facts;
39510        changed[1].v = 26;
39511        assert!(!validate_completed_task_scoring(
39512            scoring,
39513            false,
39514            &[],
39515            &changed,
39516            &work,
39517            [0, 1],
39518            6,
39519            1,
39520            474,
39521        ));
39522        assert!(!validate_completed_task_scoring(
39523            scoring,
39524            false,
39525            &[],
39526            &facts,
39527            &work,
39528            [0, 1],
39529            6,
39530            0,
39531            474,
39532        ));
39533        assert!(!validate_completed_task_scoring(
39534            scoring,
39535            false,
39536            &[],
39537            &facts,
39538            &work,
39539            [0, 1],
39540            6,
39541            1,
39542            475,
39543        ));
39544
39545        let mut refused_after_first_edit = facts;
39546        refused_after_first_edit[2].c = 3;
39547        refused_after_first_edit[2].v = -3;
39548        let partial_work = [work[0], work[0]];
39549        assert!(validate_completed_task_scoring(
39550            scoring,
39551            false,
39552            &[],
39553            &refused_after_first_edit,
39554            &partial_work,
39555            [0, 1],
39556            6,
39557            1,
39558            472,
39559        ));
39560
39561        let mut tied = facts;
39562        tied[1].g = 1;
39563        tied[1].c = 0;
39564        tied[1].v = 14;
39565        assert!(validate_completed_task_scoring(
39566            scoring,
39567            false,
39568            &[],
39569            &tied,
39570            &[SemanticTransitionWork::default(); 2],
39571            [0, 1],
39572            6,
39573            0,
39574            -21,
39575        ));
39576    }
39577
39578    #[test]
39579    #[cfg(feature = "semantic-policy")]
39580    fn task_priority_can_select_lower_value_and_negative_return() {
39581        let scoring = task_spec([0, 1, 0], vec![]).scoring;
39582        let priority_levels = [SemanticTaskPriorityLevel {
39583            goals: vec![SemanticTaskPriorityGoal {
39584                query: 0,
39585                target_truth: 1,
39586                weight: 1,
39587            }],
39588        }];
39589        let facts = [
39590            SemanticTaskFacts {
39591                g: 2,
39592                v: 28,
39593                eligible: 1,
39594                truth: [0, 1, 1],
39595                ..SemanticTaskFacts::default()
39596            },
39597            SemanticTaskFacts {
39598                g: 1,
39599                c: 1,
39600                v: 13,
39601                eligible: 1,
39602                truth: [1, 0, 0],
39603                ..SemanticTaskFacts::default()
39604            },
39605            SemanticTaskFacts::default(),
39606        ];
39607        let work = [
39608            SemanticTransitionWork {
39609                edit_commands: 1,
39610                ..SemanticTransitionWork::default()
39611            },
39612            SemanticTransitionWork::default(),
39613        ];
39614        let return_value = 45 * (13 - 28) - 3;
39615        assert!(return_value < -44);
39616        assert!(i64::from(return_value).abs() <= scoring.return_bound(false).unwrap());
39617        assert!(validate_completed_task_scoring(
39618            scoring,
39619            false,
39620            &priority_levels,
39621            &facts,
39622            &work,
39623            [0, 0],
39624            3,
39625            1,
39626            i64::from(return_value),
39627        ));
39628    }
39629
39630    #[test]
39631    #[cfg(feature = "semantic-policy")]
39632    fn completed_task_scoring_law_retains_coefficients_and_finite_bound() {
39633        let scoring = task_spec([0, 1, 0], vec![]).scoring;
39634        let task = Identity256::from_bytes([11; 32]);
39635        let bytes = scoring.completed_law_bytes(task, false).unwrap();
39636        let mut expected = b"XLOG-TASK-SCORING-LAW\0".to_vec();
39637        expected.extend_from_slice(&2u64.to_le_bytes());
39638        expected.extend_from_slice(task.as_bytes());
39639        let cost = semantic_structural_cost_descriptor(false);
39640        expected.extend_from_slice(cost.unit.as_bytes());
39641        expected.extend_from_slice(&cost.cap.to_le_bytes());
39642        for weight in [14u64, 7, 1, 45, 15, 1] {
39643            expected.extend_from_slice(&weight.to_le_bytes());
39644        }
39645        expected.extend_from_slice(&scoring.return_bound(false).unwrap().to_le_bytes());
39646        assert_eq!(bytes, expected);
39647        assert_eq!(scoring.return_bound(false).unwrap(), 2522);
39648        let structural = scoring.completed_law_bytes(task, true).unwrap();
39649        assert_eq!(scoring.return_bound(true).unwrap(), 186799);
39650        assert_eq!(
39651            structural[structural.len() - size_of::<i64>()..],
39652            scoring.return_bound(true).unwrap().to_le_bytes()
39653        );
39654    }
39655
39656    #[test]
39657    fn checkpoint_scoring_identity_tracks_the_bound_law() {
39658        let scoring = SemanticTaskScoring {
39659            correct_weight: 14,
39660            all_correct_weight: 7,
39661            work_weight: 1,
39662            improvement_weight: 45,
39663            refusal_weight: 15,
39664            spent_weight: 1,
39665        };
39666        let task = SemanticTaskContentIdentity {
39667            query: Identity256::from_bytes([11; 32]),
39668            theory_program: Identity256::from_bytes([12; 32]),
39669            result: Identity256::from_bytes([13; 32]),
39670        };
39671        let baseline = checkpoint_scoring_law_identity(
39672            scoring,
39673            task,
39674            scoring.objective_law(false).unwrap(),
39675            None,
39676        );
39677        assert_ne!(
39678            baseline,
39679            checkpoint_scoring_law_identity(
39680                scoring,
39681                task,
39682                scoring.objective_law(true).unwrap(),
39683                None
39684            )
39685        );
39686        let mut changed = scoring;
39687        changed.correct_weight += 1;
39688        assert_ne!(
39689            baseline,
39690            checkpoint_scoring_law_identity(
39691                changed,
39692                task,
39693                changed.objective_law(false).unwrap(),
39694                None
39695            )
39696        );
39697    }
39698
39699    pub(crate) fn verify_native_decoded_reconstruction(
39700        executable: &std::path::Path,
39701        directory: &std::path::Path,
39702        run: &impl Fn(&mut std::process::Command),
39703    ) {
39704        use crate::semantic_hypergraph::tests::{
39705            admit_material_records, reconstructed_material_statement, root_material_records,
39706        };
39707        let mut records = root_material_records();
39708        records.supports.push(records.supports[0].clone());
39709        let admission = admit_material_records(records);
39710        let books = ActionCodebooks::derive(&admission, 1, None).unwrap();
39711        let leaf = books
39712            .leaves
39713            .iter()
39714            .position(|value| {
39715                matches!(
39716                    value,
39717                    SemanticActionDescriptor::SupportEvent { source_record: 3 }
39718                )
39719            })
39720            .unwrap() as u32
39721            + 1;
39722        for (ordinal, operand) in [1, books.operands.len() as u32].into_iter().enumerate() {
39723            let mut choices = [0u32; SEMANTIC_TRANSITION_COMPONENT_COUNT];
39724            choices[2] = 1;
39725            choices[3] = operand;
39726            choices[11] = 1;
39727            choices[17] = leaf;
39728            let mut input = format!("{}\n", books.words.len());
39729            for word in &books.words {
39730                input.push_str(&format!("{word} "));
39731            }
39732            for choice in choices {
39733                input.push_str(&format!("{choice} "));
39734            }
39735            let source = directory.join(format!("decoded-input-{ordinal}.txt"));
39736            let destination = directory.join(format!("decoded-output-{ordinal}.txt"));
39737            std::fs::write(&source, input).unwrap();
39738            run(std::process::Command::new(executable)
39739                .arg("--decode")
39740                .arg(&source)
39741                .arg(&destination));
39742            let words: Vec<u32> = std::fs::read_to_string(&destination)
39743                .unwrap()
39744                .split_whitespace()
39745                .map(|word| word.parse().unwrap())
39746                .collect();
39747            assert_eq!(words.len(), 20);
39748            assert_eq!(
39749                words[8],
39750                u32::MAX,
39751                "computed target invented an original occurrence"
39752            );
39753            assert_eq!(
39754                words[19], 3,
39755                "actual decoder selected a different equal support occurrence"
39756            );
39757            let reconstruction: [u32; 10] = words[9..19].try_into().unwrap();
39758            let key = reconstructed_material_statement(&admission, None, &reconstruction).unwrap();
39759            let digest: Vec<u8> = words[..8]
39760                .iter()
39761                .flat_map(|word| word.to_le_bytes())
39762                .collect();
39763            assert_eq!(
39764                digest.as_slice(),
39765                key.identity().as_bytes(),
39766                "actual decode differs from canonical restore"
39767            );
39768            if ordinal == 0 {
39769                assert_eq!(
39770                    key.identity(),
39771                    admission.statement_key(0).unwrap().identity()
39772                );
39773            } else {
39774                assert_ne!(
39775                    key.identity(),
39776                    admission.statement_key(0).unwrap().identity()
39777                );
39778                assert_ne!(
39779                    key.identity(),
39780                    admission.statement_key(1).unwrap().identity()
39781                );
39782            }
39783            assert!(
39784                reconstructed_material_statement(&admission, Some(0), &reconstruction).is_err(),
39785                "derived reconstruction was accepted as an original occurrence"
39786            );
39787            std::fs::remove_file(source).unwrap();
39788            std::fs::remove_file(destination).unwrap();
39789        }
39790    }
39791
39792    #[test]
39793    fn task_scoring_rejects_signed_return_overflow() {
39794        let mut spec = task_spec([0, 1, 1], vec![0]);
39795        spec.scoring.correct_weight = u32::MAX;
39796        spec.scoring.improvement_weight = u32::MAX;
39797        assert!(spec.validate_records(&carry_records()).is_err());
39798    }
39799
39800    #[test]
39801    fn cold_task_binding_requires_admitted_statement_scope() {
39802        let spec = task_spec([0, 1, 1], vec![0]);
39803        spec.validate_records(&carry_records()).unwrap();
39804        for invalid in 0..4 {
39805            let mut records = carry_records();
39806            match invalid {
39807                0 => records.records[1].predicate = RelId(18),
39808                1 => records.records[1].predicate = RelId(999),
39809                2 => records.predicates[0].role = SemanticRecordRole::Qualifier,
39810                _ => records.supports[0].statement = 2,
39811            }
39812            assert!(spec.validate_records(&records).is_err(), "case {invalid}");
39813        }
39814        assert!(task_spec([0, 2, 2], vec![])
39815            .validate_records(&carry_records())
39816            .is_err());
39817        assert!(task_spec([0, 1, 1], vec![1])
39818            .validate_records(&carry_records())
39819            .is_err());
39820    }
39821}