///|
/// Runtime data types accepted by a production change-point pipeline.
pub(all) enum ProductionContractFieldKind {
Numeric
Timestamp
Sequence
Label
Boolean
}
///|
pub fn production_contract_field_kind_name(
kind : ProductionContractFieldKind,
) -> String {
match kind {
Numeric => "numeric"
Timestamp => "timestamp"
Sequence => "sequence"
Label => "label"
Boolean => "boolean"
}
}
///|
/// Validation severity used by a data contract.
pub(all) enum ProductionContractSeverity {
ContractError
ContractWarning
}
///|
pub fn production_contract_severity_name(
severity : ProductionContractSeverity,
) -> String {
match severity {
ContractError => "error"
ContractWarning => "warning"
}
}
///|
/// Machine-readable reason for rejecting or downgrading an observation.
pub(all) enum ProductionContractViolationCode {
MissingMetric
MissingValue
NonFiniteValue
ValueBelowMinimum
ValueAboveMaximum
TimestampOutOfOrder
TimestampTooOld
DuplicateSequence
EmptyLabel
LabelTooLong
InvalidBoolean
InsufficientSamples
ExcessiveGap
CardinalityExceeded
SchemaMismatch
}
///|
pub fn production_contract_violation_code_name(
code : ProductionContractViolationCode,
) -> String {
match code {
MissingMetric => "missing-metric"
MissingValue => "missing-value"
NonFiniteValue => "non-finite-value"
ValueBelowMinimum => "below-minimum"
ValueAboveMaximum => "above-maximum"
TimestampOutOfOrder => "timestamp-out-of-order"
TimestampTooOld => "timestamp-too-old"
DuplicateSequence => "duplicate-sequence"
EmptyLabel => "empty-label"
LabelTooLong => "label-too-long"
InvalidBoolean => "invalid-boolean"
InsufficientSamples => "insufficient-samples"
ExcessiveGap => "excessive-gap"
CardinalityExceeded => "cardinality-exceeded"
SchemaMismatch => "schema-mismatch"
}
}
///|
/// Declarative validation rules for a metric stream.
pub struct ProductionContractRule {
name : String
field_kind : ProductionContractFieldKind
required : Bool
allow_missing : Bool
minimum : Double
maximum : Double
has_minimum : Bool
has_maximum : Bool
minimum_samples : Int
maximum_gap : Int64
monotonic_timestamps : Bool
maximum_label_length : Int
maximum_distinct_values : Int
severity : ProductionContractSeverity
}
///|
pub fn ProductionContractRule::new(
name : String,
field_kind? : ProductionContractFieldKind = Numeric,
required? : Bool = true,
allow_missing? : Bool = false,
minimum? : Double = 0.0,
maximum? : Double = 0.0,
has_minimum? : Bool = false,
has_maximum? : Bool = false,
minimum_samples? : Int = 1,
maximum_gap? : Int64 = 0L,
monotonic_timestamps? : Bool = true,
maximum_label_length? : Int = 128,
maximum_distinct_values? : Int = 1000,
severity? : ProductionContractSeverity = ContractError,
) -> ProductionContractRule {
{
name,
field_kind,
required,
allow_missing,
minimum,
maximum,
has_minimum,
has_maximum,
minimum_samples: if minimum_samples < 1 {
1
} else {
minimum_samples
},
maximum_gap: if maximum_gap < 0L {
0L
} else {
maximum_gap
},
monotonic_timestamps,
maximum_label_length: if maximum_label_length < 1 {
1
} else {
maximum_label_length
},
maximum_distinct_values: if maximum_distinct_values < 1 {
1
} else {
maximum_distinct_values
},
severity,
}
}
///|
pub fn ProductionContractRule::name(self : ProductionContractRule) -> String {
self.name
}
///|
pub fn ProductionContractRule::field_kind(
self : ProductionContractRule,
) -> ProductionContractFieldKind {
self.field_kind
}
///|
pub fn ProductionContractRule::required(self : ProductionContractRule) -> Bool {
self.required
}
///|
pub fn ProductionContractRule::allow_missing(
self : ProductionContractRule,
) -> Bool {
self.allow_missing
}
///|
pub fn ProductionContractRule::minimum(self : ProductionContractRule) -> Double {
self.minimum
}
///|
pub fn ProductionContractRule::maximum(self : ProductionContractRule) -> Double {
self.maximum
}
///|
pub fn ProductionContractRule::has_minimum(
self : ProductionContractRule,
) -> Bool {
self.has_minimum
}
///|
pub fn ProductionContractRule::has_maximum(
self : ProductionContractRule,
) -> Bool {
self.has_maximum
}
///|
pub fn ProductionContractRule::minimum_samples(
self : ProductionContractRule,
) -> Int {
self.minimum_samples
}
///|
pub fn ProductionContractRule::maximum_gap(
self : ProductionContractRule,
) -> Int64 {
self.maximum_gap
}
///|
pub fn ProductionContractRule::monotonic_timestamps(
self : ProductionContractRule,
) -> Bool {
self.monotonic_timestamps
}
///|
pub fn ProductionContractRule::maximum_label_length(
self : ProductionContractRule,
) -> Int {
self.maximum_label_length
}
///|
pub fn ProductionContractRule::maximum_distinct_values(
self : ProductionContractRule,
) -> Int {
self.maximum_distinct_values
}
///|
pub fn ProductionContractRule::severity(
self : ProductionContractRule,
) -> ProductionContractSeverity {
self.severity
}
///|
/// One contract violation retained for audit and diagnostics.
pub struct ProductionContractViolation {
code : ProductionContractViolationCode
severity : ProductionContractSeverity
metric : String
rule : String
index : Int
value : Double
has_value : Bool
message : String
}
///|
pub fn ProductionContractViolation::new(
code : ProductionContractViolationCode,
severity : ProductionContractSeverity,
metric : String,
rule : String,
index? : Int = -1,
value? : Double = 0.0,
has_value? : Bool = false,
message? : String = "",
) -> ProductionContractViolation {
{ code, severity, metric, rule, index, value, has_value, message }
}
///|
pub fn ProductionContractViolation::code(
self : ProductionContractViolation,
) -> ProductionContractViolationCode {
self.code
}
///|
pub fn ProductionContractViolation::severity(
self : ProductionContractViolation,
) -> ProductionContractSeverity {
self.severity
}
///|
pub fn ProductionContractViolation::metric(
self : ProductionContractViolation,
) -> String {
self.metric
}
///|
pub fn ProductionContractViolation::rule(
self : ProductionContractViolation,
) -> String {
self.rule
}
///|
pub fn ProductionContractViolation::index(
self : ProductionContractViolation,
) -> Int {
self.index
}
///|
pub fn ProductionContractViolation::has_value(
self : ProductionContractViolation,
) -> Bool {
self.has_value
}
///|
pub fn ProductionContractViolation::value(
self : ProductionContractViolation,
) -> Double {
self.value
}
///|
pub fn ProductionContractViolation::message(
self : ProductionContractViolation,
) -> String {
self.message
}
///|
pub fn ProductionContractViolation::summary(
self : ProductionContractViolation,
) -> String {
let location = if self.index < 0 {
"stream"
} else {
"sample[" + self.index.to_string() + "]"
}
let value_text = if self.has_value {
" value=" + self.value.to_string()
} else {
""
}
production_contract_severity_name(self.severity) +
" " +
self.metric +
" " +
location +
" " +
production_contract_violation_code_name(self.code) +
value_text +
" " +
self.message
}
///|
/// Result of validating one metric stream.
pub struct ProductionContractReport {
metric : String
mut checked : Int
mut accepted : Int
mut rejected : Int
missing : Int
mut warnings : Int
violations : Array[ProductionContractViolation]
distinct_labels : Array[String]
mut first_timestamp : Int64
mut last_timestamp : Int64
mut has_timestamp : Bool
mut monotonic : Bool
}
///|
pub fn ProductionContractReport::new(
metric : String,
) -> ProductionContractReport {
{
metric,
checked: 0,
accepted: 0,
rejected: 0,
missing: 0,
warnings: 0,
violations: [],
distinct_labels: [],
first_timestamp: 0L,
last_timestamp: 0L,
has_timestamp: false,
monotonic: true,
}
}
///|
pub fn ProductionContractReport::metric(
self : ProductionContractReport,
) -> String {
self.metric
}
///|
pub fn ProductionContractReport::checked(
self : ProductionContractReport,
) -> Int {
self.checked
}
///|
pub fn ProductionContractReport::accepted(
self : ProductionContractReport,
) -> Int {
self.accepted
}
///|
pub fn ProductionContractReport::rejected(
self : ProductionContractReport,
) -> Int {
self.rejected
}
///|
pub fn ProductionContractReport::missing(
self : ProductionContractReport,
) -> Int {
self.missing
}
///|
pub fn ProductionContractReport::warnings(
self : ProductionContractReport,
) -> Int {
self.warnings
}
///|
pub fn ProductionContractReport::violations(
self : ProductionContractReport,
) -> Array[ProductionContractViolation] {
self.violations[:].to_owned()
}
///|
pub fn ProductionContractReport::distinct_count(
self : ProductionContractReport,
) -> Int {
self.distinct_labels.length()
}
///|
pub fn ProductionContractReport::first_timestamp(
self : ProductionContractReport,
) -> Int64 {
self.first_timestamp
}
///|
pub fn ProductionContractReport::last_timestamp(
self : ProductionContractReport,
) -> Int64 {
self.last_timestamp
}
///|
pub fn ProductionContractReport::monotonic(
self : ProductionContractReport,
) -> Bool {
self.monotonic
}
///|
pub fn ProductionContractReport::acceptance_rate(
self : ProductionContractReport,
) -> Double {
if self.checked == 0 {
1.0
} else {
self.accepted.to_double() / self.checked.to_double()
}
}
///|
pub fn ProductionContractReport::is_valid(
self : ProductionContractReport,
) -> Bool {
self.rejected == 0 && self.accepted >= 0
}
///|
pub fn ProductionContractReport::summary(
self : ProductionContractReport,
) -> String {
self.metric +
" checked=" +
self.checked.to_string() +
" accepted=" +
self.accepted.to_string() +
" rejected=" +
self.rejected.to_string() +
" missing=" +
self.missing.to_string() +
" warnings=" +
self.warnings.to_string() +
" rate=" +
self.acceptance_rate().to_string()
}
///|
/// A compact contract snapshot suitable for health endpoints.
pub struct ProductionContractSummary {
contract_count : Int
report_count : Int
valid_count : Int
rejected_count : Int
warning_count : Int
total_samples : Int
total_violations : Int
}
///|
pub fn ProductionContractSummary::contract_count(
self : ProductionContractSummary,
) -> Int {
self.contract_count
}
///|
pub fn ProductionContractSummary::report_count(
self : ProductionContractSummary,
) -> Int {
self.report_count
}
///|
pub fn ProductionContractSummary::valid_count(
self : ProductionContractSummary,
) -> Int {
self.valid_count
}
///|
pub fn ProductionContractSummary::rejected_count(
self : ProductionContractSummary,
) -> Int {
self.rejected_count
}
///|
pub fn ProductionContractSummary::warning_count(
self : ProductionContractSummary,
) -> Int {
self.warning_count
}
///|
pub fn ProductionContractSummary::total_samples(
self : ProductionContractSummary,
) -> Int {
self.total_samples
}
///|
pub fn ProductionContractSummary::total_violations(
self : ProductionContractSummary,
) -> Int {
self.total_violations
}
///|
pub fn ProductionContractSummary::health_score(
self : ProductionContractSummary,
) -> Double {
if self.total_samples == 0 {
1.0
} else {
let failures = self.rejected_count.to_double()
let samples = self.total_samples.to_double()
clamp_probability(1.0 - failures / samples)
}
}
///|
/// Runtime validator for metric contracts. Rules stay in memory so a service
/// can validate every batch without rebuilding schema state.
pub struct ProductionContractValidator {
mut rules : Array[ProductionContractRule]
mut reports : Array[ProductionContractReport]
mut total_batches : Int
mut total_samples : Int
mut total_violations : Int
}
///|
pub fn ProductionContractValidator::new() -> ProductionContractValidator {
{
rules: [],
reports: [],
total_batches: 0,
total_samples: 0,
total_violations: 0,
}
}
///|
fn production_contract_index_of(
rules : Array[ProductionContractRule],
name : String,
) -> Int {
for i = 0; i < rules.length(); i = i + 1 {
if rules[i].name() == name {
return i
}
}
-1
}
///|
pub fn ProductionContractValidator::register(
self : ProductionContractValidator,
rule : ProductionContractRule,
) -> Bool {
let index = production_contract_index_of(self.rules, rule.name())
if index < 0 {
self.rules.push(rule)
true
} else {
self.rules[index] = rule
false
}
}
///|
pub fn ProductionContractValidator::remove(
self : ProductionContractValidator,
name : String,
) -> Bool {
let index = production_contract_index_of(self.rules, name)
if index < 0 {
false
} else {
let remaining : Array[ProductionContractRule] = []
for i = 0; i < self.rules.length(); i = i + 1 {
if i != index {
remaining.push(self.rules[i])
}
}
self.rules = remaining
true
}
}
///|
pub fn ProductionContractValidator::rule_count(
self : ProductionContractValidator,
) -> Int {
self.rules.length()
}
///|
pub fn ProductionContractValidator::rules(
self : ProductionContractValidator,
) -> Array[ProductionContractRule] {
self.rules[:].to_owned()
}
///|
pub fn ProductionContractValidator::reports(
self : ProductionContractValidator,
) -> Array[ProductionContractReport] {
self.reports[:].to_owned()
}
///|
pub fn ProductionContractValidator::total_batches(
self : ProductionContractValidator,
) -> Int {
self.total_batches
}
///|
pub fn ProductionContractValidator::total_samples(
self : ProductionContractValidator,
) -> Int {
self.total_samples
}
///|
pub fn ProductionContractValidator::total_violations(
self : ProductionContractValidator,
) -> Int {
self.total_violations
}
///|
fn production_contract_violation_is_warning(
violation : ProductionContractViolation,
) -> Bool {
violation.severity() is ContractWarning
}
///|
fn production_contract_contains_label(
labels : Array[String],
label : String,
) -> Bool {
for item in labels {
if item == label {
return true
}
}
false
}
///|
fn production_contract_push_violation(
report : ProductionContractReport,
violation : ProductionContractViolation,
) -> Unit {
report.violations.push(violation)
if production_contract_violation_is_warning(violation) {
report.warnings = report.warnings + 1
} else {
report.rejected = report.rejected + 1
}
}
///|
fn production_contract_is_finite(value : Double) -> Bool {
value == value && value > -1.0e308 && value < 1.0e308
}
///|
fn production_contract_validate_numeric(
rule : ProductionContractRule,
report : ProductionContractReport,
index : Int,
value : Double,
) -> Bool {
let mut valid = true
if !production_contract_is_finite(value) {
production_contract_push_violation(
report,
ProductionContractViolation::new(
NonFiniteValue,
rule.severity(),
rule.name(),
rule.name(),
index~,
value~,
has_value=true,
message="numeric value is not finite",
),
)
valid = false
}
if rule.has_minimum() && value < rule.minimum() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
ValueBelowMinimum,
rule.severity(),
rule.name(),
rule.name(),
index~,
value~,
has_value=true,
message="value is below the contract minimum",
),
)
valid = false
}
if rule.has_maximum() && value > rule.maximum() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
ValueAboveMaximum,
rule.severity(),
rule.name(),
rule.name(),
index~,
value~,
has_value=true,
message="value is above the contract maximum",
),
)
valid = false
}
valid
}
///|
fn production_contract_validate_labels(
rule : ProductionContractRule,
report : ProductionContractReport,
index : Int,
label : String,
) -> Bool {
let mut valid = true
if label.length() == 0 {
production_contract_push_violation(
report,
ProductionContractViolation::new(
EmptyLabel,
rule.severity(),
rule.name(),
rule.name(),
index~,
message="label must not be empty",
),
)
valid = false
}
if label.length() > rule.maximum_label_length() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
LabelTooLong,
rule.severity(),
rule.name(),
rule.name(),
index~,
message="label exceeds the configured length",
),
)
valid = false
}
if !production_contract_contains_label(report.distinct_labels, label) {
report.distinct_labels.push(label)
}
if report.distinct_labels.length() > rule.maximum_distinct_values() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
CardinalityExceeded,
rule.severity(),
rule.name(),
rule.name(),
index~,
message="label cardinality exceeds the configured limit",
),
)
valid = false
}
valid
}
///|
fn production_contract_update_timestamp(
rule : ProductionContractRule,
report : ProductionContractReport,
index : Int,
timestamp : Int64,
) -> Bool {
let mut valid = true
if report.has_timestamp {
if timestamp < report.last_timestamp {
report.monotonic = false
if rule.monotonic_timestamps() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
TimestampOutOfOrder,
rule.severity(),
rule.name(),
rule.name(),
index~,
message="timestamps must be monotonic",
),
)
valid = false
}
}
if rule.maximum_gap() > 0L &&
timestamp - report.last_timestamp > rule.maximum_gap() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
ExcessiveGap,
rule.severity(),
rule.name(),
rule.name(),
index~,
message="timestamp gap exceeds the contract",
),
)
valid = false
}
} else {
report.first_timestamp = timestamp
report.has_timestamp = true
}
if timestamp > report.last_timestamp || !report.has_timestamp {
report.last_timestamp = timestamp
}
valid
}
///|
/// Validate numeric samples and event-time ordering for one metric batch.
pub fn ProductionContractValidator::validate_numeric_batch(
self : ProductionContractValidator,
metric : String,
timestamps : Array[Int64],
values : Array[Double],
) -> ProductionContractReport {
let rule_index = production_contract_index_of(self.rules, metric)
let rule = if rule_index < 0 {
ProductionContractRule::new(metric, required=false, allow_missing=true)
} else {
self.rules[rule_index]
}
let report = ProductionContractReport::new(metric)
let count = if timestamps.length() < values.length() {
timestamps.length()
} else {
values.length()
}
self.total_batches = self.total_batches + 1
self.total_samples = self.total_samples + count
for i = 0; i < count; i = i + 1 {
report.checked = report.checked + 1
let time_valid = production_contract_update_timestamp(
rule,
report,
i,
timestamps[i],
)
let value_valid = production_contract_validate_numeric(
rule,
report,
i,
values[i],
)
if time_valid && value_valid {
report.accepted = report.accepted + 1
}
}
if timestamps.length() != values.length() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
SchemaMismatch,
ContractError,
metric,
metric,
message="timestamps and values have different lengths",
),
)
}
if report.checked < rule.minimum_samples() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
InsufficientSamples,
rule.severity(),
metric,
metric,
message="batch contains fewer samples than required",
),
)
}
self.total_violations = self.total_violations + report.violations.length()
self.reports.push(report)
report
}
///|
/// Validate categorical labels while tracking bounded cardinality.
pub fn ProductionContractValidator::validate_label_batch(
self : ProductionContractValidator,
metric : String,
timestamps : Array[Int64],
labels : Array[String],
) -> ProductionContractReport {
let rule_index = production_contract_index_of(self.rules, metric)
let rule = if rule_index < 0 {
ProductionContractRule::new(
metric,
field_kind=Label,
required=false,
allow_missing=true,
)
} else {
self.rules[rule_index]
}
let report = ProductionContractReport::new(metric)
let count = if timestamps.length() < labels.length() {
timestamps.length()
} else {
labels.length()
}
self.total_batches = self.total_batches + 1
self.total_samples = self.total_samples + count
for i = 0; i < count; i = i + 1 {
report.checked = report.checked + 1
let time_valid = production_contract_update_timestamp(
rule,
report,
i,
timestamps[i],
)
let label_valid = production_contract_validate_labels(
rule,
report,
i,
labels[i],
)
if time_valid && label_valid {
report.accepted = report.accepted + 1
}
}
if timestamps.length() != labels.length() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
SchemaMismatch,
ContractError,
metric,
metric,
message="timestamps and labels have different lengths",
),
)
}
if report.checked < rule.minimum_samples() {
production_contract_push_violation(
report,
ProductionContractViolation::new(
InsufficientSamples,
rule.severity(),
metric,
metric,
message="batch contains fewer labels than required",
),
)
}
self.total_violations = self.total_violations + report.violations.length()
self.reports.push(report)
report
}
///|
/// Validate a batch and return only the samples accepted by the contract.
pub fn ProductionContractValidator::filter_numeric_batch(
self : ProductionContractValidator,
metric : String,
timestamps : Array[Int64],
values : Array[Double],
) -> (Array[Int64], Array[Double], ProductionContractReport) {
let report = self.validate_numeric_batch(metric, timestamps, values)
let accepted_times : Array[Int64] = []
let accepted_values : Array[Double] = []
let rule_index = production_contract_index_of(self.rules, report.metric())
let rule = if rule_index < 0 {
ProductionContractRule::new(
report.metric(),
required=false,
allow_missing=true,
)
} else {
self.rules[rule_index]
}
let count = if timestamps.length() < values.length() {
timestamps.length()
} else {
values.length()
}
for i = 0; i < count; i = i + 1 {
let numeric_ok = production_contract_is_finite(values[i]) &&
(!rule.has_minimum() || values[i] >= rule.minimum()) &&
(!rule.has_maximum() || values[i] <= rule.maximum())
if numeric_ok {
accepted_times.push(timestamps[i])
accepted_values.push(values[i])
}
}
(accepted_times, accepted_values, report)
}
///|
pub fn ProductionContractValidator::latest_report(
self : ProductionContractValidator,
) -> ProductionContractReport? {
if self.reports.length() == 0 {
None
} else {
Some(self.reports[self.reports.length() - 1])
}
}
///|
pub fn ProductionContractValidator::summary(
self : ProductionContractValidator,
) -> ProductionContractSummary {
let mut valid_count = 0
let mut rejected_count = 0
let mut warning_count = 0
let mut violations = 0
for report in self.reports {
if report.is_valid() {
valid_count = valid_count + 1
}
rejected_count = rejected_count + report.rejected()
warning_count = warning_count + report.warnings()
violations = violations + report.violations.length()
}
{
contract_count: self.rules.length(),
report_count: self.reports.length(),
valid_count,
rejected_count,
warning_count,
total_samples: self.total_samples,
total_violations: violations,
}
}
///|
pub fn ProductionContractValidator::clear_reports(
self : ProductionContractValidator,
) -> Unit {
self.reports = []
self.total_batches = 0
self.total_samples = 0
self.total_violations = 0
}
///|
/// Returns whether a timestamp series is non-decreasing.
pub fn production_validate_monotonic_timestamps(
timestamps : Array[Int64],
) -> Bool {
if timestamps.length() < 2 {
true
} else {
for i = 1; i < timestamps.length(); i = i + 1 {
if timestamps[i] < timestamps[i - 1] {
return false
}
}
true
}
}
///|
/// Returns the largest time gap in a timestamp series.
pub fn production_contract_largest_gap(timestamps : Array[Int64]) -> Int64 {
let mut largest = 0L
if timestamps.length() > 1 {
for i = 1; i < timestamps.length(); i = i + 1 {
let gap = timestamps[i] - timestamps[i - 1]
if gap > largest {
largest = gap
}
}
}
largest
}
///|
pub fn production_contract_distinct_labels(labels : Array[String]) -> Int {
let distinct : Array[String] = []
for label in labels {
if !production_contract_contains_label(distinct, label) {
distinct.push(label)
}
}
distinct.length()
}
///|
/// Stable, order-sensitive checksum for a contract definition.
pub fn production_contract_checksum(rule : ProductionContractRule) -> String {
let seed = rule.name().length().to_string() +
":" +
production_contract_field_kind_name(rule.field_kind()) +
":" +
rule.minimum_samples().to_string() +
":" +
rule.maximum_gap().to_string() +
":" +
rule.maximum_label_length().to_string() +
":" +
rule.maximum_distinct_values().to_string()
let mut hash = 216613626
for character in seed {
hash = (hash * 16777619 + character.to_int()) % 2147483647
}
hash.to_string()
}
///|
pub fn production_contract_report_json(
report : ProductionContractReport,
) -> String {
let monotonic_text = if report.monotonic() { "true" } else { "false" }
"{\"metric\":\"" +
report.metric() +
"\",\"checked\":" +
report.checked().to_string() +
",\"accepted\":" +
report.accepted().to_string() +
",\"rejected\":" +
report.rejected().to_string() +
",\"warnings\":" +
report.warnings().to_string() +
",\"monotonic\":" +
monotonic_text +
"}"
}
///|
pub fn production_contract_summary_markdown(
summary : ProductionContractSummary,
) -> String {
"| contracts | reports | samples | rejected | warnings | health |\n" +
"| ---: | ---: | ---: | ---: | ---: | ---: |\n" +
"| " +
summary.contract_count().to_string() +
" | " +
summary.report_count().to_string() +
" | " +
summary.total_samples().to_string() +
" | " +
summary.rejected_count().to_string() +
" | " +
summary.warning_count().to_string() +
" | " +
summary.health_score().to_string() +
" |"
}