infotheory/spec/document/types.rs
1//! Canonical top-level specification document schema types.
2
3use crate::aixi::common::{ActionAlphabet, MctsStrategy, ObservationKeyMode};
4use crate::api::{BitStreamSemantics, CompressionBackend, RateBackend};
5use crate::spec::core::{
6 AssetRef, CanonicalBytes, CompiledCompressionBackend, CompiledRateBackend,
7 ValidatedCompressionBackend, ValidatedRateBackend,
8};
9use std::path::PathBuf;
10use std::sync::Arc;
11
12/// Stable identifier for an external asset binding.
13pub type AssetId = String;
14
15/// Filesystem binding for a named external asset referenced by a spec document.
16#[derive(Clone, Debug, Eq, PartialEq)]
17#[non_exhaustive]
18pub struct AssetBinding {
19 /// Stable asset identifier used inside canonical specs.
20 pub id: AssetId,
21 /// Filesystem path used to resolve the asset at runtime.
22 pub path: String,
23}
24
25/// Resolved runtime asset binding derived from a canonical asset identifier.
26#[derive(Clone, Debug, Eq, PartialEq)]
27#[non_exhaustive]
28pub struct ResolvedAssetBinding {
29 /// Stable asset identifier used inside canonical specs.
30 pub id: AssetId,
31 /// Resolved asset handle in the current compilation environment.
32 pub asset: AssetRef,
33}
34
35/// Built-in non-VM environment choices available to planner runs.
36#[derive(Clone, Copy, Debug, Eq, PartialEq)]
37#[non_exhaustive]
38pub enum BuiltinEnvironmentSpec {
39 /// Internal planner environment bridge used by tuner controller execution.
40 TunerBridge,
41 /// GameEngine biased coin-flip environment.
42 CoinFlip,
43 /// GameEngine biased rock-paper-scissor environment.
44 BiasedRockPaperScissor,
45 /// GameEngine Kuhn poker environment.
46 KuhnPoker,
47 /// GameEngine extended tiger environment.
48 ExtendedTiger,
49 /// GameEngine tic-tac-toe environment.
50 TicTacToe,
51 /// GameEngine blackjack environment.
52 Blackjack,
53 /// GameEngine platformer environment.
54 Platformer,
55}
56
57/// Shared-memory persistence policy for Nyx VM environments.
58#[derive(Clone, Copy, Debug, Eq, PartialEq)]
59#[non_exhaustive]
60pub enum SharedMemoryPolicySpec {
61 /// Preserve the region across resets.
62 Preserve,
63 /// Reset from the snapshot baseline each iteration.
64 Snapshot,
65}
66
67/// Reward shaping configuration for VM environments.
68///
69/// Algorithmic configuration for the entropy estimator (such as ROSA's
70/// `max_order`) lives inside the active rate backend's variant; the shaping
71/// spec only carries shaping-policy parameters.
72#[derive(Clone, Debug, PartialEq)]
73#[non_exhaustive]
74pub enum VmRewardShapingSpec {
75 /// Entropy reduction relative to a baseline asset.
76 EntropyReduction {
77 /// Asset identifier providing baseline bytes.
78 baseline_asset: AssetId,
79 /// Linear scale applied to the shaping reward.
80 scale: f64,
81 /// Optional bonus applied on crash exits.
82 crash_bonus: Option<i64>,
83 /// Optional bonus applied on timeout exits.
84 timeout_bonus: Option<i64>,
85 },
86 /// Trace entropy shaping using online trace bytes.
87 TraceEntropy {
88 /// Linear scale applied to the shaping reward.
89 scale: f64,
90 /// Whether to normalize by trace length.
91 normalize: bool,
92 },
93}
94
95/// Reward policy for canonical VM environment specs.
96#[derive(Clone, Debug, Eq, PartialEq)]
97#[non_exhaustive]
98pub enum VmRewardPolicySpec {
99 /// Parse reward directly from the guest protocol.
100 FromGuest,
101 /// Pattern-based reward shaping against guest output.
102 Pattern {
103 /// Pattern searched in guest output.
104 pattern: String,
105 /// Reward applied when the pattern does not match.
106 base_reward: i64,
107 /// Additional reward applied on match.
108 bonus_reward: i64,
109 },
110}
111
112/// Optional information-theoretic action filtering for VM runs.
113///
114/// Algorithmic configuration for the entropy estimator (such as ROSA's
115/// `max_order`) lives inside the active rate backend's variant; the filter
116/// spec only carries filter-policy thresholds.
117#[derive(Clone, Debug, PartialEq)]
118#[non_exhaustive]
119pub struct VmActionFilterSpec {
120 /// Minimum entropy threshold.
121 pub min_entropy: Option<f64>,
122 /// Maximum entropy threshold.
123 pub max_entropy: Option<f64>,
124 /// Minimum intrinsic dependence threshold.
125 pub min_intrinsic_dependence: Option<f64>,
126 /// Minimum novelty threshold.
127 pub min_novelty: Option<f64>,
128 /// Optional prior asset used for novelty scoring.
129 pub novelty_prior_asset: Option<AssetId>,
130 /// Reward assigned when an action is rejected.
131 pub reject_reward: Option<i64>,
132}
133
134/// Optional VM trace collection settings.
135#[derive(Clone, Debug, Eq, PartialEq)]
136#[non_exhaustive]
137pub struct VmTraceSpec {
138 /// Shared-memory region name carrying trace bytes.
139 pub shared_region_name: Option<String>,
140 /// Maximum trace bytes collected per step.
141 pub max_bytes: usize,
142 /// Whether the trace model resets on episode boundaries.
143 pub reset_on_episode: bool,
144}
145
146/// Canonical observation derivation modes for VM environments.
147#[derive(Clone, Copy, Debug, Eq, PartialEq)]
148#[non_exhaustive]
149pub enum VmObservationPolicySpec {
150 /// Parse observations from the guest protocol.
151 FromGuest,
152 /// Hash guest output into the observation stream.
153 OutputHash,
154 /// Use raw guest output bytes directly.
155 RawOutput,
156 /// Read observations from shared memory.
157 SharedMemory,
158}
159
160/// Canonical normalization modes for VM observation streams.
161#[derive(Clone, Copy, Debug, Eq, PartialEq)]
162#[non_exhaustive]
163pub enum VmObservationStreamModeSpec {
164 /// Pad short streams and truncate long streams.
165 PadTruncate,
166 /// Only pad short streams.
167 Pad,
168 /// Only truncate long streams.
169 Truncate,
170}
171
172/// Canonical payload encodings for VM action and protocol payloads.
173#[derive(Clone, Copy, Debug, Eq, PartialEq)]
174#[non_exhaustive]
175pub enum VmPayloadEncodingSpec {
176 /// Interpret payload strings as UTF-8 text.
177 Utf8,
178 /// Interpret payload strings as hexadecimal bytes.
179 Hex,
180}
181
182/// Canonical fuzz mutator choices for VM action generation.
183#[derive(Clone, Copy, Debug, Eq, PartialEq)]
184#[non_exhaustive]
185pub enum VmFuzzMutatorSpec {
186 /// Flip one random bit.
187 FlipBit,
188 /// Flip one random byte.
189 FlipByte,
190 /// Insert one random byte.
191 InsertByte,
192 /// Delete one random byte.
193 DeleteByte,
194 /// Splice in bytes from another seed.
195 SpliceSeed,
196 /// Reset to a seed input.
197 ResetSeed,
198 /// Apply a short random mutation sequence.
199 Havoc,
200}
201
202/// Canonical runtime action source for VM environments.
203#[derive(Clone, Debug, Eq, PartialEq)]
204#[non_exhaustive]
205pub enum VmRuntimeActionSourceSpec {
206 /// Inline literal action payloads.
207 Literal {
208 /// Human-readable action names.
209 names: Vec<Option<String>>,
210 /// Action payloads encoded with the selected payload encoding.
211 payloads: Vec<String>,
212 /// Payload encoding applied to all literals.
213 encoding: VmPayloadEncodingSpec,
214 },
215 /// Mutation-based fuzzing configuration.
216 Fuzz {
217 /// Seed inputs encoded with the selected payload encoding.
218 seeds: Vec<String>,
219 /// Payload encoding applied to seeds and dictionary entries.
220 encoding: VmPayloadEncodingSpec,
221 /// Enabled mutators by canonical name.
222 mutators: Vec<VmFuzzMutatorSpec>,
223 /// Minimum generated payload length.
224 min_len: usize,
225 /// Maximum generated payload length.
226 max_len: usize,
227 /// Optional dictionary entries.
228 dictionary: Vec<String>,
229 /// Deterministic RNG seed for mutation sampling.
230 rng_seed: u64,
231 },
232}
233
234/// Canonical Nyx/Firecracker environment configuration.
235#[derive(Clone)]
236#[non_exhaustive]
237pub struct VmEnvironmentSpec {
238 /// Asset identifier pointing at the Firecracker JSON config.
239 pub firecracker_config_asset: AssetId,
240 /// VM instance identifier.
241 pub instance_id: String,
242 /// Shared-memory region name used for guest communication.
243 pub shared_region_name: String,
244 /// Shared-memory region size in bytes.
245 pub shared_region_size: usize,
246 /// Snapshot-vs-preserve policy for shared memory.
247 pub shared_memory_policy: SharedMemoryPolicySpec,
248 /// Per-step timeout in milliseconds.
249 pub step_timeout_ms: u64,
250 /// Initial boot timeout in milliseconds.
251 pub boot_timeout_ms: u64,
252 /// Episode length in steps.
253 pub episode_steps: usize,
254 /// Per-step cost subtracted from rewards.
255 pub step_cost: i64,
256 /// Observation derivation mode.
257 pub observation_policy: VmObservationPolicySpec,
258 /// Observation bit width.
259 pub observation_bits: usize,
260 /// Observation stream length.
261 pub observation_stream_len: usize,
262 /// Observation stream normalization mode.
263 pub observation_stream_mode: VmObservationStreamModeSpec,
264 /// Padding byte for short observation streams.
265 pub observation_pad_byte: u8,
266 /// Reward bit width.
267 pub reward_bits: usize,
268 /// Reward policy.
269 pub reward_policy: VmRewardPolicySpec,
270 /// Optional reward shaping policy.
271 pub reward_shaping: Option<VmRewardShapingSpec>,
272 /// Runtime action source.
273 pub action_source: VmRuntimeActionSourceSpec,
274 /// Optional information-theoretic filter.
275 pub action_filter: Option<VmActionFilterSpec>,
276 /// Protocol action prefix.
277 pub action_prefix: String,
278 /// Protocol action suffix.
279 pub action_suffix: String,
280 /// Protocol observation prefix.
281 pub obs_prefix: String,
282 /// Protocol reward prefix.
283 pub rew_prefix: String,
284 /// Protocol done prefix.
285 pub done_prefix: String,
286 /// Protocol data prefix.
287 pub data_prefix: String,
288 /// Payload encoding label (`utf8` or `hex`).
289 pub wire_encoding: VmPayloadEncodingSpec,
290 /// Rate backend used for entropy/statistics estimation.
291 pub stats_backend: RateBackend,
292 /// Optional trace configuration.
293 pub trace: Option<VmTraceSpec>,
294 /// Whether to enable verbose VM diagnostics.
295 pub debug_mode: bool,
296 /// Optional crash log path for VM exits.
297 pub crash_log: Option<String>,
298}
299
300/// Canonical planner-visible environment specification.
301#[derive(Clone)]
302#[non_exhaustive]
303pub enum EnvironmentSpec {
304 /// Built-in Rust environment.
305 Builtin {
306 /// Built-in environment kind.
307 builtin: BuiltinEnvironmentSpec,
308 },
309 /// Nyx/Firecracker VM environment.
310 #[cfg(feature = "vm")]
311 NyxVm(VmEnvironmentSpec),
312}
313
314/// Planner observation/reward/action interface contract.
315#[derive(Clone, Debug, PartialEq)]
316#[non_exhaustive]
317pub struct PlannerInterfaceSpec {
318 /// Observation bit width.
319 pub observation_bits: usize,
320 /// Observation stream length.
321 pub observation_stream_len: usize,
322 /// Observation key projection used by MC-AIXI.
323 pub observation_key_mode: ObservationKeyMode,
324 /// Reward bit width.
325 pub reward_bits: usize,
326 /// Action alphabet cardinality.
327 pub agent_actions: ActionAlphabet,
328}
329
330/// Canonical tuning interface contract for planner-visible I/O shape.
331///
332/// Unlike [`PlannerInterfaceSpec`], this tune-document interface is limited to
333/// candidate-facing semantics and intentionally excludes reward encoding
334/// bounds that belong to executor/runtime policy.
335#[cfg(feature = "tuner")]
336#[derive(Clone, Debug, PartialEq)]
337#[non_exhaustive]
338pub struct TunePlannerInterfaceSpec {
339 /// Observation bit width.
340 pub observation_bits: usize,
341 /// Observation stream length.
342 pub observation_stream_len: usize,
343 /// Observation key projection used by MC-AIXI.
344 pub observation_key_mode: ObservationKeyMode,
345 /// Reward bit width.
346 pub reward_bits: usize,
347 /// Action alphabet cardinality.
348 pub agent_actions: ActionAlphabet,
349}
350
351/// MC-AIXI controller configuration using a unified rate-backend predictor.
352#[derive(Clone)]
353#[non_exhaustive]
354pub struct McAixiControllerSpec {
355 /// Predictive backend used by the planner model.
356 pub predictor: RateBackend,
357 /// Bit-stream semantics used to adapt the predictor to AIXI symbols.
358 pub bit_stream_semantics: BitStreamSemantics,
359 /// Planning horizon.
360 pub agent_horizon: usize,
361 /// Number of simulations per planning step.
362 pub num_simulations: usize,
363 /// Explicit MCTS strategy used by the planner.
364 pub mcts_strategy: MctsStrategy,
365 /// UCT exploration constant.
366 pub exploration_exploitation_ratio: f64,
367 /// Reward discount factor.
368 pub discount_gamma: f64,
369}
370
371/// Discounted AIQI controller configuration.
372#[derive(Clone)]
373#[non_exhaustive]
374pub struct AiqiDiscountedControllerSpec {
375 /// Predictive backend used by the return model.
376 pub predictor: RateBackend,
377 /// Bit-stream semantics used to adapt the predictor to AIQI symbols.
378 pub bit_stream_semantics: BitStreamSemantics,
379 /// Discount factor used for return construction.
380 pub discount_gamma: f64,
381 /// Return horizon.
382 pub return_horizon: usize,
383 /// Number of discrete return bins.
384 pub return_bins: usize,
385 /// Label augmentation period.
386 pub augmentation_period: usize,
387 /// Optional bounded-history retention hint.
388 pub history_prune_keep_steps: Option<usize>,
389 /// Baseline exploration probability.
390 pub baseline_exploration: f64,
391}
392
393/// Warm-start exact-\u{1d4a5}_H controller configuration.
394#[cfg(feature = "aixi")]
395#[derive(Clone)]
396#[non_exhaustive]
397pub struct WarmStartExactJhControllerSpec {
398 /// Predictive backend used by the return model.
399 pub predictor: RateBackend,
400 /// Bit-stream semantics used to adapt the predictor to warm-start symbols.
401 pub bit_stream_semantics: BitStreamSemantics,
402 /// Return horizon in planner steps.
403 pub return_horizon: usize,
404 /// Exact return-label alphabet size.
405 ///
406 /// Valid canonical warm-start specs use `return_horizon * max_reward + 1`;
407 /// slack labels are rejected because they do not represent reachable exact
408 /// returns.
409 pub return_bins: usize,
410 /// Delayed-label phase period.
411 pub label_phase_period: usize,
412 /// Asset identifier for the warm-start teacher dataset.
413 pub teacher_dataset_asset: AssetId,
414 /// Canonical direct-evaluator budget marker.
415 ///
416 /// Warm-start exact-\(J_H\) performs deterministic full return-law
417 /// evaluation, not MCTS-style simulation. Valid canonical specs use `1`.
418 pub planner_simulations_per_step: usize,
419}
420
421/// Canonical planner controller selection.
422#[derive(Clone)]
423#[non_exhaustive]
424pub enum ControllerSpec {
425 /// Monte Carlo AIXI.
426 McAixi(McAixiControllerSpec),
427 /// Discounted AIQI.
428 AiqiDiscounted(AiqiDiscountedControllerSpec),
429 /// Warm-start exact-\u{1d4a5}_H AIQI-style controller.
430 #[cfg(feature = "aixi")]
431 AiqiWarmstartExactJh(WarmStartExactJhControllerSpec),
432}
433
434/// Operational planner-run controls that do not change predictor semantics.
435#[derive(Clone, Debug, PartialEq)]
436#[non_exhaustive]
437pub struct PlannerRuntimeSpec {
438 /// Seed used for planner/environment stochasticity.
439 ///
440 /// `None` canonicalizes to `Some(0)` during validation/compilation.
441 pub random_seed: Option<u64>,
442 /// Number of learning cycles.
443 pub learn_cycles: Option<usize>,
444 /// Number of evaluation cycles.
445 pub eval_cycles: Option<usize>,
446 /// Default cycle count when learn/eval are omitted.
447 pub terminate_lifetime: usize,
448 /// Logging interval in steps.
449 pub log_every: usize,
450 /// Whether to print throughput diagnostics.
451 pub perf: bool,
452 /// Whether to run VM perf-only mode.
453 pub vm_perf_only: bool,
454 /// Extra epsilon exploration used during execution.
455 pub explore_epsilon: f64,
456 /// Exponential decay for extra exploration.
457 pub explore_gamma: f64,
458}
459
460/// Canonical planner-run specification.
461#[derive(Clone)]
462#[non_exhaustive]
463pub struct PlannerRunSpec {
464 /// External asset bindings referenced by this run.
465 pub assets: Vec<AssetBinding>,
466 /// Planner-facing environment.
467 pub environment: EnvironmentSpec,
468 /// Planner observation/reward/action contract.
469 pub interface: PlannerInterfaceSpec,
470 /// Controller configuration.
471 pub controller: ControllerSpec,
472 /// Operational run controls.
473 pub runtime: PlannerRuntimeSpec,
474}
475
476/// Tuning controller kind specified by the formal tuner document.
477#[cfg(feature = "tuner")]
478#[derive(Clone, Copy, Debug, Eq, PartialEq)]
479#[non_exhaustive]
480pub enum TuneControllerKind {
481 /// Annealed hill climbing.
482 AnnealedHillClimbing,
483 /// MC-AIXI(FAC-CTW).
484 McAixiFacCtw,
485 /// Discounted AIQI.
486 AiqiDiscounted,
487 /// Warm-start exact-\u{1d4a5}_H controller.
488 #[cfg(feature = "aixi")]
489 AiqiWarmstartExactJh,
490}
491
492/// Annealed hill-climbing controller settings for tuning.
493#[cfg(feature = "tuner")]
494#[derive(Clone, Debug, Eq, PartialEq)]
495#[non_exhaustive]
496pub struct AnnealedHillClimbingTuneControllerSpec {
497 /// Maximum mutation radius applied to a candidate step.
498 pub max_mutation_radius: usize,
499}
500
501/// MC-AIXI(FAC-CTW) controller settings for tuning.
502#[cfg(feature = "tuner")]
503#[derive(Clone, Debug, PartialEq)]
504#[non_exhaustive]
505pub struct McAixiFacCtwTuneControllerSpec {
506 /// Planner/environment observation/reward/action contract.
507 pub interface: TunePlannerInterfaceSpec,
508 /// Simulation budget per planner step.
509 pub planner_simulations_per_step: usize,
510}
511
512/// Discounted AIQI controller settings for tuning.
513#[cfg(feature = "tuner")]
514#[derive(Clone, Debug, PartialEq)]
515#[non_exhaustive]
516pub struct AiqiDiscountedTuneControllerSpec {
517 /// Planner/environment observation/reward/action contract.
518 pub interface: TunePlannerInterfaceSpec,
519 /// Simulation budget per planner step.
520 pub planner_simulations_per_step: usize,
521 /// Return horizon.
522 pub return_horizon: usize,
523 /// Number of return bins.
524 pub return_bins: usize,
525 /// Discount factor used to construct returns.
526 pub discount_factor: f64,
527 /// Minimum clipped improvement value.
528 pub min_improvement: f64,
529 /// Maximum clipped improvement value.
530 pub max_improvement: f64,
531}
532
533/// Warm-start exact-J_H controller settings for tuning.
534#[cfg(feature = "tuner")]
535#[derive(Clone, Debug, PartialEq)]
536#[non_exhaustive]
537pub struct WarmStartExactJhTuneControllerSpec {
538 /// Planner/environment observation/reward/action contract.
539 pub interface: TunePlannerInterfaceSpec,
540 /// Canonical direct-evaluator budget marker.
541 ///
542 /// Warm-start exact-\(J_H\) performs deterministic full return-law
543 /// evaluation, not MCTS-style simulation. Valid canonical specs use `1`.
544 pub planner_simulations_per_step: usize,
545 /// Return horizon.
546 pub return_horizon: usize,
547 /// Teacher dataset asset for warm-start labels.
548 pub warmstart_teacher_dataset_asset: AssetId,
549 /// Label phase period.
550 pub label_phase_period: usize,
551}
552
553/// Runtime-selectable controller configuration for the tuning runtime.
554#[cfg(feature = "tuner")]
555#[derive(Clone, Debug, PartialEq)]
556#[non_exhaustive]
557pub enum TuneControllerSpec {
558 /// Annealed hill climbing.
559 AnnealedHillClimbing(AnnealedHillClimbingTuneControllerSpec),
560 /// MC-AIXI(FAC-CTW).
561 McAixiFacCtw(McAixiFacCtwTuneControllerSpec),
562 /// Discounted AIQI.
563 AiqiDiscounted(AiqiDiscountedTuneControllerSpec),
564 /// Warm-start exact-J_H.
565 #[cfg(feature = "aixi")]
566 AiqiWarmstartExactJh(WarmStartExactJhTuneControllerSpec),
567}
568
569#[cfg(feature = "tuner")]
570impl TuneControllerSpec {
571 /// Controller family tag for this tuning controller configuration.
572 pub fn kind(&self) -> TuneControllerKind {
573 match self {
574 Self::AnnealedHillClimbing(_) => TuneControllerKind::AnnealedHillClimbing,
575 Self::McAixiFacCtw(_) => TuneControllerKind::McAixiFacCtw,
576 Self::AiqiDiscounted(_) => TuneControllerKind::AiqiDiscounted,
577 #[cfg(feature = "aixi")]
578 Self::AiqiWarmstartExactJh(_) => TuneControllerKind::AiqiWarmstartExactJh,
579 }
580 }
581}
582
583#[cfg(all(test, feature = "tuner"))]
584mod tests {
585 use super::*;
586
587 fn action_alphabet(n: usize) -> ActionAlphabet {
588 ActionAlphabet::try_from_usize(n).expect("test action alphabet must be non-zero")
589 }
590
591 fn sample_tune_interface() -> TunePlannerInterfaceSpec {
592 TunePlannerInterfaceSpec {
593 observation_bits: 8,
594 observation_stream_len: 1,
595 observation_key_mode: ObservationKeyMode::FullStream,
596 reward_bits: 8,
597 agent_actions: action_alphabet(2),
598 }
599 }
600
601 #[test]
602 fn tune_controller_kind_matches_each_variant() {
603 let annealed =
604 TuneControllerSpec::AnnealedHillClimbing(AnnealedHillClimbingTuneControllerSpec {
605 max_mutation_radius: 3,
606 });
607 assert_eq!(annealed.kind(), TuneControllerKind::AnnealedHillClimbing);
608
609 let mc_aixi = TuneControllerSpec::McAixiFacCtw(McAixiFacCtwTuneControllerSpec {
610 interface: sample_tune_interface(),
611 planner_simulations_per_step: 8,
612 });
613 assert_eq!(mc_aixi.kind(), TuneControllerKind::McAixiFacCtw);
614
615 let aiqi = TuneControllerSpec::AiqiDiscounted(AiqiDiscountedTuneControllerSpec {
616 interface: sample_tune_interface(),
617 planner_simulations_per_step: 8,
618 return_horizon: 2,
619 return_bins: 8,
620 discount_factor: 0.5,
621 min_improvement: -1.0,
622 max_improvement: 1.0,
623 });
624 assert_eq!(aiqi.kind(), TuneControllerKind::AiqiDiscounted);
625
626 #[cfg(feature = "aixi")]
627 {
628 let warmstart =
629 TuneControllerSpec::AiqiWarmstartExactJh(WarmStartExactJhTuneControllerSpec {
630 interface: sample_tune_interface(),
631 planner_simulations_per_step: 1,
632 return_horizon: 2,
633 warmstart_teacher_dataset_asset: "teacher".to_string(),
634 label_phase_period: 3,
635 });
636 assert_eq!(warmstart.kind(), TuneControllerKind::AiqiWarmstartExactJh);
637 }
638 }
639}
640
641/// Bounded numeric range for a named canonical tuning parameter.
642#[cfg(feature = "tuner")]
643#[derive(Clone, Debug, PartialEq)]
644#[non_exhaustive]
645pub struct TuneParameterRangeSpec {
646 /// Canonical parameter path or name.
647 pub parameter: String,
648 /// Inclusive lower bound.
649 pub min: f64,
650 /// Inclusive upper bound.
651 pub max: f64,
652}
653
654/// Canonical bounds specification for the future tuning runtime.
655#[cfg(feature = "tuner")]
656#[derive(Clone, Debug, PartialEq)]
657#[non_exhaustive]
658pub struct TuneBoundsSpec {
659 /// Allowed canonical backend names.
660 pub allowed_backends: Vec<String>,
661 /// Forbidden canonical backend names.
662 pub forbidden_backends: Vec<String>,
663 /// Inclusive ranges for canonical numeric parameters.
664 pub parameter_ranges: Vec<TuneParameterRangeSpec>,
665 /// Maximum experts per mixture node.
666 pub max_experts: usize,
667 /// Maximum recursive mixture nesting depth.
668 pub max_mixture_nesting_depth: usize,
669 /// Optional minimum experts per mixture node.
670 pub min_experts: Option<usize>,
671 /// Whether duplicate experts are permitted.
672 pub allow_duplicate_experts: Option<bool>,
673 /// Expert names that must appear in the candidate set.
674 pub required_experts: Vec<String>,
675 /// Canonical expert-pair combinations that are forbidden together.
676 pub forbidden_expert_pairs: Vec<(String, String)>,
677}
678
679/// Canonical future-facing tune request document.
680#[cfg(feature = "tuner")]
681#[derive(Clone)]
682#[non_exhaustive]
683pub struct TuneSpec {
684 /// External asset bindings referenced by this request.
685 pub assets: Vec<AssetBinding>,
686 /// Asset identifier for the input dataset.
687 pub input_asset: AssetId,
688 /// Baseline candidate configuration.
689 pub baseline_candidate: CompressionBackend,
690 /// Runtime-selectable controller used by the tuning runtime.
691 pub controller: TuneControllerSpec,
692 /// Candidate bounds specification.
693 pub bounds: TuneBoundsSpec,
694 /// Per-candidate evaluation time limit in seconds.
695 pub eval_time_limit_seconds: f64,
696 /// Total search budget in seconds.
697 pub time_budget_seconds: f64,
698 /// Minimum required throughput in bytes/second.
699 pub min_throughput_bytes_per_second: f64,
700 /// Maximum allowed memory use in bytes.
701 pub max_memory_bytes: u64,
702 /// Output path for the best canonical candidate.
703 pub output_config_path: String,
704 /// Deterministic search seed.
705 pub seed: u64,
706 /// Optional report output path.
707 pub report_path: Option<String>,
708}
709
710/// Compiled planner controller with precompiled predictor backends.
711#[derive(Clone)]
712#[non_exhaustive]
713pub enum CompiledPlannerController {
714 /// MC-AIXI controller.
715 McAixi {
716 /// Compiled predictor backend.
717 predictor: CompiledRateBackend,
718 /// Bit-stream semantics used to adapt the predictor to AIXI symbols.
719 bit_stream_semantics: BitStreamSemantics,
720 /// Planning horizon.
721 agent_horizon: usize,
722 /// Number of simulations per planning step.
723 num_simulations: usize,
724 /// Explicit MCTS strategy used by the planner.
725 mcts_strategy: MctsStrategy,
726 /// UCT exploration constant.
727 exploration_exploitation_ratio: f64,
728 /// Reward discount factor.
729 discount_gamma: f64,
730 },
731 /// Discounted AIQI controller.
732 AiqiDiscounted {
733 /// Compiled predictor backend.
734 predictor: CompiledRateBackend,
735 /// Bit-stream semantics used to adapt the predictor to AIQI symbols.
736 bit_stream_semantics: BitStreamSemantics,
737 /// Discount factor used for return construction.
738 discount_gamma: f64,
739 /// Return horizon.
740 return_horizon: usize,
741 /// Number of return bins.
742 return_bins: usize,
743 /// Label augmentation period.
744 augmentation_period: usize,
745 /// Optional bounded-history retention hint.
746 history_prune_keep_steps: Option<usize>,
747 /// Baseline exploration probability.
748 baseline_exploration: f64,
749 },
750 /// Warm-start exact-J_H controller.
751 #[cfg(feature = "aixi")]
752 AiqiWarmstartExactJh {
753 /// Compiled predictor backend.
754 predictor: CompiledRateBackend,
755 /// Bit-stream semantics used to adapt the predictor to warm-start symbols.
756 bit_stream_semantics: BitStreamSemantics,
757 /// Return horizon.
758 return_horizon: usize,
759 /// Number of return bins.
760 return_bins: usize,
761 /// Label phase period.
762 label_phase_period: usize,
763 /// Teacher dataset asset id.
764 teacher_dataset_asset: AssetId,
765 /// Canonical direct-evaluator budget marker.
766 planner_simulations_per_step: usize,
767 },
768}
769
770/// Compiled planner-run specification with resolved assets and compiled backends.
771#[derive(Clone)]
772#[non_exhaustive]
773pub struct CompiledPlannerRunSpec {
774 pub(super) canonical_spec: Arc<PlannerRunSpec>,
775 pub(super) canonical_bytes: CanonicalBytes,
776 pub(super) resolved_assets: Arc<[ResolvedAssetBinding]>,
777 pub(super) interface: PlannerInterfaceSpec,
778 pub(super) runtime: PlannerRuntimeSpec,
779 pub(super) controller: CompiledPlannerController,
780 pub(super) action_bits: usize,
781}
782
783/// Compiled tuning controller configuration.
784#[cfg(feature = "tuner")]
785#[derive(Clone)]
786#[non_exhaustive]
787pub enum CompiledTuneController {
788 /// Annealed hill climbing.
789 AnnealedHillClimbing(AnnealedHillClimbingTuneControllerSpec),
790 /// MC-AIXI(FAC-CTW).
791 McAixiFacCtw(McAixiFacCtwTuneControllerSpec),
792 /// Discounted AIQI.
793 AiqiDiscounted(AiqiDiscountedTuneControllerSpec),
794 /// Warm-start exact-J_H.
795 #[cfg(feature = "aixi")]
796 AiqiWarmstartExactJh(WarmStartExactJhTuneControllerSpec),
797}
798
799/// Compiled tune request with resolved assets and compiled baseline candidate.
800#[cfg(feature = "tuner")]
801#[derive(Clone)]
802#[non_exhaustive]
803pub struct CompiledTuneSpec {
804 pub(super) canonical_spec: Arc<TuneSpec>,
805 pub(super) canonical_bytes: CanonicalBytes,
806 pub(super) base_dir: PathBuf,
807 pub(super) resolved_assets: Arc<[ResolvedAssetBinding]>,
808 pub(super) baseline_candidate: CompiledCompressionBackend,
809 pub(super) controller: CompiledTuneController,
810 pub(super) candidate_canonicalization_version: &'static str,
811}
812
813/// Universal top-level spec document.
814#[derive(Clone)]
815#[non_exhaustive]
816#[allow(clippy::large_enum_variant)]
817pub enum SpecDocument {
818 /// Planner-run configuration document.
819 PlannerRun(PlannerRunSpec),
820 /// Tune request document.
821 #[cfg(feature = "tuner")]
822 Tune(TuneSpec),
823 /// Standalone rate-backend document.
824 RateBackend(RateBackend),
825 /// Standalone compression-backend document.
826 CompressionBackend(CompressionBackend),
827}
828
829/// Parsed top-level spec document paired with its parse base directory.
830///
831/// This is the first stage of the canonical pipeline:
832/// parse -> validate -> compile.
833#[derive(Clone)]
834#[non_exhaustive]
835pub struct ParsedSpecDocument {
836 pub(super) document: SpecDocument,
837 pub(super) base_dir: PathBuf,
838}
839
840/// Canonicalized and validated planner-run document.
841#[derive(Clone)]
842#[non_exhaustive]
843pub struct ValidatedPlannerRunSpec {
844 pub(super) canonical_spec: Arc<PlannerRunSpec>,
845 pub(super) canonical_bytes: CanonicalBytes,
846 pub(super) base_dir: PathBuf,
847}
848
849/// Canonicalized and validated tune request document.
850#[cfg(feature = "tuner")]
851#[derive(Clone)]
852#[non_exhaustive]
853pub struct ValidatedTuneSpec {
854 pub(super) canonical_spec: Arc<TuneSpec>,
855 pub(super) canonical_bytes: CanonicalBytes,
856 #[cfg(feature = "tuner")]
857 pub(super) base_dir: PathBuf,
858}
859
860/// Validated top-level spec document.
861///
862/// This is the second stage of the canonical pipeline and can be compiled into
863/// runtime-ready plans/backends.
864#[derive(Clone)]
865#[non_exhaustive]
866pub enum ValidatedSpecDocument {
867 /// Validated planner-run document.
868 PlannerRun(ValidatedPlannerRunSpec),
869 /// Validated tune document.
870 #[cfg(feature = "tuner")]
871 Tune(ValidatedTuneSpec),
872 /// Validated standalone rate-backend document.
873 RateBackend(ValidatedRateBackend),
874 /// Validated standalone compression-backend document.
875 CompressionBackend(ValidatedCompressionBackend),
876}
877
878/// Compiled top-level spec document.
879///
880/// This is the final stage of the canonical pipeline and is executable by
881/// runtime adapters.
882#[derive(Clone)]
883#[non_exhaustive]
884#[allow(clippy::large_enum_variant)]
885pub enum CompiledSpecDocument {
886 /// Compiled planner-run document.
887 PlannerRun(CompiledPlannerRunSpec),
888 /// Compiled tune document.
889 #[cfg(feature = "tuner")]
890 Tune(CompiledTuneSpec),
891 /// Compiled standalone rate-backend document.
892 RateBackend(CompiledRateBackend),
893 /// Compiled standalone compression-backend document.
894 CompressionBackend(CompiledCompressionBackend),
895}