pub struct VerificationReport {Show 19 fields
pub verified: bool,
pub bitwise_parity: bool,
pub verdict: Verdict,
pub no_result_reason: Option<NoResultReason>,
pub infrastructure_error: Option<InfrastructureError>,
pub comparison: Option<ComparisonReport>,
pub compared_log_messages: Option<ComparedLogMessages>,
pub compared_outputs: Option<ComparedOutputs>,
pub dbt_counted_branches: Option<DbtCountedBranchComparison>,
pub runtime: Option<VerificationRuntime>,
pub guest_exit_code: Option<i32>,
pub guest_signal: Option<i32>,
pub first_divergent_scheduler_turn: Option<u64>,
pub first_divergent_virtual_nanoseconds: Option<u64>,
pub first_divergent_record: Option<u64>,
pub first_divergent_syscall: Option<u64>,
pub first_divergent_left_message: Option<String>,
pub first_divergent_right_message: Option<String>,
pub exact_branch_counter: Option<BranchCounterVerdict>,
}Expand description
The complete machine-readable report written by --verify-json.
This type is shared by the Hermit producer, the manifest runner, the compatibility pressure test, and the scorecard. The serialized field order is retained because existing report bytes are hashed as evidence.
Fields§
§verified: bool§bitwise_parity: bool§verdict: Verdict§no_result_reason: Option<NoResultReason>§infrastructure_error: Option<InfrastructureError>§comparison: Option<ComparisonReport>None when the producer reached no verdict. This is a DOCUMENTED
producer state, not a malformed report: VerificationReport::no_result()
in hermit-cli sets it, and its doc says “null when no verdict was
reached”. Declaring it non-optional made a legitimate no-result
deserialise as “unreadable report”, which reported an infrastructure
fault where the truth was that nothing had been recorded.
compared_log_messages: Option<ComparedLogMessages>§compared_outputs: Option<ComparedOutputs>Exact output/status evidence for both executions. Optional only so retained reports written before this field remain readable.
dbt_counted_branches: Option<DbtCountedBranchComparison>§runtime: Option<VerificationRuntime>Runtime totals for the two compared executions when the producer could read both run summaries.
guest_exit_code: Option<i32>The guest’s exit code when an exited status was available to the
producer. None means either that guest_signal records a signal
disposition, or that execution did not return a guest status at all;
current producers must not leave this null for ExitStatus::Exited.
guest_signal: Option<i32>The guest’s signal when a signaled status was available to the producer. When both disposition fields are null, the writer had no guest status.
first_divergent_scheduler_turn: Option<u64>WHERE the divergence began, in scheduler-turn units. None when the
logs matched, when no comparison ran, or when the report predates the
field.
#[serde(default)] is deliberate here and is the OPPOSITE choice from
ComparisonReport::record_envelope above. That field is an admission
gate, so a missing value must never be supplied on the producer’s
behalf. This one is a diagnostic position: absent means “not located”,
which is exactly what None says. Requiring it would turn every
retained pre-field report into an unreadable-report ERROR and
misclassify old evidence as an infrastructure fault – the same trap
documented on comparison just above.
first_divergent_virtual_nanoseconds: Option<u64>WHERE the divergence began, in virtual-nanosecond units. Same tolerant-default rationale as the field above.
NOTE both of these are the position of the PRECEDING scheduler COMMIT, so when no COMMIT precedes the differing record they collapse to the origin and BOUND the divergence rather than locating it. The field below is the one that locates it.
first_divergent_record: Option<u64>1-based index of the first differing compared record – the LOCATION of
the divergence rather than a bound on it, and the only one of the three
that is a true log prefix. It shares a unit with
compared_log_messages, so record / compared is the fraction of the
log that was deterministic.
null and 0 are not the same claim: null is “no divergence located”,
while 0 would mean the very first record differed. Nothing writes 0 –
the index is 1-based. Same tolerant-default rationale as its siblings.
first_divergent_syscall: Option<u64>How many syscalls the guest had COMPLETED when the divergence appeared,
from detcore’s own finish syscall #N counter.
NOT interchangeable with first_divergent_record: one counts guest work
and the other counts compared log records, and they move at completely
different rates. Measured on one real divergence: record 98, syscall 37.
null also covers a genuine state – a run that diverged before any
syscall completed.
first_divergent_left_message: Option<String>First differing compared message from the left execution, with the separately recorded syscall number, scheduler turn, and committed time removed. Older reports omit it and remain readable.
first_divergent_right_message: Option<String>Corresponding first differing compared message from the right execution.
exact_branch_counter: Option<BranchCounterVerdict>Whether the retired-branch counter that this run’s virtual clock and
preemption points came from was exact on the producing host: the same
verdict hermit host-capabilities reports as exact_branch_counter
(https://github.com/rrnewton/hermit/issues/3794). Present for a run
on a backend that reads that counter (ptrace, e9patch, and record start); absent for another backend, and in a report written before
this field.
Implementations§
Source§impl VerificationReport
impl VerificationReport
pub fn no_result() -> Self
Sourcepub fn from_json_slice(bytes: &[u8]) -> Result<Self, String>
pub fn from_json_slice(bytes: &[u8]) -> Result<Self, String>
Parse the complete typed receipt. A top-level JSON object is not enough: every nested field used by admission must deserialize successfully.
pub fn from_json_value(value: Value) -> Result<Self, String>
Sourcepub fn from_current_json_slice(bytes: &[u8]) -> Result<Self, String>
pub fn from_current_json_slice(bytes: &[u8]) -> Result<Self, String>
Parse a report written by the current producer and require every field it promises to emit, preserving duplicate-field refusal from the original bytes. Parsing only a Value would silently collapse duplicate object keys.
Sourcepub fn from_current_json_value(value: Value) -> Result<Self, String>
pub fn from_current_json_value(value: Value) -> Result<Self, String>
Parse a report written by the current producer and require every field
that producer promises to emit. Retained-report readers use
Self::from_json_value instead so fields added after an old run remain
honest absence rather than making the whole report unreadable.
Sourcepub fn from_retained_cell_json_slice(bytes: &[u8]) -> Result<Self, String>
pub fn from_retained_cell_json_slice(bytes: &[u8]) -> Result<Self, String>
Parse a retained cell receipt from before exact output evidence was added. Preserve that absence while retaining the other producer-field and duplicate-key requirements. This is not current producer admission and must not be used for either operand of backend parity.
Sourcepub fn require_canonical_comparison(&self) -> Result<(), String>
pub fn require_canonical_comparison(&self) -> Result<(), String>
Prove that the invocation actually compared the canonical INFO evidence. This is separate from whether that comparison matched: a canonical divergence is a product result, while a stripped/output-only/empty-log comparison is incomplete evidence and therefore an infrastructure result.
Sourcepub fn require_exact_output_match(&self) -> Result<(), String>
pub fn require_exact_output_match(&self) -> Result<(), String>
Require complete, identical guest outputs for a current strict operand. Historical log-only receipts retain their separate admission path.
Sourcepub fn require_canonical_match(&self) -> Result<(), String>
pub fn require_canonical_match(&self) -> Result<(), String>
Admit a green only when both the canonical comparison and the match
claim agree. verified=true alone is intentionally insufficient: KVM’s
output-only fallback can report it with zero compared INFO messages.
Trait Implementations§
Source§impl Clone for VerificationReport
impl Clone for VerificationReport
Source§fn clone(&self) -> VerificationReport
fn clone(&self) -> VerificationReport
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for VerificationReport
impl Debug for VerificationReport
Source§impl<'de> Deserialize<'de> for VerificationReport
impl<'de> Deserialize<'de> for VerificationReport
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for VerificationReport
impl PartialEq for VerificationReport
Source§impl Serialize for VerificationReport
impl Serialize for VerificationReport
impl StructuralPartialEq for VerificationReport
Auto Trait Implementations§
impl Freeze for VerificationReport
impl RefUnwindSafe for VerificationReport
impl Send for VerificationReport
impl Sync for VerificationReport
impl Unpin for VerificationReport
impl UnsafeUnpin for VerificationReport
impl UnwindSafe for VerificationReport
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling [Attribute] value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi [Quirk] value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the [Condition] value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.