Skip to main content

vyre_runtime/megakernel/
mixed_work.rs

1//! Runtime-owned mixed-work protocol for resident megakernel batches.
2//!
3//! This module is intentionally domain-neutral. Scan, graph, parser, and flow
4//! callers own their manifests and payload layouts; the runtime owns only the
5//! queue class, work-unit type, resident artifact id, output slab id, watchdog
6//! budget, and deterministic evidence contract needed to drain one resident
7//! batch without hidden host loops.
8
9/// Schema version for mixed-work protocol evidence.
10pub const MIXED_WORK_PROTOCOL_SCHEMA_VERSION: u32 = 1;
11
12const FNV_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
13const FNV_PRIME: u64 = 0x0000_0100_0000_01b3;
14
15/// Resident queue class used by the megakernel scheduler.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub enum MixedWorkQueueClass {
18    /// Byte, literal, regex, or token scan work.
19    Scan,
20    /// Frontier, CSR, motif, or reachability graph work.
21    Graph,
22    /// Lexer, parser, VAST, or changed-range parser work.
23    Parser,
24    /// Relation, dataflow, IFDS, or fixed-point flow work.
25    Flow,
26    /// Runtime control work such as bounded drain sentinels.
27    Control,
28}
29
30impl MixedWorkQueueClass {
31    /// Stable label used in evidence and diagnostics.
32    #[must_use]
33    pub const fn as_str(self) -> &'static str {
34        match self {
35            Self::Scan => "scan",
36            Self::Graph => "graph",
37            Self::Parser => "parser",
38            Self::Flow => "flow",
39            Self::Control => "control",
40        }
41    }
42
43    const fn tag(self) -> u64 {
44        match self {
45            Self::Scan => 1,
46            Self::Graph => 2,
47            Self::Parser => 3,
48            Self::Flow => 4,
49            Self::Control => 5,
50        }
51    }
52}
53
54/// Resident work-unit type selected inside a queue class.
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56pub enum MixedWorkUnitType {
57    /// Scan one byte chunk or literal/regex shard.
58    ScanChunk,
59    /// Verify scan candidates in a resident verifier fragment.
60    ScanVerifier,
61    /// Expand or compact a graph frontier.
62    GraphFrontier,
63    /// Compact graph output or frontier queues.
64    GraphCompaction,
65    /// Run one parser shard or lexer/tokenization shard.
66    ParserShard,
67    /// Apply one parser changed-range shard.
68    ParserChangedRange,
69    /// Apply a relation delta batch.
70    FlowRelationDelta,
71    /// Run one flow fixed-point step.
72    FlowFixpointStep,
73    /// Drain-control sentinel used to bound persistent execution.
74    DrainSentinel,
75}
76
77impl MixedWorkUnitType {
78    /// Stable label used in evidence and diagnostics.
79    #[must_use]
80    pub const fn as_str(self) -> &'static str {
81        match self {
82            Self::ScanChunk => "scan_chunk",
83            Self::ScanVerifier => "scan_verifier",
84            Self::GraphFrontier => "graph_frontier",
85            Self::GraphCompaction => "graph_compaction",
86            Self::ParserShard => "parser_shard",
87            Self::ParserChangedRange => "parser_changed_range",
88            Self::FlowRelationDelta => "flow_relation_delta",
89            Self::FlowFixpointStep => "flow_fixpoint_step",
90            Self::DrainSentinel => "drain_sentinel",
91        }
92    }
93
94    const fn tag(self) -> u64 {
95        match self {
96            Self::ScanChunk => 11,
97            Self::ScanVerifier => 12,
98            Self::GraphFrontier => 21,
99            Self::GraphCompaction => 22,
100            Self::ParserShard => 31,
101            Self::ParserChangedRange => 32,
102            Self::FlowRelationDelta => 41,
103            Self::FlowFixpointStep => 42,
104            Self::DrainSentinel => 51,
105        }
106    }
107}
108
109/// Opaque id for an artifact already resident in megakernel-owned buffers.
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub struct ResidentArtifactId(pub u32);
112
113impl ResidentArtifactId {
114    /// Return true when this id names a concrete resident artifact.
115    #[must_use]
116    pub const fn is_valid(self) -> bool {
117        self.0 != 0
118    }
119}
120
121/// Opaque id for a resident output slab owned by the runtime.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123pub struct OutputSlabId(pub u32);
124
125impl OutputSlabId {
126    /// Return true when this id names a concrete output slab.
127    #[must_use]
128    pub const fn is_valid(self) -> bool {
129        self.0 != 0
130    }
131}
132
133/// One resident mixed-work unit.
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
135pub struct MixedWorkUnit {
136    /// Stable sequence number used for deterministic drain and output evidence.
137    pub sequence: u64,
138    /// Scheduler queue class.
139    pub queue_class: MixedWorkQueueClass,
140    /// Work-unit kind inside the queue class.
141    pub unit_type: MixedWorkUnitType,
142    /// Resident artifact consumed by this work unit.
143    pub resident_artifact_id: ResidentArtifactId,
144    /// Output slab written by this work unit.
145    pub output_slab_id: OutputSlabId,
146    /// Per-unit watchdog budget in scheduler ticks.
147    pub watchdog_budget_ticks: u32,
148    /// Caller-owned payload digest. Runtime treats payload bytes as opaque.
149    pub payload_digest: u64,
150}
151
152impl MixedWorkUnit {
153    /// Construct one mixed-work unit.
154    #[must_use]
155    pub const fn new(
156        sequence: u64,
157        queue_class: MixedWorkQueueClass,
158        unit_type: MixedWorkUnitType,
159        resident_artifact_id: ResidentArtifactId,
160        output_slab_id: OutputSlabId,
161        watchdog_budget_ticks: u32,
162        payload_digest: u64,
163    ) -> Self {
164        Self {
165            sequence,
166            queue_class,
167            unit_type,
168            resident_artifact_id,
169            output_slab_id,
170            watchdog_budget_ticks,
171            payload_digest,
172        }
173    }
174}
175
176/// Borrowed resident mixed-work plan supplied to the runtime scheduler.
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178pub struct MixedWorkProtocolPlan<'a> {
179    /// Work units to drain in deterministic sequence order.
180    pub units: &'a [MixedWorkUnit],
181    /// Total watchdog budget for draining the plan.
182    pub drain_watchdog_budget_ticks: u64,
183}
184
185impl<'a> MixedWorkProtocolPlan<'a> {
186    /// Construct a borrowed mixed-work protocol plan.
187    #[must_use]
188    pub const fn new(units: &'a [MixedWorkUnit], drain_watchdog_budget_ticks: u64) -> Self {
189        Self {
190            units,
191            drain_watchdog_budget_ticks,
192        }
193    }
194}
195
196/// Evidence emitted after validating a mixed-work protocol plan.
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198pub struct MixedWorkProtocolEvidence {
199    /// Evidence schema version.
200    pub schema_version: u32,
201    /// Total work units.
202    pub unit_count: u32,
203    /// Scan queue units.
204    pub scan_units: u32,
205    /// Graph queue units.
206    pub graph_units: u32,
207    /// Parser queue units.
208    pub parser_units: u32,
209    /// Flow queue units.
210    pub flow_units: u32,
211    /// Runtime control queue units.
212    pub control_units: u32,
213    /// Sum of per-unit watchdog budgets.
214    pub total_watchdog_budget_ticks: u64,
215    /// Largest per-unit watchdog budget.
216    pub max_watchdog_budget_ticks: u32,
217    /// Drain budget supplied for the full resident batch.
218    pub drain_watchdog_budget_ticks: u64,
219    /// True when the sum of per-unit watchdog budgets is bounded by the drain budget.
220    pub bounded_drain: bool,
221    /// Hidden host-loop count. Valid mixed-work plans keep this at zero.
222    pub hidden_host_loop_count: u32,
223    /// Deterministic digest of queue class, unit type, ids, budgets, and payload digests.
224    pub deterministic_output_digest: u64,
225}
226
227impl MixedWorkProtocolEvidence {
228    /// Return true when scan, graph, parser, and flow classes are all present.
229    #[must_use]
230    pub const fn covers_scan_graph_parser_flow(self) -> bool {
231        self.scan_units != 0
232            && self.graph_units != 0
233            && self.parser_units != 0
234            && self.flow_units != 0
235    }
236
237    /// Return true when evidence is complete enough for release benches.
238    #[must_use]
239    pub const fn is_complete(self) -> bool {
240        self.schema_version == MIXED_WORK_PROTOCOL_SCHEMA_VERSION
241            && self.unit_count != 0
242            && self.bounded_drain
243            && self.hidden_host_loop_count == 0
244            && self.deterministic_output_digest != 0
245    }
246}
247
248/// Mixed-work protocol validation error.
249#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
250#[non_exhaustive]
251pub enum MixedWorkProtocolError {
252    /// The plan has no resident work.
253    #[error(
254        "mixed-work plan is empty. Fix: publish at least one resident work unit before scheduling."
255    )]
256    EmptyPlan,
257    /// The total drain budget is zero.
258    #[error(
259        "mixed-work drain watchdog budget is zero. Fix: provide a positive resident drain budget."
260    )]
261    ZeroDrainWatchdogBudget,
262    /// A unit has no watchdog budget.
263    #[error("mixed-work unit {sequence} has zero watchdog budget. Fix: assign a positive per-unit watchdog budget.")]
264    ZeroUnitWatchdogBudget {
265        /// Sequence number of the invalid unit.
266        sequence: u64,
267    },
268    /// A unit references no resident artifact.
269    #[error("mixed-work unit {sequence} has resident artifact id 0. Fix: publish a resident artifact before queueing work.")]
270    ZeroResidentArtifactId {
271        /// Sequence number of the invalid unit.
272        sequence: u64,
273    },
274    /// A unit references no output slab.
275    #[error("mixed-work unit {sequence} has output slab id 0. Fix: allocate a resident output slab before queueing work.")]
276    ZeroOutputSlabId {
277        /// Sequence number of the invalid unit.
278        sequence: u64,
279    },
280    /// Queue class and unit type do not match.
281    #[error(
282        "mixed-work unit {sequence} routes {unit_type} through {queue_class}. Fix: use a unit type owned by the queue class."
283    )]
284    QueueClassMismatch {
285        /// Sequence number of the invalid unit.
286        sequence: u64,
287        /// Queue class label.
288        queue_class: &'static str,
289        /// Unit type label.
290        unit_type: &'static str,
291    },
292    /// Unit count cannot fit the evidence ABI.
293    #[error(
294        "mixed-work unit count {unit_count} overflows u32 evidence. Fix: shard the resident batch."
295    )]
296    UnitCountOverflow {
297        /// Unit count that exceeded the evidence ABI.
298        unit_count: usize,
299    },
300    /// Class-specific count cannot fit the evidence ABI.
301    #[error(
302        "mixed-work {queue_class} unit count overflowed u32 evidence. Fix: shard that queue class."
303    )]
304    ClassCountOverflow {
305        /// Queue class whose count overflowed.
306        queue_class: &'static str,
307    },
308    /// Watchdog sum overflowed the evidence ABI.
309    #[error("mixed-work watchdog budget sum overflowed u64. Fix: shard the resident batch.")]
310    WatchdogBudgetOverflow,
311    /// The plan cannot drain inside the supplied watchdog budget.
312    #[error(
313        "mixed-work watchdog budget {total_watchdog_budget_ticks} exceeds drain budget {drain_watchdog_budget_ticks}. Fix: increase the drain budget or shard the resident batch."
314    )]
315    WatchdogBudgetExceeded {
316        /// Sum of per-unit watchdog budgets.
317        total_watchdog_budget_ticks: u64,
318        /// Drain budget supplied by the caller.
319        drain_watchdog_budget_ticks: u64,
320    },
321}
322
323/// Validate a mixed-work protocol plan and return deterministic drain evidence.
324///
325/// # Errors
326///
327/// Returns [`MixedWorkProtocolError`] when the plan cannot be drained by the
328/// resident scheduler without invalid ids, class mismatches, hidden host loops,
329/// or an unbounded watchdog budget.
330pub fn mixed_work_protocol_evidence(
331    plan: &MixedWorkProtocolPlan<'_>,
332) -> Result<MixedWorkProtocolEvidence, MixedWorkProtocolError> {
333    validate_mixed_work_protocol(plan)
334}
335
336/// Validate a mixed-work protocol plan and return deterministic drain evidence.
337///
338/// # Errors
339///
340/// Returns [`MixedWorkProtocolError`] when any work unit is malformed or the
341/// plan exceeds its drain watchdog budget.
342pub fn validate_mixed_work_protocol(
343    plan: &MixedWorkProtocolPlan<'_>,
344) -> Result<MixedWorkProtocolEvidence, MixedWorkProtocolError> {
345    if plan.units.is_empty() {
346        return Err(MixedWorkProtocolError::EmptyPlan);
347    }
348    if plan.drain_watchdog_budget_ticks == 0 {
349        return Err(MixedWorkProtocolError::ZeroDrainWatchdogBudget);
350    }
351    if plan.units.len() > u32::MAX as usize {
352        return Err(MixedWorkProtocolError::UnitCountOverflow {
353            unit_count: plan.units.len(),
354        });
355    }
356
357    let mut counts = [0_u32; 5];
358    let mut total_watchdog_budget_ticks = 0_u64;
359    let mut max_watchdog_budget_ticks = 0_u32;
360    let mut digest = FNV_OFFSET;
361
362    for unit in plan.units {
363        validate_unit(*unit)?;
364        bump_class_count(&mut counts, unit.queue_class)?;
365        total_watchdog_budget_ticks = total_watchdog_budget_ticks
366            .checked_add(u64::from(unit.watchdog_budget_ticks))
367            .ok_or(MixedWorkProtocolError::WatchdogBudgetOverflow)?;
368        max_watchdog_budget_ticks = max_watchdog_budget_ticks.max(unit.watchdog_budget_ticks);
369        digest = mix_unit_digest(digest, *unit);
370    }
371
372    if total_watchdog_budget_ticks > plan.drain_watchdog_budget_ticks {
373        return Err(MixedWorkProtocolError::WatchdogBudgetExceeded {
374            total_watchdog_budget_ticks,
375            drain_watchdog_budget_ticks: plan.drain_watchdog_budget_ticks,
376        });
377    }
378
379    Ok(MixedWorkProtocolEvidence {
380        schema_version: MIXED_WORK_PROTOCOL_SCHEMA_VERSION,
381        unit_count: plan.units.len() as u32,
382        scan_units: counts[0],
383        graph_units: counts[1],
384        parser_units: counts[2],
385        flow_units: counts[3],
386        control_units: counts[4],
387        total_watchdog_budget_ticks,
388        max_watchdog_budget_ticks,
389        drain_watchdog_budget_ticks: plan.drain_watchdog_budget_ticks,
390        bounded_drain: true,
391        hidden_host_loop_count: 0,
392        deterministic_output_digest: digest,
393    })
394}
395
396fn validate_unit(unit: MixedWorkUnit) -> Result<(), MixedWorkProtocolError> {
397    if unit.watchdog_budget_ticks == 0 {
398        return Err(MixedWorkProtocolError::ZeroUnitWatchdogBudget {
399            sequence: unit.sequence,
400        });
401    }
402    if !unit.resident_artifact_id.is_valid() {
403        return Err(MixedWorkProtocolError::ZeroResidentArtifactId {
404            sequence: unit.sequence,
405        });
406    }
407    if !unit.output_slab_id.is_valid() {
408        return Err(MixedWorkProtocolError::ZeroOutputSlabId {
409            sequence: unit.sequence,
410        });
411    }
412    if !unit_type_matches_queue(unit.queue_class, unit.unit_type) {
413        return Err(MixedWorkProtocolError::QueueClassMismatch {
414            sequence: unit.sequence,
415            queue_class: unit.queue_class.as_str(),
416            unit_type: unit.unit_type.as_str(),
417        });
418    }
419    Ok(())
420}
421
422const fn unit_type_matches_queue(
423    queue_class: MixedWorkQueueClass,
424    unit_type: MixedWorkUnitType,
425) -> bool {
426    matches!(
427        (queue_class, unit_type),
428        (MixedWorkQueueClass::Scan, MixedWorkUnitType::ScanChunk)
429            | (MixedWorkQueueClass::Scan, MixedWorkUnitType::ScanVerifier)
430            | (MixedWorkQueueClass::Graph, MixedWorkUnitType::GraphFrontier)
431            | (
432                MixedWorkQueueClass::Graph,
433                MixedWorkUnitType::GraphCompaction
434            )
435            | (MixedWorkQueueClass::Parser, MixedWorkUnitType::ParserShard)
436            | (
437                MixedWorkQueueClass::Parser,
438                MixedWorkUnitType::ParserChangedRange
439            )
440            | (
441                MixedWorkQueueClass::Flow,
442                MixedWorkUnitType::FlowRelationDelta
443            )
444            | (
445                MixedWorkQueueClass::Flow,
446                MixedWorkUnitType::FlowFixpointStep
447            )
448            | (
449                MixedWorkQueueClass::Control,
450                MixedWorkUnitType::DrainSentinel
451            )
452    )
453}
454
455fn bump_class_count(
456    counts: &mut [u32; 5],
457    queue_class: MixedWorkQueueClass,
458) -> Result<(), MixedWorkProtocolError> {
459    let index = match queue_class {
460        MixedWorkQueueClass::Scan => 0,
461        MixedWorkQueueClass::Graph => 1,
462        MixedWorkQueueClass::Parser => 2,
463        MixedWorkQueueClass::Flow => 3,
464        MixedWorkQueueClass::Control => 4,
465    };
466    counts[index] =
467        counts[index]
468            .checked_add(1)
469            .ok_or(MixedWorkProtocolError::ClassCountOverflow {
470                queue_class: queue_class.as_str(),
471            })?;
472    Ok(())
473}
474
475fn mix_unit_digest(mut digest: u64, unit: MixedWorkUnit) -> u64 {
476    digest = fnv_mix(digest, unit.sequence);
477    digest = fnv_mix(digest, unit.queue_class.tag());
478    digest = fnv_mix(digest, unit.unit_type.tag());
479    digest = fnv_mix(digest, u64::from(unit.resident_artifact_id.0));
480    digest = fnv_mix(digest, u64::from(unit.output_slab_id.0));
481    digest = fnv_mix(digest, u64::from(unit.watchdog_budget_ticks));
482    fnv_mix(digest, unit.payload_digest)
483}
484
485fn fnv_mix(mut digest: u64, value: u64) -> u64 {
486    for byte in value.to_le_bytes() {
487        digest ^= u64::from(byte);
488        digest = digest.wrapping_mul(FNV_PRIME);
489    }
490    digest
491}
492
493#[cfg(test)]
494mod tests {
495    use super::{
496        mixed_work_protocol_evidence, validate_mixed_work_protocol, MixedWorkProtocolError,
497        MixedWorkProtocolPlan, MixedWorkQueueClass, MixedWorkUnit, MixedWorkUnitType, OutputSlabId,
498        ResidentArtifactId, MIXED_WORK_PROTOCOL_SCHEMA_VERSION,
499    };
500
501    fn unit(
502        sequence: u64,
503        queue_class: MixedWorkQueueClass,
504        unit_type: MixedWorkUnitType,
505    ) -> MixedWorkUnit {
506        MixedWorkUnit::new(
507            sequence,
508            queue_class,
509            unit_type,
510            ResidentArtifactId(100 + sequence as u32),
511            OutputSlabId(200 + sequence as u32),
512            10,
513            0xfeed_0000 + sequence,
514        )
515    }
516
517    #[test]
518    fn mixed_scan_graph_parser_flow_work_emits_deterministic_bounded_drain_evidence() {
519        let units = [
520            unit(1, MixedWorkQueueClass::Scan, MixedWorkUnitType::ScanChunk),
521            unit(
522                2,
523                MixedWorkQueueClass::Graph,
524                MixedWorkUnitType::GraphFrontier,
525            ),
526            unit(
527                3,
528                MixedWorkQueueClass::Parser,
529                MixedWorkUnitType::ParserShard,
530            ),
531            unit(
532                4,
533                MixedWorkQueueClass::Flow,
534                MixedWorkUnitType::FlowRelationDelta,
535            ),
536            unit(
537                5,
538                MixedWorkQueueClass::Control,
539                MixedWorkUnitType::DrainSentinel,
540            ),
541        ];
542        let plan = MixedWorkProtocolPlan::new(&units, 64);
543
544        let first = mixed_work_protocol_evidence(&plan)
545            .expect("Fix: valid mixed-work plan should emit evidence");
546        let second = validate_mixed_work_protocol(&plan)
547            .expect("Fix: valid mixed-work plan should emit stable evidence");
548
549        assert_eq!(first, second);
550        assert_eq!(first.schema_version, MIXED_WORK_PROTOCOL_SCHEMA_VERSION);
551        assert!(first.is_complete());
552        assert!(first.covers_scan_graph_parser_flow());
553        assert!(first.bounded_drain);
554        assert_eq!(first.hidden_host_loop_count, 0);
555        assert_eq!(first.unit_count, 5);
556        assert_eq!(first.total_watchdog_budget_ticks, 50);
557        assert_eq!(first.max_watchdog_budget_ticks, 10);
558        assert_ne!(first.deterministic_output_digest, 0);
559    }
560
561    #[test]
562    fn zero_watchdog_budget_is_rejected() {
563        let units = [MixedWorkUnit::new(
564            7,
565            MixedWorkQueueClass::Scan,
566            MixedWorkUnitType::ScanChunk,
567            ResidentArtifactId(1),
568            OutputSlabId(1),
569            0,
570            9,
571        )];
572        let plan = MixedWorkProtocolPlan::new(&units, 1);
573
574        assert!(matches!(
575            validate_mixed_work_protocol(&plan),
576            Err(MixedWorkProtocolError::ZeroUnitWatchdogBudget { sequence: 7 })
577        ));
578    }
579
580    #[test]
581    fn class_unit_mismatch_is_rejected() {
582        let units = [MixedWorkUnit::new(
583            9,
584            MixedWorkQueueClass::Parser,
585            MixedWorkUnitType::FlowFixpointStep,
586            ResidentArtifactId(1),
587            OutputSlabId(1),
588            1,
589            9,
590        )];
591        let plan = MixedWorkProtocolPlan::new(&units, 1);
592
593        assert!(matches!(
594            validate_mixed_work_protocol(&plan),
595            Err(MixedWorkProtocolError::QueueClassMismatch {
596                sequence: 9,
597                queue_class: "parser",
598                unit_type: "flow_fixpoint_step"
599            })
600        ));
601    }
602
603    #[test]
604    fn drain_budget_must_bound_all_units() {
605        let units = [
606            unit(1, MixedWorkQueueClass::Scan, MixedWorkUnitType::ScanChunk),
607            unit(
608                2,
609                MixedWorkQueueClass::Flow,
610                MixedWorkUnitType::FlowRelationDelta,
611            ),
612        ];
613        let plan = MixedWorkProtocolPlan::new(&units, 19);
614
615        assert!(matches!(
616            validate_mixed_work_protocol(&plan),
617            Err(MixedWorkProtocolError::WatchdogBudgetExceeded {
618                total_watchdog_budget_ticks: 20,
619                drain_watchdog_budget_ticks: 19
620            })
621        ));
622    }
623
624    #[test]
625    fn resident_artifact_and_output_slab_ids_are_required() {
626        let bad_artifact = [MixedWorkUnit::new(
627            1,
628            MixedWorkQueueClass::Scan,
629            MixedWorkUnitType::ScanChunk,
630            ResidentArtifactId(0),
631            OutputSlabId(1),
632            1,
633            1,
634        )];
635        assert!(matches!(
636            validate_mixed_work_protocol(&MixedWorkProtocolPlan::new(&bad_artifact, 1)),
637            Err(MixedWorkProtocolError::ZeroResidentArtifactId { sequence: 1 })
638        ));
639
640        let bad_slab = [MixedWorkUnit::new(
641            2,
642            MixedWorkQueueClass::Scan,
643            MixedWorkUnitType::ScanChunk,
644            ResidentArtifactId(1),
645            OutputSlabId(0),
646            1,
647            1,
648        )];
649        assert!(matches!(
650            validate_mixed_work_protocol(&MixedWorkProtocolPlan::new(&bad_slab, 1)),
651            Err(MixedWorkProtocolError::ZeroOutputSlabId { sequence: 2 })
652        ));
653    }
654}