S559 · SOURCE-BOUND GATE EVIDENCE
S559 · R1 ses: laboratuvar ses route ve PCM capability modeli
tam S559 implementation modülü → Operations --test hedefi ile bağlı tam focused test → ayrı Operations kaydı Bu sayfa yalnız S559 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.
S559Focused kod testiOperations id exactsource SHA exacttest target exact
operation: g8l-s559-r1-audio-route-pcm-capability-model
uygulama/model · focused test · Operations · 3 exact excerpt
sequence-bound=true · implementation-bound=true
01 · Yürütme / doğrulama kodu
Kapının gerçek repository sözleşmesi
tam dosyaL1–L928
kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model.rs::S559 r1 audio route pcm capability model implementation
#![allow(unexpected_cfgs)]
//! S559 models the laboratory audio path of the R1 modem/voice stage as a
//! pure source/host model.
//!
//! The model covers five audio endpoints (`Earpiece`, `Speaker`, `Headset`,
//! `ModemUplink`, `ModemDownlink`) joined by a fixed routing matrix of allowed
//! source-to-sink pairs, a PCM format descriptor (16 kHz or 8 kHz, 16-bit
//! mono, 20 ms frames of 320 or 160 samples), a bounded ring of at most 16
//! frames with underrun/overrun counters, a gain in 3 dB steps clamped to
//! -60..+12 dB backed by a fixed Q10 multiplier table, a mute flag, and a
//! capability bit set `{PLAYBACK, CAPTURE, ROUTE}` shaped like
//! `FramebufferRights` with grant/revoke narrowing. Every accepted operation
//! publishes one receipt into a bounded ledger; a missing right, an invalid
//! route, a format or frame-length mismatch, an overrun or an underrun fails
//! closed. The mixed output of a pop carries a deterministic FNV-1a checksum
//! so the focused host test can pin the rendered samples byte-exactly.
//!
//! S559 does not claim any codec, amplifier, microphone, modem, UART, panel,
//! board, power transition or runtime observation. The module has no
//! production callsite and is driven only by its focused host test. It
//! performs no device operation and does not rerun S540 or S543.
//! Predecessor: S558 (voice call state machine model). Next gate: S560
//! (modem subsystem capability supervision model).
use alloc::vec::Vec;
pub const S559_SEQUENCE: usize = 559;
pub const S559_EXPECTED_PREDECESSOR: usize = 558;
pub const S559_R1_STAGE: u8 = 3;
pub const S559_R1_RANGE_FIRST: usize = 536;
pub const S559_R1_RANGE_LAST: usize = 568;
pub const S559_ENDPOINT_COUNT: usize = 5;
pub const S559_ALLOWED_ROUTE_COUNT: usize = 5;
pub const S559_WIDEBAND_SAMPLE_RATE_HZ: u32 = 16_000;
pub const S559_NARROWBAND_SAMPLE_RATE_HZ: u32 = 8_000;
pub const S559_BITS_PER_SAMPLE: u8 = 16;
pub const S559_CHANNELS: u8 = 1;
pub const S559_FRAME_DURATION_MS: u32 = 20;
pub const S559_WIDEBAND_FRAME_SAMPLES: usize = 320;
pub const S559_NARROWBAND_FRAME_SAMPLES: usize = 160;
pub const S559_RING_CAPACITY_FRAMES: usize = 16;
pub const S559_GAIN_MIN_DB: i8 = -60;
pub const S559_GAIN_MAX_DB: i8 = 12;
pub const S559_GAIN_STEP_DB: i8 = 3;
pub const S559_GAIN_TABLE_LEN: usize = 25;
pub const S559_GAIN_UNITY_Q10: i32 = 1024;
pub const S559_MAX_MIX_DEPTH: u8 = 4;
pub const S559_MAX_OPERATIONS: usize = 64;
pub const S559_CHECKSUM_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
pub const S559_CHECKSUM_PRIME: u64 = 0x0000_0100_0000_01b3;
pub const S559_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS: usize = 0;
pub const S559_PHYSICAL_OBSERVATIONS: usize = 0;
pub const S559_PHYSICAL_OR_DEVICE_OPERATIONS: usize = 0;
pub const S559_SD_WRITES: usize = 0;
pub const S559_UART_OPENS: usize = 0;
pub const S559_POWER_TRANSITIONS: usize = 0;
pub const S559_NEW_IMMUTABLE_RAW_CAPTURES: usize = 0;
pub const S559_S540_PHYSICAL_VERDICT_RETAINED_RED: bool = true;
pub const S559_S543_PHYSICAL_VERDICT_RETAINED_RED: bool = true;
pub const S559_AUTOMATIC_PROMOTION: bool = false;
pub const S559_BOOT_TO_UI_PHYSICALLY_OBSERVED: bool = false;
pub const S559_HARDWARE_PRESENT: bool = false;
pub const S559_R1_ACCEPTANCE_COMPLETE: bool = false;
pub const RUNBOOK_EXECUTED_IN_S559: bool = false;
/// Q10 linear multipliers for -60 dB .. +12 dB in 3 dB steps
/// (`round(10^(dB/20) * 1024)`).
pub const S559_GAIN_TABLE_Q10: [i32; S559_GAIN_TABLE_LEN] = [
1, 1, 2, 3, 4, 6, 8, 11, 16, 23, 32, 46, 65, 91, 129, 182, 257, 363, 513, 725, 1024, 1446,
2043, 2886, 4077,
];
/// Capability rights of the lab audio path, shaped like `FramebufferRights`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS559AudioRights(u8);
impl G8lS559AudioRights {
pub const PLAYBACK: Self = Self(0b001);
pub const CAPTURE: Self = Self(0b010);
pub const ROUTE: Self = Self(0b100);
pub const FULL: Self = Self(Self::PLAYBACK.0 | Self::CAPTURE.0 | Self::ROUTE.0);
pub const fn empty() -> Self {
Self(0)
}
/// Fail-closed constructor: any bit outside `FULL` is rejected.
pub const fn from_bits(bits: u8) -> Result<Self, G8lS559AudioError> {
if bits & !Self::FULL.0 != 0 {
return Err(G8lS559AudioError::InvalidRightsBits);
}
Ok(Self(bits))
}
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
pub const fn intersects(self, other: Self) -> bool {
(self.0 & other.0) != 0
}
/// Produces a new set; only narrowing is possible.
pub const fn intersect(self, other: Self) -> Self {
Self(self.0 & other.0)
}
pub const fn remove(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
pub const fn is_empty(self) -> bool {
self.0 == 0
}
pub const fn as_u8(self) -> u8 {
self.0
}
}
impl core::ops::BitOr for G8lS559AudioRights {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
/// Lab audio endpoints. A route is an ordered `(source, sink)` pair.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS559AudioEndpoint {
Earpiece,
Speaker,
Headset,
ModemUplink,
ModemDownlink,
}
impl G8lS559AudioEndpoint {
pub const ALL: [Self; S559_ENDPOINT_COUNT] = [
Self::Earpiece,
Self::Speaker,
Self::Headset,
Self::ModemUplink,
Self::ModemDownlink,
];
pub const fn index(self) -> usize {
match self {
Self::Earpiece => 0,
Self::Speaker => 1,
Self::Headset => 2,
Self::ModemUplink => 3,
Self::ModemDownlink => 4,
}
}
}
/// Routing matrix indexed `[source][sink]`. Exactly five pairs are allowed:
/// modem downlink to earpiece, speaker or headset; headset microphone to modem
/// uplink; and the lab loopback modem downlink to modem uplink.
pub const S559_ROUTE_MATRIX: [[bool; S559_ENDPOINT_COUNT]; S559_ENDPOINT_COUNT] = [
[false, false, false, false, false],
[false, false, false, false, false],
[false, false, false, true, false],
[false, false, false, false, false],
[true, true, true, true, false],
];
pub const fn s559_route_is_allowed(
source: G8lS559AudioEndpoint,
sink: G8lS559AudioEndpoint,
) -> bool {
S559_ROUTE_MATRIX[source.index()][sink.index()]
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS559RouteKind {
Downlink,
Uplink,
Loopback,
}
impl G8lS559RouteKind {
pub const fn required_rights(self) -> G8lS559AudioRights {
match self {
Self::Downlink => G8lS559AudioRights::PLAYBACK,
Self::Uplink => G8lS559AudioRights::CAPTURE,
Self::Loopback => {
G8lS559AudioRights(G8lS559AudioRights::PLAYBACK.0 | G8lS559AudioRights::CAPTURE.0)
}
}
}
}
pub const fn s559_route_kind(
source: G8lS559AudioEndpoint,
sink: G8lS559AudioEndpoint,
) -> Option<G8lS559RouteKind> {
if !s559_route_is_allowed(source, sink) {
return None;
}
match (source, sink) {
(G8lS559AudioEndpoint::ModemDownlink, G8lS559AudioEndpoint::ModemUplink) => {
Some(G8lS559RouteKind::Loopback)
}
(G8lS559AudioEndpoint::ModemDownlink, _) => Some(G8lS559RouteKind::Downlink),
(G8lS559AudioEndpoint::Headset, G8lS559AudioEndpoint::ModemUplink) => {
Some(G8lS559RouteKind::Uplink)
}
_ => None,
}
}
/// PCM format descriptor. Only 16-bit mono 20 ms frames at 16 kHz or 8 kHz
/// validate.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS559PcmFormat {
pub sample_rate_hz: u32,
pub bits_per_sample: u8,
pub channels: u8,
pub frame_duration_ms: u32,
}
impl G8lS559PcmFormat {
pub const fn wideband() -> Self {
Self {
sample_rate_hz: S559_WIDEBAND_SAMPLE_RATE_HZ,
bits_per_sample: S559_BITS_PER_SAMPLE,
channels: S559_CHANNELS,
frame_duration_ms: S559_FRAME_DURATION_MS,
}
}
pub const fn narrowband() -> Self {
Self {
sample_rate_hz: S559_NARROWBAND_SAMPLE_RATE_HZ,
bits_per_sample: S559_BITS_PER_SAMPLE,
channels: S559_CHANNELS,
frame_duration_ms: S559_FRAME_DURATION_MS,
}
}
pub const fn validate(self) -> Result<(), G8lS559AudioError> {
if self.sample_rate_hz != S559_WIDEBAND_SAMPLE_RATE_HZ
&& self.sample_rate_hz != S559_NARROWBAND_SAMPLE_RATE_HZ
{
return Err(G8lS559AudioError::InvalidSampleRate);
}
if self.bits_per_sample != S559_BITS_PER_SAMPLE {
return Err(G8lS559AudioError::InvalidBitsPerSample);
}
if self.channels != S559_CHANNELS {
return Err(G8lS559AudioError::InvalidChannels);
}
if self.frame_duration_ms != S559_FRAME_DURATION_MS {
return Err(G8lS559AudioError::InvalidFrameDuration);
}
Ok(())
}
/// Samples per frame: `rate * frame_ms / 1000 * channels`, checked.
pub const fn frame_samples(self) -> Result<usize, G8lS559AudioError> {
if let Err(error) = self.validate() {
return Err(error);
}
let Some(product) = self.sample_rate_hz.checked_mul(self.frame_duration_ms) else {
return Err(G8lS559AudioError::ArithmeticOverflow);
};
let Some(per_channel) = (product / 1000).checked_mul(self.channels as u32) else {
return Err(G8lS559AudioError::ArithmeticOverflow);
};
Ok(per_channel as usize)
}
pub const fn frame_bytes(self) -> Result<usize, G8lS559AudioError> {
match self.frame_samples() {
Ok(samples) => match samples.checked_mul((self.bits_per_sample / 8) as usize) {
Some(bytes) => Ok(bytes),
None => Err(G8lS559AudioError::ArithmeticOverflow),
},
Err(error) => Err(error),
}
}
}
/// Output gain in 3 dB steps, clamped to `S559_GAIN_MIN_DB..=S559_GAIN_MAX_DB`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS559Gain {
db: i8,
}
impl G8lS559Gain {
pub const fn unity() -> Self {
Self { db: 0 }
}
pub const fn db(self) -> i8 {
self.db
}
/// Moves the gain by `steps * 3 dB` and clamps at both bounds.
pub const fn stepped(self, steps: i8) -> Self {
let target = self.db as i16 + (steps as i16) * (S559_GAIN_STEP_DB as i16);
let clamped = if target < S559_GAIN_MIN_DB as i16 {
S559_GAIN_MIN_DB
} else if target > S559_GAIN_MAX_DB as i16 {
S559_GAIN_MAX_DB
} else {
target as i8
};
Self { db: clamped }
}
pub const fn multiplier_q10(self) -> i32 {
let index =
((self.db as i16 - S559_GAIN_MIN_DB as i16) / S559_GAIN_STEP_DB as i16) as usize;
S559_GAIN_TABLE_Q10[index]
}
/// Applies the Q10 multiplier and saturates to the 16-bit range.
pub const fn apply(self, sample: i16) -> i16 {
let scaled = (sample as i32 * self.multiplier_q10()) / S559_GAIN_UNITY_Q10;
if scaled > i16::MAX as i32 {
i16::MAX
} else if scaled < i16::MIN as i32 {
i16::MIN
} else {
scaled as i16
}
}
}
/// Deterministic FNV-1a checksum over the sample count and little-endian
/// sample bytes.
pub fn s559_pcm_checksum(samples: &[i16]) -> u64 {
let mut hash = fnv_u64(S559_CHECKSUM_OFFSET, samples.len() as u64);
for sample in samples {
for byte in sample.to_le_bytes() {
hash = fnv_byte(hash, byte);
}
}
hash
}
const fn fnv_byte(hash: u64, byte: u8) -> u64 {
(hash ^ byte as u64).wrapping_mul(S559_CHECKSUM_PRIME)
}
const fn fnv_u64(mut hash: u64, value: u64) -> u64 {
let bytes = value.to_le_bytes();
let mut index = 0;
while index < bytes.len() {
hash = fnv_byte(hash, bytes[index]);
index += 1;
}
hash
}
/// Bounded ring of PCM frames with underrun/overrun counters.
#[derive(Debug)]
pub struct G8lS559FrameRing {
slots: Vec<Option<Vec<i16>>>,
read_index: usize,
write_index: usize,
len: usize,
underruns: u32,
overruns: u32,
}
impl G8lS559FrameRing {
pub fn new() -> Self {
let mut slots = Vec::with_capacity(S559_RING_CAPACITY_FRAMES);
for _ in 0..S559_RING_CAPACITY_FRAMES {
slots.push(None);
}
Self {
slots,
read_index: 0,
write_index: 0,
len: 0,
underruns: 0,
overruns: 0,
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn underruns(&self) -> u32 {
self.underruns
}
pub fn overruns(&self) -> u32 {
self.overruns
}
/// Fails closed when full; the frame is dropped and the overrun counted.
pub fn push(&mut self, frame: Vec<i16>) -> Result<(), G8lS559AudioError> {
if self.len >= S559_RING_CAPACITY_FRAMES {
self.overruns = self.overruns.saturating_add(1);
return Err(G8lS559AudioError::RingOverrun);
}
self.slots[self.write_index] = Some(frame);
self.write_index = (self.write_index + 1) % S559_RING_CAPACITY_FRAMES;
self.len += 1;
Ok(())
}
/// Fails closed when empty and counts the underrun.
pub fn pop(&mut self) -> Result<Vec<i16>, G8lS559AudioError> {
if self.len == 0 {
self.underruns = self.underruns.saturating_add(1);
return Err(G8lS559AudioError::RingUnderrun);
}
let frame = self.slots[self.read_index]
.take()
.ok_or(G8lS559AudioError::RingSlotCorrupt)?;
self.read_index = (self.read_index + 1) % S559_RING_CAPACITY_FRAMES;
self.len -= 1;
Ok(frame)
}
pub fn record_underrun(&mut self) {
self.underruns = self.underruns.saturating_add(1);
}
pub fn flush(&mut self) {
for slot in self.slots.iter_mut() {
*slot = None;
}
self.read_index = 0;
self.write_index = 0;
self.len = 0;
}
}
impl Default for G8lS559FrameRing {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS559OpKind {
Grant,
Revoke,
SetFormat,
SelectRoute,
SetGain,
SetMute,
PushFrame,
PopMixedFrame,
}
impl G8lS559OpKind {
const fn tag(self) -> u8 {
match self {
Self::Grant => 1,
Self::Revoke => 2,
Self::SetFormat => 3,
Self::SelectRoute => 4,
Self::SetGain => 5,
Self::SetMute => 6,
Self::PushFrame => 7,
Self::PopMixedFrame => 8,
}
}
}
/// One operation of the lab audio path.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum G8lS559AudioOp {
Grant {
rights: u8,
},
Revoke {
rights: u8,
},
SetFormat {
format: G8lS559PcmFormat,
},
SelectRoute {
source: G8lS559AudioEndpoint,
sink: G8lS559AudioEndpoint,
},
SetGain {
steps: i8,
},
SetMute {
muted: bool,
},
PushFrame {
format: G8lS559PcmFormat,
samples: Vec<i16>,
},
PopMixedFrame {
mix_depth: u8,
},
}
impl G8lS559AudioOp {
pub const fn kind(&self) -> G8lS559OpKind {
match self {
Self::Grant { .. } => G8lS559OpKind::Grant,
Self::Revoke { .. } => G8lS559OpKind::Revoke,
Self::SetFormat { .. } => G8lS559OpKind::SetFormat,
Self::SelectRoute { .. } => G8lS559OpKind::SelectRoute,
Self::SetGain { .. } => G8lS559OpKind::SetGain,
Self::SetMute { .. } => G8lS559OpKind::SetMute,
Self::PushFrame { .. } => G8lS559OpKind::PushFrame,
Self::PopMixedFrame { .. } => G8lS559OpKind::PopMixedFrame,
}
}
/// Deterministic digest used to detect divergent replay.
pub fn digest(&self) -> u64 {
let mut hash = fnv_byte(S559_CHECKSUM_OFFSET, self.kind().tag());
match self {
Self::Grant { rights } | Self::Revoke { rights } => hash = fnv_byte(hash, *rights),
Self::SetFormat { format } => hash = digest_format(hash, *format),
Self::SelectRoute { source, sink } => {
hash = fnv_byte(hash, source.index() as u8);
hash = fnv_byte(hash, sink.index() as u8);
}
Self::SetGain { steps } => hash = fnv_byte(hash, *steps as u8),
Self::SetMute { muted } => hash = fnv_byte(hash, *muted as u8),
Self::PushFrame { format, samples } => {
hash = digest_format(hash, *format);
hash = fnv_u64(hash, s559_pcm_checksum(samples));
}
Self::PopMixedFrame { mix_depth } => hash = fnv_byte(hash, *mix_depth),
}
hash
}
}
const fn digest_format(mut hash: u64, format: G8lS559PcmFormat) -> u64 {
hash = fnv_u64(hash, format.sample_rate_hz as u64);
hash = fnv_byte(hash, format.bits_per_sample);
hash = fnv_byte(hash, format.channels);
fnv_u64(hash, format.frame_duration_ms as u64)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS559AudioReceipt {
pub sequence: usize,
pub step: usize,
pub op_kind: G8lS559OpKind,
pub op_digest: u64,
pub rights_after: u8,
pub route_after: Option<(G8lS559AudioEndpoint, G8lS559AudioEndpoint)>,
pub route_kind_after: Option<G8lS559RouteKind>,
pub sample_rate_hz_after: u32,
pub frame_samples_after: usize,
pub gain_db_after: i8,
pub muted_after: bool,
pub ring_len_after: usize,
pub underruns_after: u32,
pub overruns_after: u32,
pub mixed_frames: u8,
pub output_checksum: u64,
pub output_peak: u16,
pub hardware_present: bool,
pub physical_observations: usize,
pub runbook_executed: bool,
}
#[derive(Debug)]
pub struct G8lS559AudioRouteState {
rights: Option<G8lS559AudioRights>,
format: Option<G8lS559PcmFormat>,
route: Option<(G8lS559AudioEndpoint, G8lS559AudioEndpoint)>,
gain: G8lS559Gain,
muted: bool,
ring: G8lS559FrameRing,
receipts: Vec<G8lS559AudioReceipt>,
}
impl G8lS559AudioRouteState {
pub fn new() -> Self {
Self {
rights: None,
format: None,
route: None,
gain: G8lS559Gain::unity(),
muted: false,
ring: G8lS559FrameRing::new(),
receipts: Vec::new(),
}
}
pub fn rights(&self) -> Option<G8lS559AudioRights> {
self.rights
}
pub fn format(&self) -> Option<G8lS559PcmFormat> {
self.format
}
pub fn route(&self) -> Option<(G8lS559AudioEndpoint, G8lS559AudioEndpoint)> {
self.route
}
pub fn gain(&self) -> G8lS559Gain {
self.gain
}
pub fn muted(&self) -> bool {
self.muted
}
pub fn ring(&self) -> &G8lS559FrameRing {
&self.ring
}
pub fn receipts(&self) -> &[G8lS559AudioReceipt] {
&self.receipts
}
fn rights_or_err(&self) -> Result<G8lS559AudioRights, G8lS559AudioError> {
self.rights.ok_or(G8lS559AudioError::NoRightsGranted)
}
fn require(&self, required: G8lS559AudioRights) -> Result<(), G8lS559AudioError> {
let held = self.rights_or_err()?;
if required.contains(G8lS559AudioRights::ROUTE) && !held.contains(G8lS559AudioRights::ROUTE)
{
return Err(G8lS559AudioError::RightsMissingRoute);
}
if required.contains(G8lS559AudioRights::PLAYBACK)
&& !held.contains(G8lS559AudioRights::PLAYBACK)
{
return Err(G8lS559AudioError::RightsMissingPlayback);
}
if required.contains(G8lS559AudioRights::CAPTURE)
&& !held.contains(G8lS559AudioRights::CAPTURE)
{
return Err(G8lS559AudioError::RightsMissingCapture);
}
Ok(())
}
fn open_route_kind(&self) -> Result<G8lS559RouteKind, G8lS559AudioError> {
let (source, sink) = self.route.ok_or(G8lS559AudioError::RouteNotSelected)?;
s559_route_kind(source, sink).ok_or(G8lS559AudioError::InvalidRoute)
}
fn snapshot(
&self,
step: usize,
op: &G8lS559AudioOp,
mixed_frames: u8,
output_checksum: u64,
output_peak: u16,
) -> G8lS559AudioReceipt {
G8lS559AudioReceipt {
sequence: S559_SEQUENCE,
step,
op_kind: op.kind(),
op_digest: op.digest(),
rights_after: self.rights.map_or(0, G8lS559AudioRights::as_u8),
route_after: self.route,
route_kind_after: self
.route
.and_then(|(source, sink)| s559_route_kind(source, sink)),
sample_rate_hz_after: self.format.map_or(0, |format| format.sample_rate_hz),
frame_samples_after: self
.format
.and_then(|format| format.frame_samples().ok())
.unwrap_or(0),
gain_db_after: self.gain.db(),
muted_after: self.muted,
ring_len_after: self.ring.len(),
underruns_after: self.ring.underruns(),
overruns_after: self.ring.overruns(),
mixed_frames,
output_checksum,
output_peak,
hardware_present: S559_HARDWARE_PRESENT,
physical_observations: S559_PHYSICAL_OBSERVATIONS,
runbook_executed: RUNBOOK_EXECUTED_IN_S559,
}
}
}
impl Default for G8lS559AudioRouteState {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS559AudioOutcome {
OperationPublished(G8lS559AudioReceipt),
OperationRetained(G8lS559AudioReceipt),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS559AudioError {
StepOutOfOrder,
LedgerFull,
PublishedStateDrift,
InvalidRightsBits,
EmptyRightsGrant,
EmptyRightsRevoke,
RightsAlreadyGranted,
NoRightsGranted,
RevokeNotSubset,
RightsMissingRoute,
RightsMissingPlayback,
RightsMissingCapture,
InvalidRoute,
RouteNotSelected,
InvalidSampleRate,
InvalidBitsPerSample,
InvalidChannels,
InvalidFrameDuration,
FormatNotSet,
FormatMismatch,
FrameLengthMismatch,
RingOverrun,
RingUnderrun,
RingNotEmpty,
RingSlotCorrupt,
InvalidMixDepth,
GainStepZero,
ArithmeticOverflow,
}
impl G8lS559AudioError {
pub const fn diagnostic_code(self) -> u64 {
match self {
Self::StepOutOfOrder => 1,
Self::LedgerFull => 2,
Self::PublishedStateDrift => 3,
Self::InvalidRightsBits => 4,
Self::EmptyRightsGrant => 5,
Self::EmptyRightsRevoke => 6,
Self::RightsAlreadyGranted => 7,
Self::NoRightsGranted => 8,
Self::RevokeNotSubset => 9,
Self::RightsMissingRoute => 10,
Self::RightsMissingPlayback => 11,
Self::RightsMissingCapture => 12,
Self::InvalidRoute => 13,
Self::RouteNotSelected => 14,
Self::InvalidSampleRate => 15,
Self::InvalidBitsPerSample => 16,
Self::InvalidChannels => 17,
Self::InvalidFrameDuration => 18,
Self::FormatNotSet => 19,
Self::FormatMismatch => 20,
Self::FrameLengthMismatch => 21,
Self::RingOverrun => 22,
Self::RingUnderrun => 23,
Self::RingNotEmpty => 24,
Self::RingSlotCorrupt => 25,
Self::InvalidMixDepth => 26,
Self::GainStepZero => 27,
Self::ArithmeticOverflow => 28,
}
}
}
/// Applies one operation. Validation precedes every mutation except the
/// underrun/overrun counters, which are the modelled effect of a rejected
/// pop or push. Returns `(mixed_frames, output_checksum, output_peak)`.
fn apply_op(
state: &mut G8lS559AudioRouteState,
op: &G8lS559AudioOp,
) -> Result<(u8, u64, u16), G8lS559AudioError> {
match op {
G8lS559AudioOp::Grant { rights } => {
let granted = G8lS559AudioRights::from_bits(*rights)?;
if granted.is_empty() {
return Err(G8lS559AudioError::EmptyRightsGrant);
}
if state.rights.is_some() {
return Err(G8lS559AudioError::RightsAlreadyGranted);
}
state.rights = Some(granted);
}
G8lS559AudioOp::Revoke { rights } => {
let revoked = G8lS559AudioRights::from_bits(*rights)?;
if revoked.is_empty() {
return Err(G8lS559AudioError::EmptyRightsRevoke);
}
let held = state.rights_or_err()?;
if !held.contains(revoked) {
return Err(G8lS559AudioError::RevokeNotSubset);
}
let remaining = held.remove(revoked);
state.rights = if remaining.is_empty() {
None
} else {
Some(remaining)
};
if let Ok(kind) = state.open_route_kind() {
let needed = kind.required_rights() | G8lS559AudioRights::ROUTE;
if !remaining.contains(needed) {
state.route = None;
state.ring.flush();
}
}
}
G8lS559AudioOp::SetFormat { format } => {
state.require(G8lS559AudioRights::ROUTE)?;
format.validate()?;
if !state.ring.is_empty() {
return Err(G8lS559AudioError::RingNotEmpty);
}
state.format = Some(*format);
}
G8lS559AudioOp::SelectRoute { source, sink } => {
state.require(G8lS559AudioRights::ROUTE)?;
let kind = s559_route_kind(*source, *sink).ok_or(G8lS559AudioError::InvalidRoute)?;
state.require(kind.required_rights())?;
if state.format.is_none() {
return Err(G8lS559AudioError::FormatNotSet);
}
if !state.ring.is_empty() {
return Err(G8lS559AudioError::RingNotEmpty);
}
state.route = Some((*source, *sink));
}
G8lS559AudioOp::SetGain { steps } => {
state.require(G8lS559AudioRights::PLAYBACK)?;
if *steps == 0 {
return Err(G8lS559AudioError::GainStepZero);
}
state.gain = state.gain.stepped(*steps);
}
G8lS559AudioOp::SetMute { muted } => {
state.require(G8lS559AudioRights::PLAYBACK)?;
state.muted = *muted;
}
G8lS559AudioOp::PushFrame { format, samples } => {
let kind = state.open_route_kind()?;
state.require(kind.required_rights())?;
let active = state.format.ok_or(G8lS559AudioError::FormatNotSet)?;
if *format != active {
return Err(G8lS559AudioError::FormatMismatch);
}
if samples.len() != active.frame_samples()? {
return Err(G8lS559AudioError::FrameLengthMismatch);
}
state.ring.push(samples.clone())?;
}
G8lS559AudioOp::PopMixedFrame { mix_depth } => {
let kind = state.open_route_kind()?;
state.require(kind.required_rights())?;
let active = state.format.ok_or(G8lS559AudioError::FormatNotSet)?;
if *mix_depth == 0 || *mix_depth > S559_MAX_MIX_DEPTH {
return Err(G8lS559AudioError::InvalidMixDepth);
}
if state.ring.len() < *mix_depth as usize {
state.ring.record_underrun();
return Err(G8lS559AudioError::RingUnderrun);
}
let frame_samples = active.frame_samples()?;
let mut mixed: Vec<i16> = Vec::with_capacity(frame_samples);
for _ in 0..frame_samples {
mixed.push(0);
}
for _ in 0..*mix_depth {
let frame = state.ring.pop()?;
if frame.len() != frame_samples {
return Err(G8lS559AudioError::FrameLengthMismatch);
}
for (slot, sample) in mixed.iter_mut().zip(frame.iter()) {
*slot = slot.saturating_add(*sample);
}
}
let mut peak: u16 = 0;
for slot in mixed.iter_mut() {
*slot = if state.muted {
0
} else {
state.gain.apply(*slot)
};
let magnitude = slot.unsigned_abs();
if magnitude > peak {
peak = magnitude;
}
}
return Ok((*mix_depth, s559_pcm_checksum(&mixed), peak));
}
}
Ok((0, 0, 0))
}
/// Fail-closed, replay-idempotent lab audio operation service.
///
/// `step` must equal the number of already published receipts. A smaller
/// `step` replays: the identical operation returns `OperationRetained` with
/// the stored receipt; a divergent one is `PublishedStateDrift`. A larger
/// `step` is `StepOutOfOrder`.
pub fn service_s559_model_audio_route_operation(
state: &mut G8lS559AudioRouteState,
step: usize,
op: &G8lS559AudioOp,
) -> Result<G8lS559AudioOutcome, G8lS559AudioError> {
let published = state.receipts.len();
if step < published {
let receipt = state.receipts[step];
if receipt.op_kind != op.kind() || receipt.op_digest != op.digest() {
return Err(G8lS559AudioError::PublishedStateDrift);
}
return Ok(G8lS559AudioOutcome::OperationRetained(receipt));
}
if step > published {
return Err(G8lS559AudioError::StepOutOfOrder);
}
if published >= S559_MAX_OPERATIONS {
return Err(G8lS559AudioError::LedgerFull);
}
let (mixed_frames, output_checksum, output_peak) = apply_op(state, op)?;
let receipt = state.snapshot(step, op, mixed_frames, output_checksum, output_peak);
state.receipts.push(receipt);
Ok(G8lS559AudioOutcome::OperationPublished(receipt))
}
snippet sha256: 941d47dbd1d5…file sha256: 941d47dbd1d5…
02 · Doğrulayan test kodu
Operations komutuna bağlı focused test
tam dosyaL1–L860
simulation/tests/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model.rs::S559 r1 audio route pcm capability model focused tests
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model::*;
use std::collections::BTreeSet;
const SOURCE: &str = include_str!(
"../../kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model.rs"
);
const MAIN: &str = include_str!("../../kernel/src/main.rs");
const SIMULATION_LIB: &str = include_str!("../src/lib.rs");
type State = G8lS559AudioRouteState;
type Op = G8lS559AudioOp;
type Endpoint = G8lS559AudioEndpoint;
type Rights = G8lS559AudioRights;
type Format = G8lS559PcmFormat;
type Outcome = G8lS559AudioOutcome;
type Error = G8lS559AudioError;
fn step(state: &mut State, op: &Op) -> Result<Outcome, Error> {
let step = state.receipts().len();
service_s559_model_audio_route_operation(state, step, op)
}
fn publish(state: &mut State, op: &Op) -> G8lS559AudioReceipt {
match step(state, op) {
Ok(Outcome::OperationPublished(receipt)) => receipt,
other => panic!("expected publication for {op:?}, got {other:?}"),
}
}
fn ramp(samples: usize, base: i16, slope: i16) -> Vec<i16> {
(0..samples)
.map(|index| base.wrapping_add(slope.wrapping_mul(index as i16)))
.collect()
}
fn frame(samples: Vec<i16>) -> Op {
Op::PushFrame {
format: Format::wideband(),
samples,
}
}
fn downlink_state(rights: u8) -> State {
let mut state = State::new();
publish(&mut state, &Op::Grant { rights });
publish(
&mut state,
&Op::SetFormat {
format: Format::wideband(),
},
);
publish(
&mut state,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Earpiece,
},
);
state
}
#[test]
fn sequence_scope_and_nonpromotion_are_exact() {
assert_eq!(S559_SEQUENCE, 559);
assert_eq!(S559_EXPECTED_PREDECESSOR, 558);
assert_eq!(S559_R1_STAGE, 3);
assert_eq!(S559_R1_RANGE_FIRST, 536);
assert_eq!(S559_R1_RANGE_LAST, 568);
assert_eq!(S559_ENDPOINT_COUNT, 5);
assert_eq!(S559_ALLOWED_ROUTE_COUNT, 5);
assert_eq!(S559_WIDEBAND_SAMPLE_RATE_HZ, 16_000);
assert_eq!(S559_NARROWBAND_SAMPLE_RATE_HZ, 8_000);
assert_eq!(S559_BITS_PER_SAMPLE, 16);
assert_eq!(S559_CHANNELS, 1);
assert_eq!(S559_FRAME_DURATION_MS, 20);
assert_eq!(S559_WIDEBAND_FRAME_SAMPLES, 320);
assert_eq!(S559_NARROWBAND_FRAME_SAMPLES, 160);
assert_eq!(S559_RING_CAPACITY_FRAMES, 16);
assert_eq!(S559_GAIN_MIN_DB, -60);
assert_eq!(S559_GAIN_MAX_DB, 12);
assert_eq!(S559_GAIN_STEP_DB, 3);
assert_eq!(S559_GAIN_TABLE_LEN, 25);
assert_eq!(S559_GAIN_UNITY_Q10, 1024);
assert_eq!(S559_MAX_MIX_DEPTH, 4);
assert_eq!(S559_MAX_OPERATIONS, 64);
assert_eq!(S559_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS, 0);
assert_eq!(S559_PHYSICAL_OBSERVATIONS, 0);
assert_eq!(S559_PHYSICAL_OR_DEVICE_OPERATIONS, 0);
assert_eq!(S559_SD_WRITES, 0);
assert_eq!(S559_UART_OPENS, 0);
assert_eq!(S559_POWER_TRANSITIONS, 0);
assert_eq!(S559_NEW_IMMUTABLE_RAW_CAPTURES, 0);
assert!(S559_S540_PHYSICAL_VERDICT_RETAINED_RED);
assert!(S559_S543_PHYSICAL_VERDICT_RETAINED_RED);
assert!(!S559_AUTOMATIC_PROMOTION);
assert!(!S559_BOOT_TO_UI_PHYSICALLY_OBSERVED);
assert!(!S559_HARDWARE_PRESENT);
assert!(!S559_R1_ACCEPTANCE_COMPLETE);
assert!(!RUNBOOK_EXECUTED_IN_S559);
}
#[test]
fn module_is_registered_in_kernel_and_simulation() {
let module = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model";
assert!(MAIN.contains(&format!("mod {module};")));
assert!(SIMULATION_LIB.contains(&format!("pub mod {module};")));
}
#[test]
fn source_has_no_device_execution_or_uart_emission_surface() {
for forbidden in [
"unsafe",
"asm!",
"write_volatile",
"crate::uart",
"crate::arch",
"#[no_mangle]",
"spin::",
"std::",
"crate::kprintln!",
] {
assert!(!SOURCE.contains(forbidden), "forbidden token: {forbidden}");
}
assert!(SOURCE.contains("performs no device operation"));
assert!(SOURCE.contains("does not rerun S540 or S543"));
assert!(SOURCE.contains("S559_HARDWARE_PRESENT: bool = false"));
assert!(SOURCE.contains("RUNBOOK_EXECUTED_IN_S559: bool = false"));
}
#[test]
fn diagnostic_codes_are_nonzero_and_unique() {
let errors = [
Error::StepOutOfOrder,
Error::LedgerFull,
Error::PublishedStateDrift,
Error::InvalidRightsBits,
Error::EmptyRightsGrant,
Error::EmptyRightsRevoke,
Error::RightsAlreadyGranted,
Error::NoRightsGranted,
Error::RevokeNotSubset,
Error::RightsMissingRoute,
Error::RightsMissingPlayback,
Error::RightsMissingCapture,
Error::InvalidRoute,
Error::RouteNotSelected,
Error::InvalidSampleRate,
Error::InvalidBitsPerSample,
Error::InvalidChannels,
Error::InvalidFrameDuration,
Error::FormatNotSet,
Error::FormatMismatch,
Error::FrameLengthMismatch,
Error::RingOverrun,
Error::RingUnderrun,
Error::RingNotEmpty,
Error::RingSlotCorrupt,
Error::InvalidMixDepth,
Error::GainStepZero,
Error::ArithmeticOverflow,
];
let codes: BTreeSet<u64> = errors.iter().map(|error| error.diagnostic_code()).collect();
assert_eq!(codes.len(), errors.len());
assert_eq!(errors.len(), 28);
assert!(!codes.contains(&0));
}
#[test]
fn exact_replay_retains_the_same_receipt() {
let mut state = downlink_state(Rights::FULL.as_u8());
let push = frame(ramp(320, 100, 3));
let receipt = publish(&mut state, &push);
assert_eq!(receipt.step, 3);
assert_eq!(
service_s559_model_audio_route_operation(&mut state, 3, &push),
Ok(Outcome::OperationRetained(receipt))
);
assert_eq!(
service_s559_model_audio_route_operation(
&mut state,
0,
&Op::Grant {
rights: Rights::FULL.as_u8()
}
),
Ok(Outcome::OperationRetained(state.receipts()[0]))
);
assert_eq!(state.receipts().len(), 4);
assert_eq!(state.ring().len(), 1);
}
#[test]
fn divergent_input_after_publication_fails_closed() {
let mut state = downlink_state(Rights::FULL.as_u8());
publish(&mut state, &frame(ramp(320, 100, 3)));
assert_eq!(
service_s559_model_audio_route_operation(&mut state, 3, &frame(ramp(320, 101, 3))),
Err(Error::PublishedStateDrift)
);
assert_eq!(
service_s559_model_audio_route_operation(&mut state, 3, &Op::SetMute { muted: true }),
Err(Error::PublishedStateDrift)
);
assert_eq!(
service_s559_model_audio_route_operation(
&mut state,
2,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Speaker
}
),
Err(Error::PublishedStateDrift)
);
assert_eq!(state.receipts().len(), 4);
assert_eq!(state.route(), Some((Endpoint::ModemDownlink, Endpoint::Earpiece)));
assert!(!state.muted());
}
#[test]
fn rights_bitset_behaves_like_framebuffer_rights() {
assert_eq!(Rights::PLAYBACK.as_u8(), 0b001);
assert_eq!(Rights::CAPTURE.as_u8(), 0b010);
assert_eq!(Rights::ROUTE.as_u8(), 0b100);
assert_eq!(Rights::FULL.as_u8(), 0b111);
assert!(Rights::empty().is_empty());
let playback_route = Rights::PLAYBACK | Rights::ROUTE;
assert!(playback_route.contains(Rights::PLAYBACK));
assert!(playback_route.contains(Rights::ROUTE));
assert!(!playback_route.contains(Rights::CAPTURE));
assert!(playback_route.intersects(Rights::ROUTE));
assert!(!playback_route.intersects(Rights::CAPTURE));
assert_eq!(playback_route.intersect(Rights::FULL), playback_route);
assert_eq!(playback_route.intersect(Rights::CAPTURE), Rights::empty());
assert_eq!(playback_route.remove(Rights::ROUTE), Rights::PLAYBACK);
assert_eq!(Rights::from_bits(0b101), Ok(playback_route));
for bits in [0b1000u8, 0b1111, 0x80, 0xff] {
assert_eq!(Rights::from_bits(bits), Err(Error::InvalidRightsBits));
}
}
#[test]
fn routing_matrix_allows_exactly_five_pairs() {
let mut allowed = Vec::new();
for source in Endpoint::ALL {
for sink in Endpoint::ALL {
if s559_route_is_allowed(source, sink) {
allowed.push((source, sink));
assert!(s559_route_kind(source, sink).is_some());
} else {
assert_eq!(s559_route_kind(source, sink), None);
}
if source == sink {
assert!(!s559_route_is_allowed(source, sink), "self loop {source:?}");
}
}
}
assert_eq!(allowed.len(), S559_ALLOWED_ROUTE_COUNT);
assert_eq!(
allowed,
vec![
(Endpoint::Headset, Endpoint::ModemUplink),
(Endpoint::ModemDownlink, Endpoint::Earpiece),
(Endpoint::ModemDownlink, Endpoint::Speaker),
(Endpoint::ModemDownlink, Endpoint::Headset),
(Endpoint::ModemDownlink, Endpoint::ModemUplink),
]
);
assert_eq!(
s559_route_kind(Endpoint::ModemDownlink, Endpoint::Speaker),
Some(G8lS559RouteKind::Downlink)
);
assert_eq!(
s559_route_kind(Endpoint::Headset, Endpoint::ModemUplink),
Some(G8lS559RouteKind::Uplink)
);
assert_eq!(
s559_route_kind(Endpoint::ModemDownlink, Endpoint::ModemUplink),
Some(G8lS559RouteKind::Loopback)
);
assert_eq!(G8lS559RouteKind::Downlink.required_rights(), Rights::PLAYBACK);
assert_eq!(G8lS559RouteKind::Uplink.required_rights(), Rights::CAPTURE);
assert_eq!(
G8lS559RouteKind::Loopback.required_rights(),
Rights::PLAYBACK | Rights::CAPTURE
);
for (index, endpoint) in Endpoint::ALL.iter().enumerate() {
assert_eq!(endpoint.index(), index);
}
}
#[test]
fn pcm_format_descriptor_yields_320_and_160_samples_and_rejects_others() {
assert_eq!(Format::wideband().frame_samples(), Ok(320));
assert_eq!(Format::narrowband().frame_samples(), Ok(160));
assert_eq!(Format::wideband().frame_bytes(), Ok(640));
assert_eq!(Format::narrowband().frame_bytes(), Ok(320));
let mut rate = Format::wideband();
rate.sample_rate_hz = 44_100;
assert_eq!(rate.frame_samples(), Err(Error::InvalidSampleRate));
let mut bits = Format::wideband();
bits.bits_per_sample = 8;
assert_eq!(bits.validate(), Err(Error::InvalidBitsPerSample));
let mut channels = Format::narrowband();
channels.channels = 2;
assert_eq!(channels.validate(), Err(Error::InvalidChannels));
let mut duration = Format::narrowband();
duration.frame_duration_ms = 10;
assert_eq!(duration.validate(), Err(Error::InvalidFrameDuration));
let mut zero = Format::wideband();
zero.sample_rate_hz = 0;
assert_eq!(zero.frame_samples(), Err(Error::InvalidSampleRate));
}
#[test]
fn downlink_pipeline_publishes_deterministic_mixed_checksum() {
let mut state = downlink_state(Rights::FULL.as_u8());
let samples = ramp(320, -1000, 7);
let push = publish(&mut state, &frame(samples.clone()));
assert_eq!(push.op_kind, G8lS559OpKind::PushFrame);
assert_eq!(push.ring_len_after, 1);
assert_eq!(push.route_kind_after, Some(G8lS559RouteKind::Downlink));
assert_eq!(push.sample_rate_hz_after, 16_000);
assert_eq!(push.frame_samples_after, 320);
assert_eq!(push.output_checksum, 0);
let pop = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(pop.mixed_frames, 1);
assert_eq!(pop.ring_len_after, 0);
assert_eq!(pop.gain_db_after, 0);
assert_eq!(pop.output_checksum, s559_pcm_checksum(&samples));
assert_eq!(pop.output_peak, 1233);
assert_eq!(pop.underruns_after, 0);
assert_eq!(pop.overruns_after, 0);
assert!(!pop.hardware_present);
assert_eq!(pop.physical_observations, 0);
assert!(!pop.runbook_executed);
let mut replay = downlink_state(Rights::FULL.as_u8());
publish(&mut replay, &frame(samples));
let again = publish(&mut replay, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(again, pop);
assert_eq!(s559_pcm_checksum(&[]), s559_pcm_checksum(&[]));
assert_ne!(s559_pcm_checksum(&[1, 2]), s559_pcm_checksum(&[2, 1]));
assert_ne!(s559_pcm_checksum(&[0]), s559_pcm_checksum(&[0, 0]));
}
#[test]
fn missing_rights_fail_closed_before_any_mutation() {
let mut state = State::new();
assert_eq!(
step(
&mut state,
&Op::SetFormat {
format: Format::wideband()
}
),
Err(Error::NoRightsGranted)
);
publish(
&mut state,
&Op::Grant {
rights: Rights::PLAYBACK.as_u8(),
},
);
assert_eq!(
step(
&mut state,
&Op::SetFormat {
format: Format::wideband()
}
),
Err(Error::RightsMissingRoute)
);
assert_eq!(state.format(), None);
let mut capture_only = State::new();
publish(
&mut capture_only,
&Op::Grant {
rights: (Rights::CAPTURE | Rights::ROUTE).as_u8(),
},
);
publish(
&mut capture_only,
&Op::SetFormat {
format: Format::narrowband(),
},
);
assert_eq!(
step(
&mut capture_only,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Earpiece
}
),
Err(Error::RightsMissingPlayback)
);
assert_eq!(
step(
&mut capture_only,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::ModemUplink
}
),
Err(Error::RightsMissingPlayback)
);
assert_eq!(step(&mut capture_only, &Op::SetGain { steps: 1 }), Err(Error::RightsMissingPlayback));
assert_eq!(
step(&mut capture_only, &Op::SetMute { muted: true }),
Err(Error::RightsMissingPlayback)
);
let mut playback_only = State::new();
publish(
&mut playback_only,
&Op::Grant {
rights: (Rights::PLAYBACK | Rights::ROUTE).as_u8(),
},
);
publish(
&mut playback_only,
&Op::SetFormat {
format: Format::narrowband(),
},
);
assert_eq!(
step(
&mut playback_only,
&Op::SelectRoute {
source: Endpoint::Headset,
sink: Endpoint::ModemUplink
}
),
Err(Error::RightsMissingCapture)
);
assert_eq!(playback_only.route(), None);
assert_eq!(capture_only.receipts().len(), 2);
}
#[test]
fn invalid_route_and_route_preconditions_fail_closed() {
let mut state = State::new();
publish(
&mut state,
&Op::Grant {
rights: Rights::FULL.as_u8(),
},
);
assert_eq!(
step(
&mut state,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Earpiece
}
),
Err(Error::FormatNotSet)
);
for (source, sink) in [
(Endpoint::Earpiece, Endpoint::ModemUplink),
(Endpoint::Speaker, Endpoint::Speaker),
(Endpoint::ModemUplink, Endpoint::ModemDownlink),
(Endpoint::Headset, Endpoint::Earpiece),
(Endpoint::ModemDownlink, Endpoint::ModemDownlink),
] {
assert_eq!(
step(&mut state, &Op::SelectRoute { source, sink }),
Err(Error::InvalidRoute),
"{source:?} -> {sink:?}"
);
}
assert_eq!(
step(&mut state, &frame(ramp(320, 0, 1))),
Err(Error::RouteNotSelected)
);
assert_eq!(
step(&mut state, &Op::PopMixedFrame { mix_depth: 1 }),
Err(Error::RouteNotSelected)
);
assert_eq!(state.route(), None);
assert_eq!(state.ring().underruns(), 0);
assert_eq!(state.receipts().len(), 1);
}
#[test]
fn format_mismatch_and_frame_length_fail_closed() {
let mut state = downlink_state(Rights::FULL.as_u8());
assert_eq!(
step(
&mut state,
&Op::PushFrame {
format: Format::narrowband(),
samples: ramp(160, 0, 1)
}
),
Err(Error::FormatMismatch)
);
assert_eq!(step(&mut state, &frame(ramp(160, 0, 1))), Err(Error::FrameLengthMismatch));
assert_eq!(step(&mut state, &frame(ramp(321, 0, 1))), Err(Error::FrameLengthMismatch));
assert_eq!(step(&mut state, &frame(Vec::new())), Err(Error::FrameLengthMismatch));
let mut invalid = Format::wideband();
invalid.bits_per_sample = 24;
assert_eq!(
step(&mut state, &Op::SetFormat { format: invalid }),
Err(Error::InvalidBitsPerSample)
);
assert_eq!(state.ring().len(), 0);
assert_eq!(state.ring().overruns(), 0);
publish(&mut state, &frame(ramp(320, 0, 1)));
assert_eq!(
step(
&mut state,
&Op::SetFormat {
format: Format::narrowband()
}
),
Err(Error::RingNotEmpty)
);
assert_eq!(
step(
&mut state,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Speaker
}
),
Err(Error::RingNotEmpty)
);
assert_eq!(state.format(), Some(Format::wideband()));
assert_eq!(state.route(), Some((Endpoint::ModemDownlink, Endpoint::Earpiece)));
}
#[test]
fn ring_overrun_and_underrun_are_counted_and_bounded() {
let mut state = downlink_state(Rights::FULL.as_u8());
for index in 0..S559_RING_CAPACITY_FRAMES {
let receipt = publish(&mut state, &frame(ramp(320, index as i16, 1)));
assert_eq!(receipt.ring_len_after, index + 1);
}
assert_eq!(step(&mut state, &frame(ramp(320, 99, 1))), Err(Error::RingOverrun));
assert_eq!(step(&mut state, &frame(ramp(320, 98, 1))), Err(Error::RingOverrun));
assert_eq!(state.ring().overruns(), 2);
assert_eq!(state.ring().len(), 16);
for index in 0..S559_RING_CAPACITY_FRAMES {
let receipt = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(receipt.output_checksum, s559_pcm_checksum(&ramp(320, index as i16, 1)));
assert_eq!(receipt.overruns_after, 2);
}
assert_eq!(
step(&mut state, &Op::PopMixedFrame { mix_depth: 1 }),
Err(Error::RingUnderrun)
);
publish(&mut state, &frame(ramp(320, 5, 1)));
assert_eq!(
step(&mut state, &Op::PopMixedFrame { mix_depth: 2 }),
Err(Error::RingUnderrun)
);
assert_eq!(state.ring().underruns(), 2);
assert_eq!(state.ring().len(), 1);
let receipt = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(receipt.underruns_after, 2);
assert_eq!(receipt.ring_len_after, 0);
}
#[test]
fn gain_steps_clamp_at_bounds_and_mute_zeroes_output() {
let unity = G8lS559Gain::unity();
assert_eq!(unity.db(), 0);
assert_eq!(unity.multiplier_q10(), 1024);
assert_eq!(unity.stepped(1).db(), 3);
assert_eq!(unity.stepped(-1).db(), -3);
assert_eq!(unity.stepped(4).db(), 12);
assert_eq!(unity.stepped(5).db(), 12);
assert_eq!(unity.stepped(127).db(), 12);
assert_eq!(unity.stepped(-20).db(), -60);
assert_eq!(unity.stepped(-128).db(), -60);
assert_eq!(unity.stepped(-128).multiplier_q10(), 1);
assert_eq!(unity.stepped(127).multiplier_q10(), 4077);
assert_eq!(unity.stepped(-2).apply(1024), 513);
assert_eq!(unity.stepped(4).apply(20_000), i16::MAX);
assert_eq!(unity.stepped(4).apply(-20_000), i16::MIN);
assert_eq!(unity.stepped(2).apply(1000), 1995);
assert_eq!(S559_GAIN_TABLE_Q10[20], 1024);
assert!(S559_GAIN_TABLE_Q10.windows(2).all(|pair| pair[0] <= pair[1]));
let mut state = downlink_state(Rights::FULL.as_u8());
assert_eq!(step(&mut state, &Op::SetGain { steps: 0 }), Err(Error::GainStepZero));
let louder = publish(&mut state, &Op::SetGain { steps: 2 });
assert_eq!(louder.gain_db_after, 6);
publish(&mut state, &frame(vec![1000; 320]));
let pop = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(pop.output_peak, 1995);
assert_eq!(pop.output_checksum, s559_pcm_checksum(&[1995; 320]));
let clamped = publish(&mut state, &Op::SetGain { steps: 100 });
assert_eq!(clamped.gain_db_after, 12);
publish(&mut state, &frame(vec![20_000; 320]));
let saturated = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(saturated.output_peak, 32_767);
let muted = publish(&mut state, &Op::SetMute { muted: true });
assert!(muted.muted_after);
publish(&mut state, &frame(ramp(320, 500, 9)));
let silent = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(silent.output_peak, 0);
assert_eq!(silent.output_checksum, s559_pcm_checksum(&[0; 320]));
assert_eq!(silent.gain_db_after, 12);
let floor = publish(&mut state, &Op::SetGain { steps: -128 });
assert_eq!(floor.gain_db_after, -60);
}
#[test]
fn mixing_saturates_and_invalid_mix_depth_is_rejected() {
let mut state = downlink_state(Rights::FULL.as_u8());
for _ in 0..4 {
publish(&mut state, &frame(vec![10_000; 320]));
}
assert_eq!(
step(&mut state, &Op::PopMixedFrame { mix_depth: 0 }),
Err(Error::InvalidMixDepth)
);
assert_eq!(
step(&mut state, &Op::PopMixedFrame { mix_depth: 5 }),
Err(Error::InvalidMixDepth)
);
assert_eq!(state.ring().underruns(), 0);
let mixed = publish(&mut state, &Op::PopMixedFrame { mix_depth: 4 });
assert_eq!(mixed.mixed_frames, 4);
assert_eq!(mixed.output_peak, 32_767);
assert_eq!(mixed.output_checksum, s559_pcm_checksum(&[32_767; 320]));
assert_eq!(mixed.ring_len_after, 0);
publish(&mut state, &frame(vec![-30_000; 320]));
publish(&mut state, &frame(vec![-30_000; 320]));
publish(&mut state, &frame(vec![100; 320]));
let negative = publish(&mut state, &Op::PopMixedFrame { mix_depth: 2 });
assert_eq!(negative.output_peak, 32_768);
assert_eq!(negative.output_checksum, s559_pcm_checksum(&[i16::MIN; 320]));
assert_eq!(negative.ring_len_after, 1);
let last = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(last.output_peak, 100);
}
#[test]
fn narrowband_uplink_and_loopback_routes_require_capture_rights() {
let mut state = State::new();
publish(
&mut state,
&Op::Grant {
rights: Rights::FULL.as_u8(),
},
);
publish(
&mut state,
&Op::SetFormat {
format: Format::narrowband(),
},
);
let uplink = publish(
&mut state,
&Op::SelectRoute {
source: Endpoint::Headset,
sink: Endpoint::ModemUplink,
},
);
assert_eq!(uplink.route_kind_after, Some(G8lS559RouteKind::Uplink));
assert_eq!(uplink.frame_samples_after, 160);
let samples = ramp(160, 40, -2);
publish(
&mut state,
&Op::PushFrame {
format: Format::narrowband(),
samples: samples.clone(),
},
);
let pop = publish(&mut state, &Op::PopMixedFrame { mix_depth: 1 });
assert_eq!(pop.output_checksum, s559_pcm_checksum(&samples));
assert_eq!(pop.output_peak, 278);
let loopback = publish(
&mut state,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::ModemUplink,
},
);
assert_eq!(loopback.route_kind_after, Some(G8lS559RouteKind::Loopback));
publish(
&mut state,
&Op::Revoke {
rights: Rights::CAPTURE.as_u8(),
},
);
assert_eq!(state.route(), None);
assert_eq!(state.rights(), Some(Rights::PLAYBACK | Rights::ROUTE));
assert_eq!(
step(
&mut state,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::ModemUplink
}
),
Err(Error::RightsMissingCapture)
);
}
#[test]
fn revoking_route_right_closes_route_and_flushes_ring() {
let mut state = downlink_state(Rights::FULL.as_u8());
publish(&mut state, &frame(ramp(320, 1, 1)));
publish(&mut state, &frame(ramp(320, 2, 1)));
assert_eq!(state.ring().len(), 2);
let revoked = publish(
&mut state,
&Op::Revoke {
rights: Rights::ROUTE.as_u8(),
},
);
assert_eq!(revoked.rights_after, (Rights::PLAYBACK | Rights::CAPTURE).as_u8());
assert_eq!(revoked.route_after, None);
assert_eq!(revoked.route_kind_after, None);
assert_eq!(revoked.ring_len_after, 0);
assert_eq!(state.route(), None);
assert!(state.ring().is_empty());
assert_eq!(step(&mut state, &frame(ramp(320, 3, 1))), Err(Error::RouteNotSelected));
assert_eq!(
step(
&mut state,
&Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Earpiece
}
),
Err(Error::RightsMissingRoute)
);
let all = publish(
&mut state,
&Op::Revoke {
rights: (Rights::PLAYBACK | Rights::CAPTURE).as_u8(),
},
);
assert_eq!(all.rights_after, 0);
assert_eq!(state.rights(), None);
assert_eq!(step(&mut state, &Op::SetMute { muted: true }), Err(Error::NoRightsGranted));
let regrant = publish(
&mut state,
&Op::Grant {
rights: Rights::PLAYBACK.as_u8(),
},
);
assert_eq!(regrant.rights_after, Rights::PLAYBACK.as_u8());
}
#[test]
fn grant_and_revoke_malformed_inputs_fail_closed() {
let mut state = State::new();
assert_eq!(step(&mut state, &Op::Grant { rights: 0 }), Err(Error::EmptyRightsGrant));
assert_eq!(step(&mut state, &Op::Grant { rights: 0b1000 }), Err(Error::InvalidRightsBits));
assert_eq!(step(&mut state, &Op::Revoke { rights: 0b001 }), Err(Error::NoRightsGranted));
assert_eq!(state.rights(), None);
publish(
&mut state,
&Op::Grant {
rights: Rights::PLAYBACK.as_u8(),
},
);
assert_eq!(
step(
&mut state,
&Op::Grant {
rights: Rights::FULL.as_u8()
}
),
Err(Error::RightsAlreadyGranted)
);
assert_eq!(step(&mut state, &Op::Revoke { rights: 0 }), Err(Error::EmptyRightsRevoke));
assert_eq!(step(&mut state, &Op::Revoke { rights: 0xf0 }), Err(Error::InvalidRightsBits));
assert_eq!(
step(
&mut state,
&Op::Revoke {
rights: Rights::ROUTE.as_u8()
}
),
Err(Error::RevokeNotSubset)
);
assert_eq!(state.rights(), Some(Rights::PLAYBACK));
assert_eq!(state.receipts().len(), 1);
}
#[test]
fn step_out_of_order_and_ledger_full_fail_closed() {
let mut state = downlink_state(Rights::FULL.as_u8());
assert_eq!(
service_s559_model_audio_route_operation(&mut state, 4, &Op::SetMute { muted: true }),
Err(Error::StepOutOfOrder)
);
assert_eq!(
service_s559_model_audio_route_operation(&mut state, usize::MAX, &Op::SetMute { muted: true }),
Err(Error::StepOutOfOrder)
);
assert!(!state.muted());
let mut toggle = false;
while state.receipts().len() < S559_MAX_OPERATIONS {
toggle = !toggle;
publish(&mut state, &Op::SetMute { muted: toggle });
}
assert_eq!(state.receipts().len(), 64);
assert_eq!(
step(&mut state, &Op::SetMute { muted: !toggle }),
Err(Error::LedgerFull)
);
assert_eq!(state.muted(), toggle);
let last = state.receipts()[63];
assert_eq!(
service_s559_model_audio_route_operation(&mut state, 63, &Op::SetMute { muted: toggle }),
Ok(Outcome::OperationRetained(last))
);
}
#[test]
fn op_digest_is_deterministic_and_distinguishes_operations() {
let a = frame(ramp(320, 1, 1));
let b = frame(ramp(320, 1, 1));
let c = frame(ramp(320, 2, 1));
assert_eq!(a.digest(), b.digest());
assert_ne!(a.digest(), c.digest());
let digests: BTreeSet<u64> = [
Op::Grant { rights: 1 },
Op::Revoke { rights: 1 },
Op::SetFormat {
format: Format::wideband(),
},
Op::SetFormat {
format: Format::narrowband(),
},
Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Earpiece,
},
Op::SelectRoute {
source: Endpoint::ModemDownlink,
sink: Endpoint::Speaker,
},
Op::SetGain { steps: 1 },
Op::SetGain { steps: -1 },
Op::SetMute { muted: true },
Op::SetMute { muted: false },
Op::PopMixedFrame { mix_depth: 1 },
Op::PopMixedFrame { mix_depth: 2 },
a,
c,
]
.iter()
.map(Op::digest)
.collect();
assert_eq!(digests.len(), 14);
let state = State::default();
assert_eq!(state.rights(), None);
assert_eq!(state.gain(), G8lS559Gain::unity());
assert!(state.receipts().is_empty());
assert_eq!(G8lS559FrameRing::default().len(), 0);
}
snippet sha256: 188f5dea23cb…file sha256: 188f5dea23cb…
03 · Kapı kimlik kaydı
Operations sıra, kimlik ve başlık bağı
tam Operations kaydıL2365–L2423
website/src/lib/operations.ts::g8l-s559-r1-audio-route-pcm-capability-model
{
id: "g8l-s559-r1-audio-route-pcm-capability-model",
date: "2026-08-30",
sequence: 559,
status: "passed",
umbrella_status: "partial",
title: "S559 · R1 ses: laboratuvar ses route ve PCM capability modeli",
summary:
"S559 kaynak/host model kapısı PASS'tir: R1 3. aşama (modem, veri, arama ve ses) için laboratuvar ses yolu saf bir model olarak yazıldı. Model beş ses ucunu (Earpiece, Speaker, Headset, ModemUplink, ModemDownlink) 25 çiftten yalnız 5'ine izin veren sabit routing matrisiyle, 16 kHz/8 kHz 16-bit mono 20 ms (320/160 örnek) PCM format tanımlayıcısını, underrun/overrun sayaçlı 16 frame'lik ring buffer'ı, -60..+12 dB aralığına clamp edilen 3 dB adımlı gain tablosunu, mute'u ve FramebufferRights biçiminde {PLAYBACK, CAPTURE, ROUTE} capability bitlerini grant/revoke daraltmasıyla kapsar; eksik hak, geçersiz route, format/frame uyumsuzluğu ve taşmalar fail-closed reddedilir ve mixed çıktı deterministik FNV-1a checksum ile mühürlenir. Focused 21/21 PASS'tir. S540 ve S543 fiziksel raw/verdict değişmez RED kalır; hiçbir codec, hoparlör, mikrofon, modem PCM hattı, UART, panel veya board yoktur; physical observation=0, SD/UART/power/new-raw=0/0/0/0, Boot-to-UI=false ve R1 acceptance=false'dur. RUNBOOK_EXECUTED_IN_S559=NO. S560 host-only modem subsystem capability supervision modeli kapısıdır.",
evidence: [
"S559, S558'den ayrı saf model kernel modülü, 21-test focused binary, proof, status manifest, Operations kaydı ve complete Code kartına sahiptir; production callsite yoktur ve modül hiçbir boot, IRQ, scheduler veya driver yoluna bağlı değildir.",
"Dar S559 source/host status=PASS; R1 umbrella=PARTIAL ve S540/S543 physical gate status=RED olarak ayrı tutulur.",
"Routing matrisi [source][sink] 25 çiftten exact 5'ine izin verir: ModemDownlink→Earpiece/Speaker/Headset (Downlink), Headset→ModemUplink (Uplink) ve laboratuvar loopback'i ModemDownlink→ModemUplink; self-loop dahil diğer her çift InvalidRoute ile reddedilir.",
"Capability bitleri FramebufferRights biçimindedir: PLAYBACK=0b001, CAPTURE=0b010, ROUTE=0b100, FULL=0b111; from_bits FULL dışındaki her biti InvalidRightsBits ile reddeder, Grant yalnız hak yokken bir kez kabul edilir ve Revoke yalnız tutulan bitleri daraltır (RevokeNotSubset).",
"Route seçimi ROUTE hakkı ister; Downlink PLAYBACK, Uplink CAPTURE, Loopback PLAYBACK+CAPTURE ister ve açık route'un bağımlı olduğu bir hakkın revoke edilmesi route'u kapatıp ring'i flush eder.",
"PCM format tanımlayıcısı yalnız 16000/8000 Hz, 16-bit, mono ve 20 ms'yi doğrular; frame örnek sayısı checked çarpımla 320/160 (640/320 bayt) türetilir ve diğer her değer ayrı diagnostic koduyla fail-closed döner.",
"Ring buffer kapasitesi 16 frame'dir: dolu ring'e push frame'i düşürür, overrun sayacını artırır ve RingOverrun döner; kuyruktakinden fazla frame isteyen pop underrun sayacını artırır ve RingUnderrun döner; sayaçlar saturating'dir.",
"Gain 3 dB adımlarla -60..+12 dB aralığına clamp edilir ve 25 girişli sabit Q10 tablosu (unity=1024) üzerinden 16-bit saturasyonla uygulanır; steps=0 GainStepZero'dur ve mute çıktıyı sıfırlar.",
"PopMixedFrame 1..4 frame'i saturating toplama ile miksler, gain ve mute uygular; receipt tepe genliği ve örnek sayısı + little-endian baytlar üzerinden deterministik FNV-1a-64 checksum'ı (s559_pcm_checksum) taşır ve focused test çıktıyı bağımsız kurulmuş beklenen vektörlerle byte-exact sabitler.",
"Format veya frame-length uyumsuzluğu (FormatMismatch/FrameLengthMismatch), format/route değişikliği kuyruk doluyken (RingNotEmpty), formatsız route seçimi (FormatNotSet) ve route'suz push/pop (RouteNotSelected) fail-closed reddedilir.",
"Ledger en fazla 64 receipt tutar; sıra dışı adım StepOutOfOrder, dolu ledger LedgerFull verir; exact replay OperationRetained ile aynı receipt'i döndürür ve yayınlanmış adımda divergent operasyon PublishedStateDrift ile reddedilir.",
"28 hata kodu sıfırdan farklı ve tekildir; kaynakta unsafe, asm!, write_volatile, crate::uart, crate::arch, #[no_mangle] ve spin:: yüzeyi yoktur.",
"Focused target 1 grup / 21 passed / 0 failed / 0 ignored / 0 filtered verdi.",
"Implementation 30504 B / 941d47dbd1d5c1fa5a7a590948af43479408386b40a5dcef2501a71967a5b03d; focused test 29580 B / 188f5dea23cbb9cb927ba3050ba0e9ef89e023f73b2ff4d8659b5797c6c14bf5 SHA-256'dır.",
"Proof 5902 B'dir.",
"S540 immutable raw 20525 B ve S543 immutable raw 20509 B fiziksel RED olarak byte-exact korunur; automatic promotion=false ve rerun=false'dur.",
"S559 sırasında codec, hoparlör, mikrofon, modem PCM hattı, SD write/read-back/eject, UART open/capture, power transition, fiziksel koşu veya yeni immutable raw üretimi yapılmadı.",
"RUNBOOK_EXECUTED_IN_S559=NO; supported-profile runtime observations=0, physical observations=0, hardware present=false, Boot-to-UI physically observed=false ve R1 acceptance=false'dur.",
"S560 yalnız host üzerinde modem subsystem capability supervision modelini yazacaktır; aygıt veya fiziksel koşu yetkisi değildir.",
],
commands: [
"CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model -- --test-threads=1",
],
terminalSessions: [
{
id: "s559-focused",
title: "S559 laboratuvar ses route ve PCM capability modeli focused",
commandLines: [
"CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model -- --test-threads=1",
],
outputLines: [
"test result: ok. 21 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s",
"S559 focused=1 group / 21 passed / 0 failed",
"hardware=none physical=0 runbook=NO",
],
exitCode: 0,
outputMode: "complete",
},
],
terminalSessionsNote:
"S559 kaynak/host model PASS'tir; supported-profile runtime, ses donanımı veya fiziksel PASS değildir. S540 ve S543 RED raw ve kararları değişmez.",
limitations: [
"S559 saf bir kaynak/host modelidir; hiçbir donanım/panel/modem/board gözlemi yoktur ve gerçek bir codec, hoparlör, mikrofon veya modem PCM hattı üzerinde hiçbir ses yolu gözlenmemiştir.",
"Modülün production callsite'ı yoktur; gerçek I2S/PCM sürücüsü, DMA, kesme ve zamanlama davranışı bu kapının dışındadır.",
"S540 ve S543 fiziksel RED immutable kalır; S546 fiziksel koşusunun kararı bu kapıda varsayılmaz.",
"BOOT_TO_UI_READY gerçek UART'ta görülmedi; Boot-to-UI ve R1 acceptance false kalır.",
"S560 host-only modem subsystem capability supervision modelidir; yeni SD/UART/power koşusu ayrı kapı, fresh target revalidation, açık operatör yetkisi ve yeni immutable raw ister.",
],
},snippet sha256: 22569e0150f7…file sha256: 9726dbf00f84…
Focused test komutu
CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s559_r1_audio_route_pcm_capability_model -- --test-threads=1proof: docs/M8.1-RPi5-G8l-S559-R1-Audio-Route-PCM-Capability-Model-Proof.md
Registry schema v5 · generator
website/scripts/generate-code-gates.mjs · Tam SHA-256: 3050638b71a684d8f8f947a8a6faa237a17fa8db5dc0db04fb207b668b462af9