S568 · SOURCE-BOUND GATE EVIDENCE
S568 · R1 kanıt matrisi ve demo sınırı yayını
tam S568 implementation modülü → Operations --test hedefi ile bağlı tam focused test → ayrı Operations kaydı Bu sayfa yalnız S568 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.
S568Focused kod testiOperations id exactsource SHA exacttest target exact
operation: g8l-s568-r1-evidence-matrix-demo-boundary-publication
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–L737
kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication.rs::S568 r1 evidence matrix demo boundary publication implementation
//! S568 publishes the R1 evidence matrix and the demo boundary statement.
//!
//! The gate models one row for every R1 gate S536..=S568 (kind, narrow
//! status, physical verdict, retained physical observations, hardware
//! presence), rolls the rows up per R1 stage 1..=5, evaluates the R1
//! acceptance predicate, pins the S545 reproducible candidate identity, and
//! renders the matrix as a fixed-width table with a FNV-1a 64 checksum.
//!
//! S568 does NOT claim any hardware, runtime, panel, modem, touch, board,
//! SD, UART or power observation. S540, S543 and S546 are immutable physical
//! RED rows and are never promoted: S540 and S543 carry error-marker REDs,
//! and S546 is the recorded silent pre-BOOT8H hang
//! (`Boot8hAbsentPrimaryFailSilent`, raw 16990 bytes, last line
//! ASELSAN/BOOT8G, BOOT8H absent, zero error/panic markers). No row is
//! PENDING any more and any pending row is rejected fail-closed. The
//! acceptance predicate is required to evaluate to `false` at publication
//! (stage 1 holds three physical REDs and zero physical PASS, and no Model
//! gate carries hardware evidence), and the publication fails closed if it
//! does not. The module is not wired into any boot, IRQ, scheduler or driver
//! path; performs no device operation; does not rerun S540, S543 or S546.
//!
//! Predecessor: S567 (application/recovery/update acceptance matrix).
//! Next: S569 (source remediation for the S546 silent primary_fail; the
//! remediation plan S569 source / S570 freeze / S571 physical is a plan,
//! not a commitment; R2 planning S705-S755 is non-binding).
use alloc::string::String;
use alloc::vec::Vec;
pub const S568_SEQUENCE: usize = 568;
pub const S568_EXPECTED_PREDECESSOR: usize = 567;
pub const S568_R1_STAGE: u8 = 5;
pub const S568_R1_RANGE_FIRST: usize = 536;
pub const S568_R1_RANGE_LAST: usize = 568;
pub const S568_R1_GATE_COUNT: usize = S568_R1_RANGE_LAST - S568_R1_RANGE_FIRST + 1;
pub const S568_R1_STAGE_COUNT: usize = 5;
pub const S568_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS: usize = 0;
pub const S568_PHYSICAL_OBSERVATIONS: usize = 0;
pub const S568_PHYSICAL_OR_DEVICE_OPERATIONS: usize = 0;
pub const S568_SD_WRITES: usize = 0;
pub const S568_UART_OPENS: usize = 0;
pub const S568_POWER_TRANSITIONS: usize = 0;
pub const S568_NEW_IMMUTABLE_RAW_CAPTURES: usize = 0;
pub const S568_S540_PHYSICAL_VERDICT_RETAINED_RED: bool = true;
pub const S568_S543_PHYSICAL_VERDICT_RETAINED_RED: bool = true;
pub const S568_AUTOMATIC_PROMOTION: bool = false;
pub const S568_BOOT_TO_UI_PHYSICALLY_OBSERVED: bool = false;
pub const S568_HARDWARE_PRESENT: bool = false;
pub const S568_R1_ACCEPTANCE_COMPLETE: bool = false;
pub const RUNBOOK_EXECUTED_IN_S568: bool = false;
/// Retained immutable physical RED rows: S540, S543 and S546.
pub const S568_RETAINED_PHYSICAL_RED_ROWS: usize = 3;
pub const S568_S540_RAW_BYTES: usize = 20_525;
pub const S568_S543_RAW_BYTES: usize = 20_509;
/// S546 third physical run: immutable physical RED, recorded silent
/// pre-BOOT8H hang. The raw ends at ASELSAN/BOOT8G with BOOT8H absent and
/// zero error/panic/unknown-IRQ markers; the deterministic source cause is
/// AcceptanceLedgerNotReady(7) -> secondary_fail(43, 544, 7) -> silent
/// primary_fail. Nothing in this module can promote or reinterpret it.
pub const S568_S546_PHYSICAL_GATE_RED: bool = true;
pub const S568_S546_RED_CLASS: &str = "Boot8hAbsentPrimaryFailSilent";
pub const S568_S546_RAW_BYTES: usize = 16_990;
pub const S568_S546_RAW_SHA256: &str =
"a71a9107b4b6ea351eb65720a6b82486105fffdb931563d1c39e8a381c3e485d";
/// No row in the matrix is PENDING any more; any pending row fails closed.
pub const S568_PENDING_PHYSICAL_ROWS: usize = 0;
/// S546 remediation plan (a plan, not a commitment, and no authorization):
/// S569 source remediation, S570 candidate freeze, S571 authorized
/// physical run.
pub const S568_S546_REMEDIATION_SOURCE_SEQUENCE: usize = 569;
pub const S568_S546_REMEDIATION_FREEZE_SEQUENCE: usize = 570;
pub const S568_S546_REMEDIATION_PHYSICAL_SEQUENCE: usize = 571;
pub const S568_S546_REMEDIATION_PLAN_IS_COMMITMENT: bool = false;
/// S545 reproducible board-rpi5 candidate identity (host-frozen, never run
/// to a physical PASS).
pub const S568_S545_IMAGE_SEQUENCE: usize = 545;
pub const S568_S545_IMAGE_BYTES: usize = 945_760;
pub const S568_S545_IMAGE_SHA256_HEX: &str =
"ed1901a991e2f9e9ae3c16f254147a2b0180686a8d70ca5d7353374fee08d467";
pub const S568_S545_IMAGE_SHA256: [u8; 32] = [
0xed, 0x19, 0x01, 0xa9, 0x91, 0xe2, 0xf9, 0xe9, 0xae, 0x3c, 0x16, 0xf2, 0x54, 0x14, 0x7a, 0x2b,
0x01, 0x80, 0x68, 0x6a, 0x8d, 0x70, 0xca, 0x5d, 0x73, 0x53, 0x37, 0x4f, 0xee, 0x08, 0xd4, 0x67,
];
/// Demo boundary non-claim bits. Every bit must be set for publication.
pub const S568_NON_CLAIM_FIELD_RELIABILITY: u8 = 0b0000_0001;
pub const S568_NON_CLAIM_DAILY_USE: u8 = 0b0000_0010;
pub const S568_NON_CLAIM_PRODUCT: u8 = 0b0000_0100;
pub const S568_NON_CLAIM_BOOT_TO_UI_OBSERVED: u8 = 0b0000_1000;
pub const S568_NON_CLAIM_R1_ACCEPTANCE: u8 = 0b0001_0000;
pub const S568_REQUIRED_NON_CLAIMS: u8 = S568_NON_CLAIM_FIELD_RELIABILITY
| S568_NON_CLAIM_DAILY_USE
| S568_NON_CLAIM_PRODUCT
| S568_NON_CLAIM_BOOT_TO_UI_OBSERVED
| S568_NON_CLAIM_R1_ACCEPTANCE;
/// Fixed-width table geometry: `SEQ_ STG KIND________ STATUS_ PHYS____ OBS HW_`.
pub const S568_COLUMN_WIDTHS: [usize; 7] = [4, 3, 12, 7, 8, 3, 3];
pub const S568_ROW_WIDTH: usize = 4 + 3 + 12 + 7 + 8 + 3 + 3 + 6;
pub const S568_TABLE_HEADER: &str = "SEQ STG KIND STATUS PHYS OBS HW ";
pub const S568_TABLE_LINES: usize = 1 + S568_R1_GATE_COUNT + 1;
pub const S568_FNV1A64_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
pub const S568_FNV1A64_PRIME: u64 = 0x0000_0100_0000_01b3;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS568GateKind {
Contract,
Request,
Wiring,
Freeze,
PhysicalRed,
Remediation,
Model,
Matrix,
Publication,
}
impl G8lS568GateKind {
pub const fn label(self) -> &'static str {
match self {
Self::Contract => "Contract",
Self::Request => "Request",
Self::Wiring => "Wiring",
Self::Freeze => "Freeze",
Self::PhysicalRed => "PhysicalRed",
Self::Remediation => "Remediation",
Self::Model => "Model",
Self::Matrix => "Matrix",
Self::Publication => "Publication",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS568NarrowStatus {
Pass,
Red,
Pending,
}
impl G8lS568NarrowStatus {
pub const fn label(self) -> &'static str {
match self {
Self::Pass => "PASS",
Self::Red => "RED",
Self::Pending => "PENDING",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS568PhysicalVerdict {
NotApplicable,
Red,
/// S546 recorded class: silent pre-BOOT8H hang, no error marker at all.
RedBoot8hAbsentPrimaryFailSilent,
Pending,
Pass,
}
impl G8lS568PhysicalVerdict {
pub const fn label(self) -> &'static str {
match self {
Self::NotApplicable => "N/A",
Self::Red => "RED",
Self::RedBoot8hAbsentPrimaryFailSilent => "RED-SLNT",
Self::Pending => "PENDING",
Self::Pass => "PASS",
}
}
/// Every immutable physical RED verdict, whatever its recorded class.
pub const fn is_red(self) -> bool {
matches!(self, Self::Red | Self::RedBoot8hAbsentPrimaryFailSilent)
}
/// Recorded failure class carried by the verdict, when one exists.
pub const fn red_class(self) -> Option<&'static str> {
match self {
Self::RedBoot8hAbsentPrimaryFailSilent => Some(S568_S546_RED_CLASS),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS568MatrixEntry {
pub sequence: usize,
pub stage: u8,
pub kind: G8lS568GateKind,
pub status: G8lS568NarrowStatus,
pub physical_verdict: G8lS568PhysicalVerdict,
pub physical_observations: usize,
pub hardware_present: bool,
}
const fn entry(
sequence: usize,
stage: u8,
kind: G8lS568GateKind,
status: G8lS568NarrowStatus,
physical_verdict: G8lS568PhysicalVerdict,
physical_observations: usize,
) -> G8lS568MatrixEntry {
G8lS568MatrixEntry {
sequence,
stage,
kind,
status,
physical_verdict,
physical_observations,
hardware_present: false,
}
}
/// Canonical R1 evidence matrix at S568 authoring time.
pub const S568_CANONICAL_MATRIX: [G8lS568MatrixEntry; S568_R1_GATE_COUNT] = {
use G8lS568GateKind as K;
use G8lS568NarrowStatus as S;
use G8lS568PhysicalVerdict as P;
[
entry(536, 1, K::Contract, S::Pass, P::NotApplicable, 0),
entry(537, 1, K::Request, S::Pass, P::NotApplicable, 0),
entry(538, 1, K::Wiring, S::Pass, P::NotApplicable, 0),
entry(539, 1, K::Freeze, S::Pass, P::NotApplicable, 0),
entry(540, 1, K::PhysicalRed, S::Red, P::Red, 1),
entry(541, 1, K::Remediation, S::Pass, P::NotApplicable, 0),
entry(542, 1, K::Freeze, S::Pass, P::NotApplicable, 0),
entry(543, 1, K::PhysicalRed, S::Red, P::Red, 1),
entry(544, 1, K::Remediation, S::Pass, P::NotApplicable, 0),
entry(545, 1, K::Freeze, S::Pass, P::NotApplicable, 0),
entry(
546,
1,
K::Contract,
S::Red,
P::RedBoot8hAbsentPrimaryFailSilent,
1,
),
entry(547, 2, K::Contract, S::Pass, P::NotApplicable, 0),
entry(548, 2, K::Model, S::Pass, P::NotApplicable, 0),
entry(549, 2, K::Model, S::Pass, P::NotApplicable, 0),
entry(550, 2, K::Model, S::Pass, P::NotApplicable, 0),
entry(551, 2, K::Model, S::Pass, P::NotApplicable, 0),
entry(552, 2, K::Model, S::Pass, P::NotApplicable, 0),
entry(553, 2, K::Model, S::Pass, P::NotApplicable, 0),
entry(554, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(555, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(556, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(557, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(558, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(559, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(560, 3, K::Model, S::Pass, P::NotApplicable, 0),
entry(561, 4, K::Model, S::Pass, P::NotApplicable, 0),
entry(562, 4, K::Model, S::Pass, P::NotApplicable, 0),
entry(563, 4, K::Model, S::Pass, P::NotApplicable, 0),
entry(564, 4, K::Model, S::Pass, P::NotApplicable, 0),
entry(565, 4, K::Model, S::Pass, P::NotApplicable, 0),
entry(566, 4, K::Contract, S::Pass, P::NotApplicable, 0),
entry(567, 4, K::Matrix, S::Pass, P::NotApplicable, 0),
entry(568, 5, K::Publication, S::Pass, P::NotApplicable, 0),
]
};
pub const fn canonical_s568_matrix_entry(sequence: usize) -> Option<G8lS568MatrixEntry> {
if sequence < S568_R1_RANGE_FIRST || sequence > S568_R1_RANGE_LAST {
return None;
}
Some(S568_CANONICAL_MATRIX[sequence - S568_R1_RANGE_FIRST])
}
pub const fn s568_stage_title(stage: u8) -> Option<&'static str> {
match stage {
1 => Some("boot/Boot-to-UI"),
2 => Some("ekran/touch/UI"),
3 => Some("modem/ses"),
4 => Some("uygulama/recovery/update"),
5 => Some("kanit matrisi ve demo siniri"),
_ => None,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub struct G8lS568StageRollup {
pub stage: u8,
pub gate_count: usize,
pub pass_count: usize,
pub red_count: usize,
pub pending_count: usize,
pub model_gate_count: usize,
pub model_gates_with_hardware_evidence: usize,
pub physical_pass_present: bool,
pub physical_red_count: usize,
pub retained_physical_observations: usize,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS568ImageIdentity {
pub sequence: usize,
pub bytes: usize,
pub sha256: [u8; 32],
}
pub const fn canonical_s568_image_identity() -> G8lS568ImageIdentity {
G8lS568ImageIdentity {
sequence: S568_S545_IMAGE_SEQUENCE,
bytes: S568_S545_IMAGE_BYTES,
sha256: S568_S545_IMAGE_SHA256,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS568DemoBoundary {
/// Bitmask of explicit non-claims; must equal `S568_REQUIRED_NON_CLAIMS`.
pub non_claims: u8,
pub demo_scope_host_model_only: bool,
pub physical_pass_required_for_stage_1: bool,
pub hardware_evidence_required_for_model_gates: bool,
}
pub const fn canonical_s568_demo_boundary() -> G8lS568DemoBoundary {
G8lS568DemoBoundary {
non_claims: S568_REQUIRED_NON_CLAIMS,
demo_scope_host_model_only: true,
physical_pass_required_for_stage_1: true,
hardware_evidence_required_for_model_gates: true,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS568EvidenceMatrixReceipt {
pub sequence: usize,
pub predecessor_sequence: usize,
pub r1_stage: u8,
pub range_first: usize,
pub range_last: usize,
pub row_count: usize,
pub rollups: [G8lS568StageRollup; S568_R1_STAGE_COUNT],
pub pass_rows: usize,
pub red_rows: usize,
pub pending_rows: usize,
pub retained_physical_red_rows: usize,
pub image: G8lS568ImageIdentity,
pub boundary: G8lS568DemoBoundary,
pub table_lines: usize,
pub table_bytes: usize,
pub table_checksum: u64,
pub r1_acceptance_complete: bool,
pub s540_physical_verdict_retained_red: bool,
pub s543_physical_verdict_retained_red: bool,
pub s546_physical_verdict_retained_red: bool,
pub s546_red_class: &'static str,
pub automatic_promotion: bool,
pub hardware_present: bool,
pub supported_profile_runtime_observations: usize,
pub physical_observations: usize,
pub runbook_executed: bool,
}
#[derive(Debug)]
pub struct G8lS568EvidenceMatrixState {
receipt: Option<G8lS568EvidenceMatrixReceipt>,
}
impl G8lS568EvidenceMatrixState {
pub const fn new() -> Self {
Self { receipt: None }
}
pub const fn receipt(&self) -> Option<G8lS568EvidenceMatrixReceipt> {
self.receipt
}
}
impl Default for G8lS568EvidenceMatrixState {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS568EvidenceMatrixOutcome {
Published(G8lS568EvidenceMatrixReceipt),
Retained(G8lS568EvidenceMatrixReceipt),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS568EvidenceMatrixError {
RowCountMismatch,
SequenceOutOfRange,
MissingSequence,
DuplicateSequence,
SequenceOrder,
HardwareClaim,
PhysicalObservationClaim,
PhysicalVerdictClaim,
FixedRedRowDrift,
PendingRowDrift,
StageDrift,
EntryDrift,
ImageIdentityDrift,
DemoBoundaryClaim,
AcceptancePredicateDrift,
TableFieldOverflow,
TableWidthDrift,
PublishedStateDrift,
}
impl G8lS568EvidenceMatrixError {
pub const fn diagnostic_code(self) -> u64 {
match self {
Self::RowCountMismatch => 1,
Self::SequenceOutOfRange => 2,
Self::MissingSequence => 3,
Self::DuplicateSequence => 4,
Self::SequenceOrder => 5,
Self::HardwareClaim => 6,
Self::PhysicalObservationClaim => 7,
Self::PhysicalVerdictClaim => 8,
Self::FixedRedRowDrift => 9,
Self::PendingRowDrift => 10,
Self::StageDrift => 11,
Self::EntryDrift => 12,
Self::ImageIdentityDrift => 13,
Self::DemoBoundaryClaim => 14,
Self::AcceptancePredicateDrift => 15,
Self::TableFieldOverflow => 16,
Self::TableWidthDrift => 17,
Self::PublishedStateDrift => 18,
}
}
}
/// FNV-1a 64 over arbitrary bytes; wrapping arithmetic is the algorithm.
pub fn s568_fnv1a64(bytes: &[u8]) -> u64 {
let mut hash = S568_FNV1A64_OFFSET;
for byte in bytes {
hash ^= u64::from(*byte);
hash = hash.wrapping_mul(S568_FNV1A64_PRIME);
}
hash
}
pub fn s568_sha256_hex(digest: &[u8; 32]) -> String {
const HEX: &[u8; 16] = b"0123456789abcdef";
let mut out = String::with_capacity(64);
for byte in digest {
out.push(HEX[usize::from(byte >> 4)] as char);
out.push(HEX[usize::from(byte & 0x0f)] as char);
}
out
}
/// Structural validation: exactly one row per S536..=S568 in ascending order.
pub fn validate_s568_matrix_shape(
entries: &[G8lS568MatrixEntry],
) -> Result<(), G8lS568EvidenceMatrixError> {
if entries.len() > S568_R1_GATE_COUNT {
return Err(G8lS568EvidenceMatrixError::RowCountMismatch);
}
let mut seen = [false; S568_R1_GATE_COUNT];
let mut previous: Option<usize> = None;
for row in entries {
if row.sequence < S568_R1_RANGE_FIRST || row.sequence > S568_R1_RANGE_LAST {
return Err(G8lS568EvidenceMatrixError::SequenceOutOfRange);
}
let index = row.sequence - S568_R1_RANGE_FIRST;
if seen[index] {
return Err(G8lS568EvidenceMatrixError::DuplicateSequence);
}
seen[index] = true;
if let Some(previous) = previous {
if row.sequence <= previous {
return Err(G8lS568EvidenceMatrixError::SequenceOrder);
}
}
previous = Some(row.sequence);
}
if seen.iter().any(|present| !present) {
return Err(G8lS568EvidenceMatrixError::MissingSequence);
}
Ok(())
}
/// Content validation: no hardware claim anywhere, physical observations only
/// on the three immutable RED rows (S540, S543, S546), no pending row at
/// all, every row canonical.
pub fn validate_s568_matrix_rows(
entries: &[G8lS568MatrixEntry],
) -> Result<(), G8lS568EvidenceMatrixError> {
for row in entries {
if row.hardware_present {
return Err(G8lS568EvidenceMatrixError::HardwareClaim);
}
if row.physical_verdict == G8lS568PhysicalVerdict::Pass {
return Err(G8lS568EvidenceMatrixError::PhysicalVerdictClaim);
}
if row.status == G8lS568NarrowStatus::Pending
|| row.physical_verdict == G8lS568PhysicalVerdict::Pending
{
return Err(G8lS568EvidenceMatrixError::PendingRowDrift);
}
let fixed_red = match row.sequence {
540 | 543 => Some((G8lS568GateKind::PhysicalRed, G8lS568PhysicalVerdict::Red)),
546 => Some((
G8lS568GateKind::Contract,
G8lS568PhysicalVerdict::RedBoot8hAbsentPrimaryFailSilent,
)),
_ => None,
};
if let Some((kind, verdict)) = fixed_red {
if row.kind != kind
|| row.status != G8lS568NarrowStatus::Red
|| row.physical_verdict != verdict
|| row.physical_observations != 1
{
return Err(G8lS568EvidenceMatrixError::FixedRedRowDrift);
}
} else if row.physical_observations != 0 {
return Err(G8lS568EvidenceMatrixError::PhysicalObservationClaim);
}
let Some(canonical) = canonical_s568_matrix_entry(row.sequence) else {
return Err(G8lS568EvidenceMatrixError::SequenceOutOfRange);
};
if row.stage != canonical.stage || s568_stage_title(row.stage).is_none() {
return Err(G8lS568EvidenceMatrixError::StageDrift);
}
if *row != canonical {
return Err(G8lS568EvidenceMatrixError::EntryDrift);
}
}
Ok(())
}
pub fn s568_stage_rollups(
entries: &[G8lS568MatrixEntry],
) -> Result<[G8lS568StageRollup; S568_R1_STAGE_COUNT], G8lS568EvidenceMatrixError> {
let mut rollups = [G8lS568StageRollup::default(); S568_R1_STAGE_COUNT];
for (index, rollup) in rollups.iter_mut().enumerate() {
rollup.stage = index as u8 + 1;
}
for row in entries {
if row.stage == 0 || usize::from(row.stage) > S568_R1_STAGE_COUNT {
return Err(G8lS568EvidenceMatrixError::StageDrift);
}
let rollup = &mut rollups[usize::from(row.stage) - 1];
rollup.gate_count = rollup
.gate_count
.checked_add(1)
.ok_or(G8lS568EvidenceMatrixError::RowCountMismatch)?;
match row.status {
G8lS568NarrowStatus::Pass => rollup.pass_count += 1,
G8lS568NarrowStatus::Red => rollup.red_count += 1,
G8lS568NarrowStatus::Pending => rollup.pending_count += 1,
}
if row.kind == G8lS568GateKind::Model {
rollup.model_gate_count += 1;
if row.hardware_present {
rollup.model_gates_with_hardware_evidence += 1;
}
}
if row.physical_verdict.is_red() {
rollup.physical_red_count += 1;
}
if row.physical_verdict == G8lS568PhysicalVerdict::Pass {
rollup.physical_pass_present = true;
}
rollup.retained_physical_observations = rollup
.retained_physical_observations
.checked_add(row.physical_observations)
.ok_or(G8lS568EvidenceMatrixError::PhysicalObservationClaim)?;
}
Ok(rollups)
}
/// R1 acceptance predicate. It is `true` only when stage 1 holds a physical
/// PASS, no row is pending, and every Model gate carries hardware evidence.
/// At S568 (post-S546 verdict) no row is pending any more, but stage 1
/// holds three physical REDs and zero physical PASS and no Model gate
/// carries hardware evidence, so the predicate necessarily evaluates to
/// `false`; no promotion path exists that could flip it.
pub fn s568_r1_acceptance_predicate(rollups: &[G8lS568StageRollup; S568_R1_STAGE_COUNT]) -> bool {
let stage_1_physical_pass = rollups[0].physical_pass_present;
let nothing_pending = rollups.iter().all(|rollup| rollup.pending_count == 0);
let every_model_gate_has_hardware = rollups
.iter()
.all(|rollup| rollup.model_gates_with_hardware_evidence == rollup.model_gate_count);
stage_1_physical_pass && nothing_pending && every_model_gate_has_hardware
}
fn push_padded(
out: &mut String,
text: &str,
width: usize,
) -> Result<(), G8lS568EvidenceMatrixError> {
if text.len() > width {
return Err(G8lS568EvidenceMatrixError::TableFieldOverflow);
}
out.push_str(text);
for _ in text.len()..width {
out.push(' ');
}
Ok(())
}
fn push_row(out: &mut String, row: &G8lS568MatrixEntry) -> Result<(), G8lS568EvidenceMatrixError> {
let start = out.len();
let widths = S568_COLUMN_WIDTHS;
push_padded(out, &alloc::format!("S{}", row.sequence), widths[0])?;
out.push(' ');
push_padded(out, &alloc::format!("{}", row.stage), widths[1])?;
out.push(' ');
push_padded(out, row.kind.label(), widths[2])?;
out.push(' ');
push_padded(out, row.status.label(), widths[3])?;
out.push(' ');
push_padded(out, row.physical_verdict.label(), widths[4])?;
out.push(' ');
push_padded(
out,
&alloc::format!("{}", row.physical_observations),
widths[5],
)?;
out.push(' ');
push_padded(
out,
if row.hardware_present { "yes" } else { "no" },
widths[6],
)?;
if out.len() - start != S568_ROW_WIDTH {
return Err(G8lS568EvidenceMatrixError::TableWidthDrift);
}
out.push('\n');
Ok(())
}
/// Render the fixed-width table: header, one row per gate, checksum trailer.
/// The checksum covers header and rows exactly as rendered.
pub fn render_s568_matrix(
entries: &[G8lS568MatrixEntry],
) -> Result<(String, u64), G8lS568EvidenceMatrixError> {
validate_s568_matrix_shape(entries)?;
if S568_TABLE_HEADER.len() != S568_ROW_WIDTH {
return Err(G8lS568EvidenceMatrixError::TableWidthDrift);
}
let mut table = String::with_capacity((S568_ROW_WIDTH + 1) * S568_TABLE_LINES);
table.push_str(S568_TABLE_HEADER);
table.push('\n');
for row in entries {
push_row(&mut table, row)?;
}
let checksum = s568_fnv1a64(table.as_bytes());
let trailer = alloc::format!("CHECKSUM fnv1a64={checksum:016x}");
push_padded(&mut table, &trailer, S568_ROW_WIDTH)?;
table.push('\n');
let lines: Vec<&str> = table.lines().collect();
if lines.len() != S568_TABLE_LINES || lines.iter().any(|line| line.len() != S568_ROW_WIDTH) {
return Err(G8lS568EvidenceMatrixError::TableWidthDrift);
}
Ok((table, checksum))
}
pub fn service_s568_model_publish_evidence_matrix(
state: &mut G8lS568EvidenceMatrixState,
entries: &[G8lS568MatrixEntry],
image: G8lS568ImageIdentity,
boundary: G8lS568DemoBoundary,
) -> Result<G8lS568EvidenceMatrixOutcome, G8lS568EvidenceMatrixError> {
validate_s568_matrix_shape(entries)?;
validate_s568_matrix_rows(entries)?;
if image != canonical_s568_image_identity() {
return Err(G8lS568EvidenceMatrixError::ImageIdentityDrift);
}
if boundary.non_claims & S568_REQUIRED_NON_CLAIMS != S568_REQUIRED_NON_CLAIMS
|| boundary.non_claims & !S568_REQUIRED_NON_CLAIMS != 0
|| !boundary.demo_scope_host_model_only
|| !boundary.physical_pass_required_for_stage_1
|| !boundary.hardware_evidence_required_for_model_gates
{
return Err(G8lS568EvidenceMatrixError::DemoBoundaryClaim);
}
let rollups = s568_stage_rollups(entries)?;
let acceptance = s568_r1_acceptance_predicate(&rollups);
if acceptance != S568_R1_ACCEPTANCE_COMPLETE {
return Err(G8lS568EvidenceMatrixError::AcceptancePredicateDrift);
}
let (table, table_checksum) = render_s568_matrix(entries)?;
let pass_rows = rollups.iter().map(|rollup| rollup.pass_count).sum();
let red_rows = rollups.iter().map(|rollup| rollup.red_count).sum();
let pending_rows = rollups.iter().map(|rollup| rollup.pending_count).sum();
let retained_physical_red_rows = rollups.iter().map(|rollup| rollup.physical_red_count).sum();
if red_rows != S568_RETAINED_PHYSICAL_RED_ROWS
|| retained_physical_red_rows != S568_RETAINED_PHYSICAL_RED_ROWS
|| pending_rows != S568_PENDING_PHYSICAL_ROWS
{
return Err(G8lS568EvidenceMatrixError::FixedRedRowDrift);
}
let receipt = G8lS568EvidenceMatrixReceipt {
sequence: S568_SEQUENCE,
predecessor_sequence: S568_EXPECTED_PREDECESSOR,
r1_stage: S568_R1_STAGE,
range_first: S568_R1_RANGE_FIRST,
range_last: S568_R1_RANGE_LAST,
row_count: entries.len(),
rollups,
pass_rows,
red_rows,
pending_rows,
retained_physical_red_rows,
image,
boundary,
table_lines: S568_TABLE_LINES,
table_bytes: table.len(),
table_checksum,
r1_acceptance_complete: acceptance,
s540_physical_verdict_retained_red: S568_S540_PHYSICAL_VERDICT_RETAINED_RED,
s543_physical_verdict_retained_red: S568_S543_PHYSICAL_VERDICT_RETAINED_RED,
s546_physical_verdict_retained_red: S568_S546_PHYSICAL_GATE_RED,
s546_red_class: S568_S546_RED_CLASS,
automatic_promotion: S568_AUTOMATIC_PROMOTION,
hardware_present: S568_HARDWARE_PRESENT,
supported_profile_runtime_observations: S568_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS,
physical_observations: S568_PHYSICAL_OBSERVATIONS,
runbook_executed: RUNBOOK_EXECUTED_IN_S568,
};
if let Some(published) = state.receipt {
if published != receipt {
return Err(G8lS568EvidenceMatrixError::PublishedStateDrift);
}
return Ok(G8lS568EvidenceMatrixOutcome::Retained(published));
}
state.receipt = Some(receipt);
Ok(G8lS568EvidenceMatrixOutcome::Published(receipt))
}
snippet sha256: b03d60ea6f98…file sha256: b03d60ea6f98…
02 · Doğrulayan test kodu
Operations komutuna bağlı focused test
tam dosyaL1–L622
simulation/tests/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication.rs::S568 r1 evidence matrix demo boundary publication focused tests
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication::*;
use std::collections::BTreeSet;
const SOURCE: &str = include_str!(
"../../kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication.rs"
);
const MAIN: &str = include_str!("../../kernel/src/main.rs");
const SIMULATION_LIB: &str = include_str!("../src/lib.rs");
fn matrix() -> Vec<G8lS568MatrixEntry> {
S568_CANONICAL_MATRIX.to_vec()
}
fn publish(
state: &mut G8lS568EvidenceMatrixState,
entries: &[G8lS568MatrixEntry],
) -> Result<G8lS568EvidenceMatrixOutcome, G8lS568EvidenceMatrixError> {
service_s568_model_publish_evidence_matrix(
state,
entries,
canonical_s568_image_identity(),
canonical_s568_demo_boundary(),
)
}
fn published_receipt() -> G8lS568EvidenceMatrixReceipt {
let mut state = G8lS568EvidenceMatrixState::new();
let G8lS568EvidenceMatrixOutcome::Published(receipt) = publish(&mut state, &matrix()).unwrap()
else {
panic!("first S568 publication missing")
};
receipt
}
#[test]
fn sequence_scope_and_nonpromotion_are_exact() {
assert_eq!(S568_SEQUENCE, 568);
assert_eq!(S568_EXPECTED_PREDECESSOR, 567);
assert_eq!(S568_R1_STAGE, 5);
assert_eq!(S568_R1_RANGE_FIRST, 536);
assert_eq!(S568_R1_RANGE_LAST, 568);
assert_eq!(S568_R1_GATE_COUNT, 33);
assert_eq!(S568_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS, 0);
assert_eq!(S568_PHYSICAL_OBSERVATIONS, 0);
assert_eq!(S568_PHYSICAL_OR_DEVICE_OPERATIONS, 0);
assert_eq!(S568_SD_WRITES, 0);
assert_eq!(S568_UART_OPENS, 0);
assert_eq!(S568_POWER_TRANSITIONS, 0);
assert_eq!(S568_NEW_IMMUTABLE_RAW_CAPTURES, 0);
assert!(S568_S540_PHYSICAL_VERDICT_RETAINED_RED);
assert!(S568_S543_PHYSICAL_VERDICT_RETAINED_RED);
assert!(!S568_AUTOMATIC_PROMOTION);
assert!(!S568_BOOT_TO_UI_PHYSICALLY_OBSERVED);
assert!(!S568_HARDWARE_PRESENT);
assert!(!S568_R1_ACCEPTANCE_COMPLETE);
assert!(!RUNBOOK_EXECUTED_IN_S568);
assert_eq!(S568_S545_IMAGE_SEQUENCE, 545);
assert_eq!(S568_S545_IMAGE_BYTES, 945_760);
assert_eq!(S568_PENDING_PHYSICAL_ROWS, 0);
assert_eq!(S568_RETAINED_PHYSICAL_RED_ROWS, 3);
assert_eq!(S568_S540_RAW_BYTES, 20_525);
assert_eq!(S568_S543_RAW_BYTES, 20_509);
assert!(S568_S546_PHYSICAL_GATE_RED);
assert_eq!(S568_S546_RED_CLASS, "Boot8hAbsentPrimaryFailSilent");
assert_eq!(S568_S546_RAW_BYTES, 16_990);
assert_eq!(
S568_S546_RAW_SHA256,
"a71a9107b4b6ea351eb65720a6b82486105fffdb931563d1c39e8a381c3e485d"
);
assert_eq!(S568_S546_REMEDIATION_SOURCE_SEQUENCE, 569);
assert_eq!(S568_S546_REMEDIATION_FREEZE_SEQUENCE, 570);
assert_eq!(S568_S546_REMEDIATION_PHYSICAL_SEQUENCE, 571);
assert!(!S568_S546_REMEDIATION_PLAN_IS_COMMITMENT);
}
#[test]
fn module_is_registered_in_kernel_and_simulation() {
let module = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication";
assert!(MAIN.contains(&format!("mod {module};")));
assert!(SIMULATION_LIB.contains(&format!("pub mod {module};")));
assert!(SIMULATION_LIB.contains(&format!("#[path = \"../../kernel/src/{module}.rs\"]")));
}
#[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::",
"std::process::Command",
"/dev/disk",
"/dev/cu.",
"diskutil",
"dd if=",
"TIOCEXCL",
"crate::kprintln!",
] {
assert!(!SOURCE.contains(forbidden), "forbidden token: {forbidden}");
}
assert!(SOURCE.contains("performs no device operation"));
assert!(SOURCE.contains("does not rerun S540, S543 or S546"));
assert!(SOURCE.contains("S568_HARDWARE_PRESENT: bool = false"));
assert!(SOURCE.contains("S568_R1_ACCEPTANCE_COMPLETE: bool = false"));
assert!(SOURCE.contains("RUNBOOK_EXECUTED_IN_S568: bool = false"));
}
#[test]
fn diagnostic_codes_are_nonzero_and_unique() {
let errors = [
G8lS568EvidenceMatrixError::RowCountMismatch,
G8lS568EvidenceMatrixError::SequenceOutOfRange,
G8lS568EvidenceMatrixError::MissingSequence,
G8lS568EvidenceMatrixError::DuplicateSequence,
G8lS568EvidenceMatrixError::SequenceOrder,
G8lS568EvidenceMatrixError::HardwareClaim,
G8lS568EvidenceMatrixError::PhysicalObservationClaim,
G8lS568EvidenceMatrixError::PhysicalVerdictClaim,
G8lS568EvidenceMatrixError::FixedRedRowDrift,
G8lS568EvidenceMatrixError::PendingRowDrift,
G8lS568EvidenceMatrixError::StageDrift,
G8lS568EvidenceMatrixError::EntryDrift,
G8lS568EvidenceMatrixError::ImageIdentityDrift,
G8lS568EvidenceMatrixError::DemoBoundaryClaim,
G8lS568EvidenceMatrixError::AcceptancePredicateDrift,
G8lS568EvidenceMatrixError::TableFieldOverflow,
G8lS568EvidenceMatrixError::TableWidthDrift,
G8lS568EvidenceMatrixError::PublishedStateDrift,
];
let codes: BTreeSet<_> = errors
.into_iter()
.map(G8lS568EvidenceMatrixError::diagnostic_code)
.collect();
assert_eq!(codes.len(), errors.len());
assert!(!codes.contains(&0));
}
#[test]
fn canonical_matrix_publishes_receipt_with_false_acceptance() {
let mut state = G8lS568EvidenceMatrixState::new();
let G8lS568EvidenceMatrixOutcome::Published(receipt) = publish(&mut state, &matrix()).unwrap()
else {
panic!("first S568 publication missing")
};
assert_eq!(state.receipt(), Some(receipt));
assert_eq!(receipt.sequence, 568);
assert_eq!(receipt.predecessor_sequence, 567);
assert_eq!(receipt.r1_stage, 5);
assert_eq!((receipt.range_first, receipt.range_last), (536, 568));
assert_eq!(receipt.row_count, 33);
assert_eq!(receipt.pass_rows, 30);
assert_eq!(receipt.red_rows, 3);
assert_eq!(receipt.pending_rows, 0);
assert_eq!(receipt.retained_physical_red_rows, 3);
assert_eq!(receipt.image, canonical_s568_image_identity());
assert_eq!(receipt.boundary, canonical_s568_demo_boundary());
assert_eq!(receipt.table_lines, 35);
assert_eq!(receipt.table_bytes, 35 * (S568_ROW_WIDTH + 1));
assert!(!receipt.r1_acceptance_complete);
assert!(receipt.s540_physical_verdict_retained_red);
assert!(receipt.s543_physical_verdict_retained_red);
assert!(receipt.s546_physical_verdict_retained_red);
assert_eq!(receipt.s546_red_class, "Boot8hAbsentPrimaryFailSilent");
assert!(!receipt.automatic_promotion);
assert!(!receipt.hardware_present);
assert_eq!(receipt.supported_profile_runtime_observations, 0);
assert_eq!(receipt.physical_observations, 0);
assert!(!receipt.runbook_executed);
}
#[test]
fn exact_replay_retains_the_same_receipt() {
let mut state = G8lS568EvidenceMatrixState::new();
let G8lS568EvidenceMatrixOutcome::Published(receipt) = publish(&mut state, &matrix()).unwrap()
else {
panic!("first publication missing")
};
assert_eq!(
publish(&mut state, &matrix()),
Ok(G8lS568EvidenceMatrixOutcome::Retained(receipt))
);
assert_eq!(state.receipt(), Some(receipt));
}
#[test]
fn divergent_input_after_publication_fails_closed() {
let mut state = G8lS568EvidenceMatrixState::new();
publish(&mut state, &matrix()).unwrap();
let mut boundary = canonical_s568_demo_boundary();
boundary.non_claims = 0;
assert_eq!(
service_s568_model_publish_evidence_matrix(
&mut state,
&matrix(),
canonical_s568_image_identity(),
boundary,
),
Err(G8lS568EvidenceMatrixError::DemoBoundaryClaim)
);
let mut rows = matrix();
rows[32].hardware_present = true;
assert_eq!(
publish(&mut state, &rows),
Err(G8lS568EvidenceMatrixError::HardwareClaim)
);
let published = state.receipt().unwrap();
assert_eq!(published.sequence, 568);
assert!(!published.r1_acceptance_complete);
}
#[test]
fn canonical_matrix_covers_every_sequence_once_with_fixed_stage_rollup() {
let rows = matrix();
assert_eq!(rows.len(), 33);
let sequences: BTreeSet<_> = rows.iter().map(|row| row.sequence).collect();
assert_eq!(sequences, (536..=568).collect());
for (index, row) in rows.iter().enumerate() {
assert_eq!(row.sequence, 536 + index);
assert_eq!(canonical_s568_matrix_entry(row.sequence), Some(*row));
assert!(!row.hardware_present);
}
assert_eq!(canonical_s568_matrix_entry(535), None);
assert_eq!(canonical_s568_matrix_entry(569), None);
let rollups = s568_stage_rollups(&rows).unwrap();
let expected = [(1, 11, 8, 3, 0, 0), (2, 7, 7, 0, 0, 6), (3, 7, 7, 0, 0, 7), (4, 7, 7, 0, 0, 5), (5, 1, 1, 0, 0, 0)];
for (rollup, (stage, gates, pass, red, pending, model)) in rollups.iter().zip(expected) {
assert_eq!(rollup.stage, stage);
assert_eq!(rollup.gate_count, gates);
assert_eq!(rollup.pass_count, pass);
assert_eq!(rollup.red_count, red);
assert_eq!(rollup.pending_count, pending);
assert_eq!(rollup.model_gate_count, model);
assert_eq!(rollup.model_gates_with_hardware_evidence, 0);
assert!(!rollup.physical_pass_present);
}
assert_eq!(rollups[0].physical_red_count, 3);
assert_eq!(rollups[0].retained_physical_observations, 3);
assert_eq!(rollups.iter().map(|rollup| rollup.gate_count).sum::<usize>(), 33);
assert_eq!(rollups.iter().map(|rollup| rollup.model_gate_count).sum::<usize>(), 18);
}
#[test]
fn s540_s543_and_s546_rows_are_immutable_physical_red() {
for sequence in [540, 543] {
let row = canonical_s568_matrix_entry(sequence).unwrap();
assert_eq!(row.stage, 1);
assert_eq!(row.kind, G8lS568GateKind::PhysicalRed);
assert_eq!(row.status, G8lS568NarrowStatus::Red);
assert_eq!(row.physical_verdict, G8lS568PhysicalVerdict::Red);
assert_eq!(row.physical_observations, 1);
assert!(row.physical_verdict.is_red());
assert_eq!(row.physical_verdict.red_class(), None);
}
let recorded = canonical_s568_matrix_entry(546).unwrap();
assert_eq!(recorded.stage, 1);
assert_eq!(recorded.kind, G8lS568GateKind::Contract);
assert_eq!(recorded.status, G8lS568NarrowStatus::Red);
assert_eq!(
recorded.physical_verdict,
G8lS568PhysicalVerdict::RedBoot8hAbsentPrimaryFailSilent
);
assert_eq!(recorded.physical_observations, 1);
assert!(recorded.physical_verdict.is_red());
assert_eq!(
recorded.physical_verdict.red_class(),
Some("Boot8hAbsentPrimaryFailSilent")
);
let last = canonical_s568_matrix_entry(568).unwrap();
assert_eq!(last.stage, 5);
assert_eq!(last.kind, G8lS568GateKind::Publication);
for sequence in [540, 543, 546] {
let mut rows = matrix();
rows[sequence - 536].status = G8lS568NarrowStatus::Pass;
rows[sequence - 536].physical_verdict = G8lS568PhysicalVerdict::NotApplicable;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::FixedRedRowDrift)
);
}
// Swapping the recorded S546 class for the plain RED verdict is drift.
let mut rows = matrix();
rows[546 - 536].physical_verdict = G8lS568PhysicalVerdict::Red;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::FixedRedRowDrift)
);
}
#[test]
fn pending_s546_row_is_rejected_fail_closed() {
// The pre-verdict authoring shape (S546 PENDING) is no longer legal.
let mut rows = matrix();
rows[546 - 536].status = G8lS568NarrowStatus::Pending;
rows[546 - 536].physical_verdict = G8lS568PhysicalVerdict::Pending;
rows[546 - 536].physical_observations = 0;
assert_eq!(
validate_s568_matrix_rows(&rows),
Err(G8lS568EvidenceMatrixError::PendingRowDrift)
);
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::PendingRowDrift)
);
// No row at all may carry a pending narrow status or pending verdict.
let mut rows = matrix();
rows[0].status = G8lS568NarrowStatus::Pending;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::PendingRowDrift)
);
let mut rows = matrix();
rows[550 - 536].physical_verdict = G8lS568PhysicalVerdict::Pending;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::PendingRowDrift)
);
// The canonical matrix itself holds zero pending rows.
let receipt = published_receipt();
assert_eq!(receipt.pending_rows, S568_PENDING_PHYSICAL_ROWS);
assert!(matrix().iter().all(|row| {
row.status != G8lS568NarrowStatus::Pending
&& row.physical_verdict != G8lS568PhysicalVerdict::Pending
}));
}
#[test]
fn missing_sequence_fails_closed() {
let mut rows = matrix();
rows.remove(10);
assert_eq!(
validate_s568_matrix_shape(&rows),
Err(G8lS568EvidenceMatrixError::MissingSequence)
);
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::MissingSequence)
);
assert_eq!(
render_s568_matrix(&[]),
Err(G8lS568EvidenceMatrixError::MissingSequence)
);
let mut rows = matrix();
rows[10] = rows[11];
assert_eq!(
validate_s568_matrix_shape(&rows),
Err(G8lS568EvidenceMatrixError::DuplicateSequence)
);
}
#[test]
fn duplicate_sequence_fails_closed() {
let mut rows = matrix();
rows.push(rows[0]);
assert_eq!(
validate_s568_matrix_shape(&rows),
Err(G8lS568EvidenceMatrixError::RowCountMismatch)
);
let mut rows = matrix();
rows[5] = rows[4];
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::DuplicateSequence)
);
let mut rows = matrix();
rows[20] = rows[4];
rows[4] = rows[20];
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::DuplicateSequence)
);
}
#[test]
fn unordered_or_out_of_range_rows_fail_closed() {
let mut rows = matrix();
rows.swap(3, 4);
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::SequenceOrder)
);
let mut rows = matrix();
rows[32].sequence = 569;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::SequenceOutOfRange)
);
let mut rows = matrix();
rows[0].sequence = 535;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::SequenceOutOfRange)
);
let mut rows = matrix();
rows[0].sequence = usize::MAX;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::SequenceOutOfRange)
);
}
#[test]
fn any_row_claiming_hardware_fails_closed() {
for index in [0, 4, 12, 20, 32] {
let mut rows = matrix();
rows[index].hardware_present = true;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::HardwareClaim)
);
}
let mut rows = matrix();
rows[12].physical_observations = 1;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::PhysicalObservationClaim)
);
let mut rows = matrix();
rows[4].physical_observations = usize::MAX;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::FixedRedRowDrift)
);
let mut rows = matrix();
rows[12].kind = G8lS568GateKind::Contract;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::EntryDrift)
);
let mut rows = matrix();
rows[12].stage = 3;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::StageDrift)
);
}
#[test]
fn physical_pass_or_promoted_verdict_fails_closed() {
let mut rows = matrix();
rows[546 - 536].physical_verdict = G8lS568PhysicalVerdict::Pass;
rows[546 - 536].status = G8lS568NarrowStatus::Pass;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::PhysicalVerdictClaim)
);
let mut rows = matrix();
rows[540 - 536].physical_verdict = G8lS568PhysicalVerdict::Pass;
assert_eq!(
publish(&mut G8lS568EvidenceMatrixState::new(), &rows),
Err(G8lS568EvidenceMatrixError::PhysicalVerdictClaim)
);
}
#[test]
fn acceptance_predicate_is_false_now_and_requires_stage1_physical_pass_and_hardware() {
let rollups = s568_stage_rollups(&matrix()).unwrap();
assert!(!s568_r1_acceptance_predicate(&rollups));
assert!(rollups.iter().all(|rollup| rollup.pending_count == 0));
let mut hypothetical = rollups;
hypothetical[0].physical_pass_present = true;
assert!(!s568_r1_acceptance_predicate(&hypothetical));
for rollup in hypothetical.iter_mut() {
rollup.model_gates_with_hardware_evidence = rollup.model_gate_count;
}
assert!(s568_r1_acceptance_predicate(&hypothetical));
let mut only_hardware = rollups;
for rollup in only_hardware.iter_mut() {
rollup.model_gates_with_hardware_evidence = rollup.model_gate_count;
}
assert!(!s568_r1_acceptance_predicate(&only_hardware));
let mut with_pending = hypothetical;
with_pending[0].pending_count = 1;
assert!(!s568_r1_acceptance_predicate(&with_pending));
assert_eq!(s568_r1_acceptance_predicate(&rollups), S568_R1_ACCEPTANCE_COMPLETE);
}
#[test]
fn image_identity_drift_fails_closed() {
let canonical = canonical_s568_image_identity();
assert_eq!(canonical.bytes, 945_760);
assert_eq!(s568_sha256_hex(&canonical.sha256), S568_S545_IMAGE_SHA256_HEX);
let mut wrong_bytes = canonical;
wrong_bytes.bytes = 945_761;
let mut wrong_sequence = canonical;
wrong_sequence.sequence = 546;
let mut wrong_digest = canonical;
wrong_digest.sha256[31] ^= 0x01;
for image in [wrong_bytes, wrong_sequence, wrong_digest] {
assert_eq!(
service_s568_model_publish_evidence_matrix(
&mut G8lS568EvidenceMatrixState::new(),
&matrix(),
image,
canonical_s568_demo_boundary(),
),
Err(G8lS568EvidenceMatrixError::ImageIdentityDrift)
);
}
}
#[test]
fn demo_boundary_missing_non_claim_fails_closed() {
assert_eq!(S568_REQUIRED_NON_CLAIMS, 0b0001_1111);
for bit in [
S568_NON_CLAIM_FIELD_RELIABILITY,
S568_NON_CLAIM_DAILY_USE,
S568_NON_CLAIM_PRODUCT,
S568_NON_CLAIM_BOOT_TO_UI_OBSERVED,
S568_NON_CLAIM_R1_ACCEPTANCE,
] {
let mut boundary = canonical_s568_demo_boundary();
boundary.non_claims &= !bit;
assert_eq!(
service_s568_model_publish_evidence_matrix(
&mut G8lS568EvidenceMatrixState::new(),
&matrix(),
canonical_s568_image_identity(),
boundary,
),
Err(G8lS568EvidenceMatrixError::DemoBoundaryClaim)
);
}
let mut unknown_bit = canonical_s568_demo_boundary();
unknown_bit.non_claims |= 0b1000_0000;
let mut not_host_only = canonical_s568_demo_boundary();
not_host_only.demo_scope_host_model_only = false;
let mut no_physical_rule = canonical_s568_demo_boundary();
no_physical_rule.physical_pass_required_for_stage_1 = false;
let mut no_hardware_rule = canonical_s568_demo_boundary();
no_hardware_rule.hardware_evidence_required_for_model_gates = false;
for boundary in [unknown_bit, not_host_only, no_physical_rule, no_hardware_rule] {
assert_eq!(
service_s568_model_publish_evidence_matrix(
&mut G8lS568EvidenceMatrixState::new(),
&matrix(),
canonical_s568_image_identity(),
boundary,
),
Err(G8lS568EvidenceMatrixError::DemoBoundaryClaim)
);
}
}
#[test]
fn rendered_table_is_fixed_width_with_stable_checksum() {
let (table, checksum) = render_s568_matrix(&matrix()).unwrap();
let lines: Vec<&str> = table.lines().collect();
assert_eq!(lines.len(), 35);
assert_eq!(S568_ROW_WIDTH, 46);
assert_eq!(S568_TABLE_HEADER.len(), 46);
assert!(lines.iter().all(|line| line.len() == 46));
assert_eq!(lines[0], S568_TABLE_HEADER);
assert_eq!(lines[1], "S536 1 Contract PASS N/A 0 no ");
assert_eq!(lines[5], "S540 1 PhysicalRed RED RED 1 no ");
assert_eq!(lines[8], "S543 1 PhysicalRed RED RED 1 no ");
assert_eq!(lines[11], "S546 1 Contract RED RED-SLNT 1 no ");
assert_eq!(lines[33], "S568 5 Publication PASS N/A 0 no ");
assert!(!table.contains("yes"));
let body_end = table.rfind("CHECKSUM").unwrap();
assert_eq!(s568_fnv1a64(&table.as_bytes()[..body_end]), checksum);
assert_eq!(lines[34].trim_end(), format!("CHECKSUM fnv1a64={checksum:016x}"));
assert_eq!(render_s568_matrix(&matrix()).unwrap(), (table.clone(), checksum));
assert_eq!(published_receipt().table_checksum, checksum);
assert_eq!(published_receipt().table_bytes, table.len());
let mut altered = matrix();
altered.swap(0, 1);
assert_eq!(
render_s568_matrix(&altered),
Err(G8lS568EvidenceMatrixError::SequenceOrder)
);
}
#[test]
fn fnv1a64_matches_known_vectors() {
assert_eq!(s568_fnv1a64(b""), 0xcbf2_9ce4_8422_2325);
assert_eq!(s568_fnv1a64(b"a"), 0xaf63_dc4c_8601_ec8c);
assert_eq!(s568_fnv1a64(b"foobar"), 0x85944171f73967e8);
assert_ne!(s568_fnv1a64(b"S568"), s568_fnv1a64(b"S567"));
}
#[test]
fn stage_titles_cover_exactly_five_stages() {
assert_eq!(s568_stage_title(0), None);
assert_eq!(s568_stage_title(1), Some("boot/Boot-to-UI"));
assert_eq!(s568_stage_title(2), Some("ekran/touch/UI"));
assert_eq!(s568_stage_title(3), Some("modem/ses"));
assert_eq!(s568_stage_title(4), Some("uygulama/recovery/update"));
assert_eq!(s568_stage_title(5), Some("kanit matrisi ve demo siniri"));
assert_eq!(s568_stage_title(6), None);
assert_eq!(S568_R1_STAGE_COUNT, 5);
let kinds = [
G8lS568GateKind::Contract,
G8lS568GateKind::Request,
G8lS568GateKind::Wiring,
G8lS568GateKind::Freeze,
G8lS568GateKind::PhysicalRed,
G8lS568GateKind::Remediation,
G8lS568GateKind::Model,
G8lS568GateKind::Matrix,
G8lS568GateKind::Publication,
];
let labels: BTreeSet<_> = kinds.iter().map(|kind| kind.label()).collect();
assert_eq!(labels.len(), 9);
assert!(labels.iter().all(|label| label.len() <= S568_COLUMN_WIDTHS[2]));
let used: BTreeSet<_> = matrix().iter().map(|row| row.kind.label()).collect();
assert_eq!(used.len(), 9);
let verdicts = [
G8lS568PhysicalVerdict::NotApplicable,
G8lS568PhysicalVerdict::Red,
G8lS568PhysicalVerdict::RedBoot8hAbsentPrimaryFailSilent,
G8lS568PhysicalVerdict::Pending,
G8lS568PhysicalVerdict::Pass,
];
let verdict_labels: BTreeSet<_> = verdicts.iter().map(|verdict| verdict.label()).collect();
assert_eq!(verdict_labels.len(), 5);
assert!(verdict_labels.iter().all(|label| label.len() <= S568_COLUMN_WIDTHS[4]));
}
snippet sha256: 5236ec2e6d47…file sha256: 5236ec2e6d47…
03 · Kapı kimlik kaydı
Operations sıra, kimlik ve başlık bağı
tam Operations kaydıL1838–L1893
website/src/lib/operations.ts::g8l-s568-r1-evidence-matrix-demo-boundary-publication
{
id: "g8l-s568-r1-evidence-matrix-demo-boundary-publication",
date: "2026-08-30",
sequence: 568,
status: "passed",
umbrella_status: "partial",
title: "S568 · R1 kanıt matrisi ve demo sınırı yayını",
summary:
"S568 kaynak kapısı PASS’tir: S536–S568 aralığındaki 33 R1 kapısının her biri için kind/narrow status/physical verdict/hardware satırı içeren kanıt matrisi, 1..5 stage rollup’ı, R1 acceptance predicate’i, S545 reproducible image kimliği (945760 B) ve açık non-claim’li demo sınırı bildirimi host-only model olarak yayınlandı. Matris 30 PASS, 3 RED ve 0 PENDING satır içerir: S540 ve S543 fiziksel RED’lerinin yanına S546 üçüncü fiziksel koşunun kaydedilmiş immutable RED’i (sınıf Boot8hAbsentPrimaryFailSilent; raw 16990 B / a71a9107…3e485d; son satır ASELSAN/BOOT8G, BOOT8H=0, hiçbir hata/panic marker’ı yok) eklendi; üç RED de değişmez tutulur, hiçbir satır artık PENDING değildir ve pending satır fail-closed reddedilir. Acceptance predicate stage 1’de fiziksel PASS ve her Model kapısında donanım kanıtı istediğinden, stage 1 üç RED ve sıfır fiziksel PASS taşırken zorunlu olarak false değerlendirilir; sabit genişlikli 35 satırlık tablo FNV-1a 64 checksum ile kapatılır ve donanım iddia eden her satır fail-closed reddedilir. Focused 21/21 PASS’tir; hardware present=false, physical observation=0, SD/UART/power/new-raw=0/0/0/0, Boot-to-UI=false, R1 acceptance=false ve RUNBOOK_EXECUTED_IN_S568=NO’dur. S569 bir sonraki kapıdır: S546 sessiz primary_fail’inin kaynak remediation’ı planlanır ve S569 → S570 → S571 zinciri plan olup taahhüt değildir; R2 planı S705–S755 bağlayıcı değildir.",
evidence: [
"S568, S536..=S568 aralığındaki 33 kapının her biri için sequence, stage (1..5), kind (Contract/Request/Wiring/Freeze/PhysicalRed/Remediation/Model/Matrix/Publication), narrow status (PASS/RED/PENDING), physical verdict, retained physical observation ve hardware_present alanlarını tek kanonik tabloda modeller.",
"Kanonik matris 30 PASS, 3 RED ve 0 PENDING satır verir; S540 ve S543 satırları immutable PhysicalRed/RED, S546 satırı ise üçüncü fiziksel koşunun kaydedilmiş immutable RED’idir; her RED satırı tam bir retained fiziksel gözlem taşır ve hiçbir RED hiçbir yolla promote edilemez.",
"S546 satırı artık PENDING değildir: fiziksel karar immutable RED’dir — sınıf Boot8hAbsentPrimaryFailSilent, raw 16990 B / a71a9107b4b6ea351eb65720a6b82486105fffdb931563d1c39e8a381c3e485d, son satır ASELSAN/BOOT8G, BOOT8H=0, hiçbir hata/panic/unknown-IRQ marker’ı yok, RUNBOOK_EXECUTED_IN_S546=YES — ve S546 satırını PENDING’e çeviren her girdi PendingRowDrift ile, PASS’e veya düz RED’e çeviren her girdi FixedRedRowDrift ile fail-closed reddedilir.",
"S546’nın kaydedilmiş kaynak nedeni deterministiktir: AcceptanceLedgerNotReady(7) → secondary_fail(43, 544, 7) → sessiz primary_fail; remediation planı S569 (kaynak: R1 marker zincirini erişilemeyen S431–S535 ledger’ından ayır ve G8h primary_fail’e bounded UART hata satırı ekle), S570 (candidate freeze) ve S571 (yetkili fiziksel koşu) sabitleriyle kaydedilir ve plan taahhüt değildir.",
"Stage rollup exact’tır: stage 1 = 11 kapı (8 PASS / 3 RED / 0 PENDING, fiziksel PASS yok), stage 2 = 7, stage 3 = 7, stage 4 = 7, stage 5 = 1; toplam 18 Model kapısının hiçbirinde donanım kanıtı yoktur.",
"R1 acceptance predicate yalnız stage 1’de fiziksel PASS varken, hiçbir satır PENDING değilken ve her Model kapısı donanım kanıtı taşırken true olur; artık hiçbir satır PENDING olmasa da stage 1 üç fiziksel RED ve sıfır fiziksel PASS taşıdığından predicate zorunlu olarak false değerlendirilir ve servis S568_R1_ACCEPTANCE_COMPLETE=false sabitinden saparsa AcceptancePredicateDrift döner.",
"S545 reproducible image kimliği exact pinlenir: 945760 B / ed1901a991e2f9e9ae3c16f254147a2b0180686a8d70ca5d7353374fee08d467; farklı byte sayısı, sequence veya digest ImageIdentityDrift ile reddedilir.",
"Demo sınırı bildirimi beş açık non-claim biti ister: saha güvenilirliği iddiası yok, günlük kullanım iddiası yok, ürün iddiası yok, Boot-to-UI gözlemi iddiası yok, R1 acceptance iddiası yok; eksik bit, bilinmeyen bit veya gevşetilmiş kural DemoBoundaryClaim ile fail-closed döner.",
"Render çıktısı sabit genişlikli 35 satırdır (başlık + 33 satır + checksum trailer), her satır exact 46 karakterdir, toplam 1645 B’dir ve FNV-1a 64 checksum’ı a22a554f442e24b9’dur; S546 satırı RED / RED-SLNT / 1 retained gözlem olarak render edilir.",
"Fail-closed koşullar test edilir: eksik sequence, duplicate sequence, aralık dışı veya sırasız satır, donanım iddia eden herhangi bir satır, üç sabit RED satırı dışında fiziksel gözlem, herhangi bir PASS physical verdict, herhangi bir PENDING satır, stage/entry drift, tablo genişlik drift’i ve yayın sonrası divergence.",
"Exact replay aynı receipt’i Retained olarak döndürür; yayın sonrası farklı girdi PublishedStateDrift ile reddedilir ve 18 diagnostic kodun tümü sıfırdan farklı ve benzersizdir.",
"Focused target 1 grup / 21 passed / 0 failed / 0 ignored / 0 filtered verdi.",
"Modül production callsite içermez; boot, IRQ, scheduler veya driver yoluna bağlanmaz; unsafe, MMIO, asm!, UART veya arch referansı içermez.",
"Implementation 27967 B / b03d60ea6f989f090c4190fa3cf1610cd6da1ecc065166fc1dfe0c6e6aefe8c4; focused test 24215 B / 5236ec2e6d476a0bd050f13f167ecccbbcfcef7102cfe809abda2dcb9bd17556 SHA-256’dır.",
"Proof 5503 B’dir.",
"S568 sırasında SD write/read-back/eject, UART open/capture, power transition, fiziksel koşu veya yeni immutable raw üretimi yapılmadı; hiçbir panel/modem/touch/board gözlemi yoktur.",
"RUNBOOK_EXECUTED_IN_S568=NO; supported-profile runtime observations=0, physical observations=0, hardware present=false, Boot-to-UI physically observed=false ve R1 acceptance complete=false’dur.",
"S569 bir sonraki kapıdır ve S546 remediation zincirinin kaynak adımıdır; stage 1 kararını ancak zincirin ayrı yetkili fiziksel koşusu (S571 planı) değiştirebilir, plan taahhüt değildir ve R2 planlaması S705–S755 bağlayıcı değildir.",
],
commands: [
"cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication -- --test-threads=1",
],
terminalSessions: [
{
id: "s568-focused",
title: "S568 R1 kanıt matrisi ve demo sınırı focused koşusu",
commandLines: [
"cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication -- --test-threads=1",
],
outputLines: [
"test result: ok. 21 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s",
"S568 focused=1 group / 21 passed / 0 failed",
"hardware=none physical=0 runbook=NO",
],
exitCode: 0,
outputMode: "complete",
},
],
limitations: [
"S568 yalnız host/source model kapısıdır; kanıt matrisi hiçbir satırda donanım kanıtı iddia etmez ve hiçbir donanım/panel/modem/board gözlemi yoktur.",
"S540 ve S543 fiziksel RED immutable kalır ve S546 üçüncü koşunun kaydedilmiş fiziksel RED’i de immutable’dır; otomatik promotion yoktur ve hiçbir raw yeniden yorumlanmaz.",
"S546 fiziksel kararı immutable RED’dir (Boot8hAbsentPrimaryFailSilent, raw 16990 B); koşu tekrarlanamaz ve geriye dönük yükseltilemez, stage 1’i ancak S569 → S570 → S571 remediation zincirinin ayrı yetkili fiziksel koşusu değiştirebilir ve bu zincir plan olup taahhüt değildir.",
"R1 acceptance predicate false’dur; saha güvenilirliği, günlük kullanım veya ürün iddiası kurulmaz ve Boot-to-UI fiziksel olarak gözlenmemiştir.",
"S569 sonraki kapıdır ve S546 sessiz primary_fail’inin kaynak remediation’ıdır; R2 planlaması S705–S755 bağlayıcı değildir ve hiçbir yeni fiziksel yetki vermez.",
],
},snippet sha256: a6cbe0c42d38…file sha256: 9726dbf00f84…
Focused test komutu
cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s568_r1_evidence_matrix_demo_boundary_publication -- --test-threads=1proof: docs/M8.1-RPi5-G8l-S545-S568-R1-Evidence-Audit.md
Registry schema v5 · generator
website/scripts/generate-code-gates.mjs · Tam SHA-256: 91d38c7b6222f0b4c117be786454853543da55a160e543d9b951057cc20dcc06