///|
/// Operational service-level metrics for analytics pipelines.
pub struct ServiceMetric {
  name : String
  value : Double
  target : Double
  status : String
}

///|
pub struct ServiceSummary {
  metrics : Array[ServiceMetric]
  score : Double
  status : String
}

///|
pub fn service_metric(
  name : String,
  value : Double,
  target : Double,
) -> ServiceMetric {
  {
    name,
    value,
    target,
    status: if value >= target {
      "healthy"
    } else {
      "review"
    },
  }
}

///|
pub fn service_summary(metrics : Array[ServiceMetric]) -> ServiceSummary {
  let mut total = 0.0
  let mut healthy = 0
  for metric in metrics {
    total += transform_clip(
      if metric.target == 0.0 {
        metric.value
      } else {
        metric.value / metric.target
      },
      0.0,
      1.0,
    )
    if metric.status == "healthy" {
      healthy += 1
    }
  }
  let score = if metrics.length() == 0 {
    1.0
  } else {
    total / metrics.length().to_double()
  }
  {
    metrics,
    score,
    status: if healthy == metrics.length() {
      "healthy"
    } else {
      "review"
    },
  }
}

///|
pub fn service_completeness(data : Array[Double]) -> ServiceMetric {
  let missing = quality_missing_indices(data).length()
  let value = if data.length() == 0 {
    1.0
  } else {
    1.0 - missing.to_double() / data.length().to_double()
  }
  service_metric("completeness", value, 0.99)
}

///|
pub fn service_stability(data : Array[Double], window : Int) -> ServiceMetric {
  service_metric("stability", streaming_quality_score(data, window, 3.5), 0.95)
}

///|
pub fn service_forecastability(
  data : Array[Double],
  period : Int,
  window : Int,
) -> ServiceMetric {
  service_metric(
    "forecastability",
    timeseries_quality(data, period, window),
    0.8,
  )
}

///|
pub fn service_from_data(
  data : Array[Double],
  window : Int,
  period : Int,
) -> ServiceSummary {
  service_summary([
    service_completeness(data),
    service_stability(data, window),
    service_forecastability(data, period, window),
  ])
}

///|
pub fn service_metric_names(summary : ServiceSummary) -> Array[String] {
  let result = []
  for metric in summary.metrics {
    result.push(metric.name)
  }
  result
}

///|
pub fn service_metric_values(summary : ServiceSummary) -> Array[Double] {
  let result = []
  for metric in summary.metrics {
    result.push(metric.value)
  }
  result
}

///|
pub fn service_metric_targets(summary : ServiceSummary) -> Array[Double] {
  let result = []
  for metric in summary.metrics {
    result.push(metric.target)
  }
  result
}

///|
pub fn service_failed(summary : ServiceSummary) -> Array[ServiceMetric] {
  let result = []
  for metric in summary.metrics {
    if metric.status != "healthy" {
      result.push(metric)
    }
  }
  result
}

///|
pub fn service_is_healthy(summary : ServiceSummary, threshold : Double) -> Bool {
  summary.status == "healthy" && summary.score >= threshold
}

///|
pub fn service_summary_vector(summary : ServiceSummary) -> Array[Double] {
  [
    summary.score,
    summary.metrics.length().to_double(),
    service_failed(summary).length().to_double(),
    if summary.status == "healthy" {
      1.0
    } else {
      0.0
    },
  ]
}

///|
pub fn service_summary_lines(summary : ServiceSummary) -> Array[String] {
  let lines = ["score=" + summary.score.to_string(), "status=" + summary.status]
  for metric in summary.metrics {
    lines.push(
      metric.name +
      "|" +
      metric.value.to_string() +
      "|target=" +
      metric.target.to_string() +
      "|" +
      metric.status,
    )
  }
  lines
}

///|
pub fn service_summary_string(summary : ServiceSummary) -> String {
  service_summary_lines(summary).join("\n")
}

///|
pub fn service_compare(
  left : ServiceSummary,
  right : ServiceSummary,
) -> Array[Double] {
  [
    left.score,
    right.score,
    right.score - left.score,
    service_failed(left).length().to_double(),
    service_failed(right).length().to_double(),
  ]
}

///|
pub fn service_batch(
  data_sets : Array[Array[Double]],
  window : Int,
  period : Int,
) -> Array[Double] {
  let result = []
  for data in data_sets {
    result.push(service_from_data(data, window, period).score)
  }
  result
}

///|
pub fn service_quality_gate(data : Array[Double], threshold : Double) -> Bool {
  service_is_healthy(service_from_data(data, 5, 7), threshold)
}

///|
pub fn service_sla_breach(summary : ServiceSummary) -> Bool {
  service_failed(summary).length() > 0
}

///|
pub fn service_digest(summary : ServiceSummary) -> Array[Double] {
  service_summary_vector(summary)
}

///|
pub fn service_score_delta(
  left : ServiceSummary,
  right : ServiceSummary,
) -> Double {
  right.score - left.score
}

///|
pub fn service_target_gap(summary : ServiceSummary) -> Array[Double] {
  let result = []
  for metric in summary.metrics {
    result.push(metric.value - metric.target)
  }
  result
}

///|
pub fn service_best_metric(summary : ServiceSummary) -> String {
  if summary.metrics.length() == 0 {
    return "none"
  }
  let mut best = summary.metrics[0]
  for metric in summary.metrics {
    if metric.value > best.value {
      best = metric
    }
  }
  best.name
}

///|
pub fn service_worst_metric(summary : ServiceSummary) -> String {
  if summary.metrics.length() == 0 {
    return "none"
  }
  let mut worst = summary.metrics[0]
  for metric in summary.metrics {
    if metric.value < worst.value {
      worst = metric
    }
  }
  worst.name
}

///|
pub fn service_reproducible(data : Array[Double]) -> Bool {
  let left = service_from_data(data, 5, 7)
  let right = service_from_data(data, 5, 7)
  left.score == right.score &&
  service_metric_names(left) == service_metric_names(right)
}

///|
pub fn service_metric_count(summary : ServiceSummary) -> Int {
  summary.metrics.length()
}

///|
pub fn service_healthy_count(summary : ServiceSummary) -> Int {
  summary.metrics.length() - service_failed(summary).length()
}

///|
pub fn service_healthy_fraction(summary : ServiceSummary) -> Double {
  if summary.metrics.length() == 0 {
    1.0
  } else {
    service_healthy_count(summary).to_double() /
    summary.metrics.length().to_double()
  }
}

///|
pub fn service_metric_index(summary : ServiceSummary, name : String) -> Int {
  for index = 0; index < summary.metrics.length(); index = index + 1 {
    if summary.metrics[index].name == name {
      return index
    }
  }
  -1
}

///|
pub fn service_metric_or_zero(
  summary : ServiceSummary,
  name : String,
) -> Double {
  let index = service_metric_index(summary, name)
  if index < 0 {
    0.0
  } else {
    summary.metrics[index].value
  }
}

///|
pub fn service_metric_statuses(summary : ServiceSummary) -> Array[String] {
  let result = []
  for metric in summary.metrics {
    result.push(metric.status)
  }
  result
}

///|
pub fn service_metric_gaps(summary : ServiceSummary) -> Array[Double] {
  let result = []
  for metric in summary.metrics {
    result.push(metric.target - metric.value)
  }
  result
}

///|
pub fn service_mean_gap(summary : ServiceSummary) -> Double {
  mean(service_metric_gaps(summary))
}

///|
pub fn service_score_with_penalty(
  summary : ServiceSummary,
  penalty : Double,
) -> Double {
  transform_clip(
    summary.score - service_failed(summary).length().to_double() * penalty,
    0.0,
    1.0,
  )
}

///|
pub fn service_gate_with_penalty(
  summary : ServiceSummary,
  threshold : Double,
  penalty : Double,
) -> Bool {
  service_score_with_penalty(summary, penalty) >= threshold
}

///|
pub fn service_merge(
  left : ServiceSummary,
  right : ServiceSummary,
) -> ServiceSummary {
  let metrics = left.metrics.copy()
  for metric in right.metrics {
    metrics.push(metric)
  }
  service_summary(metrics)
}

///|
pub fn service_batch_mean(scores : Array[Double]) -> Double {
  mean(scores)
}

///|
pub fn service_batch_min(scores : Array[Double]) -> Double {
  min_value(scores)
}

///|
pub fn service_batch_max(scores : Array[Double]) -> Double {
  max_value(scores)
}

///|
pub fn service_batch_stability(scores : Array[Double]) -> Double {
  if scores.length() == 0 {
    1.0
  } else {
    1.0 / (1.0 + sample_stddev(scores))
  }
}

///|
pub fn service_batch_quality(
  scores : Array[Double],
  threshold : Double,
) -> Double {
  if scores.length() == 0 {
    1.0
  } else {
    scores.filter(score => score >= threshold).length().to_double() /
    scores.length().to_double()
  }
}

///|
pub fn service_dashboard(
  scores : Array[Double],
  threshold : Double,
) -> Array[Double] {
  [
    service_batch_mean(scores),
    service_batch_min(scores),
    service_batch_max(scores),
    service_batch_stability(scores),
    service_batch_quality(scores, threshold),
  ]
}

///|
pub fn service_threshold_status(value : Double, threshold : Double) -> String {
  if value >= threshold {
    "healthy"
  } else {
    "review"
  }
}

///|
pub fn service_score_status(score : Double) -> String {
  service_threshold_status(score, 0.95)
}

///|
pub fn service_alert_fraction(summary : ServiceSummary) -> Double {
  if summary.metrics.length() == 0 {
    0.0
  } else {
    service_failed(summary).length().to_double() /
    summary.metrics.length().to_double()
  }
}

///|
pub fn service_alert_penalty(
  summary : ServiceSummary,
  penalty : Double,
) -> Double {
  let safe_penalty = if penalty < 0.0 { -penalty } else { penalty }
  service_alert_fraction(summary) * safe_penalty
}

///|
pub fn service_adjusted_score(
  summary : ServiceSummary,
  penalty : Double,
) -> Double {
  transform_clip(
    summary.score - service_alert_penalty(summary, penalty),
    0.0,
    1.0,
  )
}

///|
pub fn service_adjusted_gate(
  summary : ServiceSummary,
  threshold : Double,
  penalty : Double,
) -> Bool {
  service_adjusted_score(summary, penalty) >= threshold
}

///|
pub fn service_drift_metric(
  baseline : Array[Double],
  current : Array[Double],
) -> ServiceMetric {
  let score = 1.0 -
    transform_clip(
      drift_report(baseline, current, drift_default_rule()).drift_score,
      0.0,
      1.0,
    )
  service_metric("distribution-stability", score, 0.8)
}

///|
pub fn service_risk_metric(returns : Array[Double]) -> ServiceMetric {
  let snapshot = risk_snapshot(returns, risk_default_rule())
  service_metric(
    "risk-stability",
    transform_clip(1.0 - snapshot.maximum_drawdown, 0.0, 1.0),
    0.8,
  )
}

///|
pub fn service_model_metric(
  actual : Array[Double],
  predicted : Array[Double],
) -> ServiceMetric {
  service_metric(
    "model-score",
    model_validation_residual_score(actual, predicted),
    0.8,
  )
}

///|
pub fn service_extended(
  data : Array[Double],
  baseline : Array[Double],
  returns : Array[Double],
  actual : Array[Double],
  predicted : Array[Double],
) -> ServiceSummary {
  service_summary([
    service_completeness(data),
    service_drift_metric(baseline, data),
    service_risk_metric(returns),
    service_model_metric(actual, predicted),
  ])
}

///|
pub fn service_extended_vector(summary : ServiceSummary) -> Array[Double] {
  [
    summary.score,
    service_alert_fraction(summary),
    service_adjusted_score(summary, 0.1),
    service_healthy_fraction(summary),
  ]
}

///|
pub fn service_metric_report(summary : ServiceSummary) -> AnalyticsReport {
  let report = analytics_report("service", "local")
  let metrics = []
  for metric in summary.metrics {
    metrics.push(
      report_metric(
        metric.name,
        metric.value,
        "ratio",
        metric.status == "healthy",
      ),
    )
  }
  report_add_section(
    report,
    report_section(
      "service-level",
      summary.status,
      summary.score,
      metrics,
      service_summary_lines(summary),
    ),
  )
}

///|
pub fn service_metric_report_score(summary : ServiceSummary) -> Double {
  report_quality_score(service_metric_report(summary))
}

///|
pub fn service_metric_report_lines(summary : ServiceSummary) -> Array[String] {
  report_lines(service_metric_report(summary))
}

///|
pub fn service_metric_report_string(summary : ServiceSummary) -> String {
  service_metric_report_lines(summary).join("\n")
}

///|
pub fn service_alert_names(summary : ServiceSummary) -> Array[String] {
  let result = []
  for metric in service_failed(summary) {
    result.push(metric.name)
  }
  result
}

///|
pub fn service_alert_count(summary : ServiceSummary) -> Int {
  service_failed(summary).length()
}

///|
pub fn service_alert_score(summary : ServiceSummary) -> Double {
  1.0 - service_alert_fraction(summary)
}

///|
pub fn service_alert_gate(
  summary : ServiceSummary,
  maximum_fraction : Double,
) -> Bool {
  service_alert_fraction(summary) <= maximum_fraction
}

///|
pub fn service_metric_health(summary : ServiceSummary, name : String) -> Bool {
  let index = service_metric_index(summary, name)
  index >= 0 && summary.metrics[index].status == "healthy"
}

///|
pub fn service_metric_gap_score(
  summary : ServiceSummary,
  name : String,
) -> Double {
  let index = service_metric_index(summary, name)
  if index < 0 {
    0.0
  } else {
    transform_clip(
      summary.metrics[index].value - summary.metrics[index].target + 1.0,
      0.0,
      1.0,
    )
  }
}

///|
pub fn service_summary_checksum(summary : ServiceSummary) -> Double {
  let mut checksum = summary.score
  for metric in summary.metrics {
    checksum += metric.value * 0.01 + metric.target * 0.001
  }
  checksum
}

///|
pub fn service_summary_stable(
  left : ServiceSummary,
  right : ServiceSummary,
  tolerance : Double,
) -> Bool {
  abs_double(service_summary_checksum(left) - service_summary_checksum(right)) <=
  tolerance
}

///|
pub fn service_score_floor(summary : ServiceSummary, floor : Double) -> Double {
  if summary.score < floor {
    floor
  } else {
    summary.score
  }
}

///|
pub fn service_score_ceiling(
  summary : ServiceSummary,
  ceiling : Double,
) -> Double {
  if summary.score > ceiling {
    ceiling
  } else {
    summary.score
  }
}

///|
pub fn service_breach_message(summary : ServiceSummary) -> String {
  if service_sla_breach(summary) {
    "service-level breach"
  } else {
    "service-level healthy"
  }
}

///|
pub fn service_operational_vector(summary : ServiceSummary) -> Array[Double] {
  [
    service_score_floor(summary, 0.0),
    service_score_ceiling(summary, 1.0),
    service_alert_score(summary),
    service_healthy_fraction(summary),
    service_mean_gap(summary),
  ]
}

///|
pub fn service_metric_average(summary : ServiceSummary) -> Double {
  mean(service_metric_values(summary))
}

///|
pub fn service_metric_scale(summary : ServiceSummary) -> Double {
  mad(service_metric_values(summary))
}

///|
pub fn service_metric_range(summary : ServiceSummary) -> Double {
  range(service_metric_values(summary))
}

///|
pub fn service_metric_profile(summary : ServiceSummary) -> Array[Double] {
  [
    service_metric_average(summary),
    service_metric_scale(summary),
    service_metric_range(summary),
    service_summary_checksum(summary),
  ]
}

///|
pub fn service_metric_median(summary : ServiceSummary) -> Double {
  median(service_metric_values(summary))
}

///|
pub fn service_metric_mad(summary : ServiceSummary) -> Double {
  mad(service_metric_values(summary))
}

///|
pub fn service_metric_quantiles(summary : ServiceSummary) -> Array[Double] {
  let values = service_metric_values(summary)
  [quantile(values, 0.25), quantile(values, 0.5), quantile(values, 0.75)]
}

///|
pub fn service_metric_distribution(summary : ServiceSummary) -> Array[Double] {
  [
    service_metric_median(summary),
    service_metric_mad(summary),
    quantile(service_metric_values(summary), 0.95),
  ]
}

///|
pub fn service_metric_zscores(summary : ServiceSummary) -> Array[Double] {
  transform_standardize(service_metric_values(summary))
}

///|
pub fn service_metric_robust_scores(summary : ServiceSummary) -> Array[Double] {
  transform_robust_scale(service_metric_values(summary))
}

///|
pub fn service_metric_alerts(
  summary : ServiceSummary,
  threshold : Double,
) -> Array[Int] {
  outlier_indices_z(service_metric_values(summary), threshold~)
}

///|
pub fn service_metric_alert_rate(
  summary : ServiceSummary,
  threshold : Double,
) -> Double {
  let values = service_metric_values(summary)
  if values.length() == 0 {
    0.0
  } else {
    service_metric_alerts(summary, threshold).length().to_double() /
    values.length().to_double()
  }
}

///|
pub fn service_metric_trimmed_average(
  summary : ServiceSummary,
  probability : Double,
) -> Double {
  mean(transform_trim(service_metric_values(summary), probability))
}

///|
pub fn service_metric_winsorized_average(
  summary : ServiceSummary,
  probability : Double,
) -> Double {
  mean(transform_winsorize(service_metric_values(summary), probability))
}

///|
pub fn service_metric_robust_profile(
  summary : ServiceSummary,
  probability : Double,
) -> Array[Double] {
  [
    service_metric_trimmed_average(summary, probability),
    service_metric_winsorized_average(summary, probability),
    service_metric_mad(summary),
  ]
}

///|
pub fn service_metric_consensus(summary : ServiceSummary) -> Double {
  mean([
    service_metric_average(summary),
    service_metric_median(summary),
    service_metric_trimmed_average(summary, 0.1),
  ])
}

///|
pub fn service_metric_consensus_gap(summary : ServiceSummary) -> Double {
  abs_double(service_metric_consensus(summary) - service_metric_median(summary))
}

///|
pub fn service_metric_consensus_score(summary : ServiceSummary) -> Double {
  1.0 / (1.0 + service_metric_consensus_gap(summary))
}

///|
pub fn service_metric_final_profile(summary : ServiceSummary) -> Array[Double] {
  [
    service_metric_consensus(summary),
    service_metric_consensus_gap(summary),
    service_metric_consensus_score(summary),
    service_summary_checksum(summary),
  ]
}

///|
pub fn service_final_gate(summary : ServiceSummary, threshold : Double) -> Bool {
  service_is_healthy(summary, threshold) &&
  service_metric_consensus_score(summary) >= threshold
}

///|
pub fn service_metric_final_status(summary : ServiceSummary) -> String {
  if service_final_gate(summary, 0.8) {
    "healthy"
  } else {
    "review"
  }
}

///|
pub fn service_metric_final_message(summary : ServiceSummary) -> String {
  service_metric_final_status(summary) + ":" + service_breach_message(summary)
}

///|
pub fn service_metric_final_digest(summary : ServiceSummary) -> Array[Double] {
  let profile = service_metric_final_profile(summary)
  [
    profile[0],
    profile[1],
    profile[2],
    profile[3],
    service_alert_count(summary).to_double(),
  ]
}

///|
pub fn service_metric_final_reproducible(data : Array[Double]) -> Bool {
  let left = service_from_data(data, 5, 7)
  let right = service_from_data(data, 5, 7)
  service_summary_stable(left, right, 1.0e-12)
}

///|
pub fn service_metric_final_score(summary : ServiceSummary) -> Double {
  service_metric_consensus_score(summary) * service_alert_score(summary)
}

///|
pub fn service_metric_final_quality(summary : ServiceSummary) -> Double {
  transform_clip(service_metric_final_score(summary), 0.0, 1.0)
}

///|
pub fn service_metric_final_vector(summary : ServiceSummary) -> Array[Double] {
  [
    service_metric_final_score(summary),
    service_metric_final_quality(summary),
    service_metric_average(summary),
    service_metric_median(summary),
    service_metric_scale(summary),
  ]
}

///|
pub fn service_metric_final_ok(summary : ServiceSummary) -> Bool {
  service_metric_final_quality(summary) >= 0.8
}

///|
pub fn service_metric_final_threshold(
  summary : ServiceSummary,
  threshold : Double,
) -> Double {
  service_metric_final_quality(summary) - threshold
}

///|
pub fn service_metric_final_margin(summary : ServiceSummary) -> Double {
  service_metric_final_threshold(summary, 0.8)
}

///|
pub fn service_metric_final_status_code(summary : ServiceSummary) -> Int {
  if service_metric_final_ok(summary) {
    0
  } else {
    1
  }
}

///|
pub fn service_metric_final_report(summary : ServiceSummary) -> Array[String] {
  [
    service_metric_final_message(summary),
    service_metric_final_status_code(summary).to_string(),
    service_metric_final_margin(summary).to_string(),
  ]
}

///|
pub fn service_metric_final_name(summary : ServiceSummary) -> String {
  if service_metric_final_ok(summary) {
    service_best_metric(summary)
  } else {
    service_worst_metric(summary)
  }
}

///|
pub fn service_metric_final_alerts(summary : ServiceSummary) -> Array[String] {
  service_alert_names(summary)
}

///|
pub fn service_metric_final_profile_lines(
  summary : ServiceSummary,
) -> Array[String] {
  let values = service_metric_final_vector(summary)
  let lines = []
  for index = 0; index < values.length(); index = index + 1 {
    lines.push(index.to_string() + "=" + values[index].to_string())
  }
  lines
}

///|
pub fn service_metric_final_profile_string(summary : ServiceSummary) -> String {
  service_metric_final_profile_lines(summary).join("\n")
}

///|
pub fn service_metric_final_checksum(summary : ServiceSummary) -> Double {
  let mut checksum = service_summary_checksum(summary)
  for value in service_metric_final_vector(summary) {
    checksum += value * 0.0001
  }
  checksum
}

///|
pub fn service_metric_final_recommendation(summary : ServiceSummary) -> String {
  if service_metric_final_ok(summary) {
    "continue"
  } else {
    "investigate"
  }
}

///|
pub fn service_metric_final_recommendation_line(
  summary : ServiceSummary,
) -> String {
  service_metric_final_recommendation(summary) +
  "|" +
  service_metric_final_name(summary)
}

///|
pub fn service_metric_final_commit(summary : ServiceSummary) -> Bool {
  service_metric_final_ok(summary) && service_alert_count(summary) == 0
}

///|
pub fn service_metric_final_commit_line(summary : ServiceSummary) -> String {
  service_metric_final_commit(summary).to_string() +
  "|" +
  service_metric_final_recommendation(summary)
}

///|
pub fn service_metric_final_audit(summary : ServiceSummary) -> Array[Double] {
  [
    service_metric_final_checksum(summary),
    service_metric_final_quality(summary),
    service_alert_count(summary).to_double(),
    service_healthy_count(summary).to_double(),
  ]
}

///|
pub fn service_metric_final_audit_line(summary : ServiceSummary) -> String {
  let lines = []
  for value in service_metric_final_audit(summary) {
    lines.push(value.to_string())
  }
  lines.join(",")
}

///|
pub fn service_metric_final_audit_status(summary : ServiceSummary) -> String {
  if service_metric_final_commit(summary) {
    "pass"
  } else {
    "fail"
  }
}

///|
pub fn service_metric_final_audit_message(summary : ServiceSummary) -> String {
  service_metric_final_audit_status(summary) +
  "|" +
  service_metric_final_message(summary)
}

///|
pub fn service_metric_final_audit_digest(
  summary : ServiceSummary,
) -> Array[Double] {
  let audit = service_metric_final_audit(summary)
  [
    audit[0],
    audit[1],
    audit[2],
    audit[3],
    if service_metric_final_commit(summary) {
      1.0
    } else {
      0.0
    },
  ]
}

///|
pub fn service_metric_final_audit_vector(
  summary : ServiceSummary,
) -> Array[Double] {
  service_metric_final_audit_digest(summary)
}

///|
pub fn service_metric_final_audit_ok(summary : ServiceSummary) -> Bool {
  service_metric_final_audit_status(summary) == "pass"
}

///|
pub fn service_metric_final_audit_label(summary : ServiceSummary) -> String {
  if service_metric_final_audit_ok(summary) {
    "production-ready"
  } else {
    "needs-review"
  }
}

///|
pub fn service_metric_final_audit_tag(summary : ServiceSummary) -> String {
  service_metric_final_audit_label(summary) +
  "|" +
  service_metric_final_status(summary)
}

///|
pub fn service_metric_final_audit_ready(summary : ServiceSummary) -> Bool {
  service_metric_final_audit_ok(summary) &&
  service_metric_final_quality(summary) >= 0.8
}

///|
pub fn service_metric_final_audit_ready_line(
  summary : ServiceSummary,
) -> String {
  service_metric_final_audit_ready(summary).to_string() +
  "|" +
  service_metric_final_audit_tag(summary)
}

///|
pub fn service_metric_final_audit_ready_label(
  summary : ServiceSummary,
) -> String {
  if service_metric_final_audit_ready(summary) {
    "ready"
  } else {
    "review"
  }
}

///|
pub fn service_metric_final_audit_ready_message(
  summary : ServiceSummary,
) -> String {
  service_metric_final_audit_ready_label(summary) +
  "|" +
  service_metric_final_audit_message(summary)
}

///|
pub fn service_metric_final_audit_ready_digest(
  summary : ServiceSummary,
) -> Array[Double] {
  let digest = service_metric_final_audit_digest(summary)
  [
    digest[0],
    digest[1],
    digest[2],
    digest[3],
    if service_metric_final_audit_ready(summary) {
      1.0
    } else {
      0.0
    },
  ]
}

///|
pub fn service_metric_final_audit_ready_vector(
  summary : ServiceSummary,
) -> Array[Double] {
  service_metric_final_audit_ready_digest(summary)
}

///|
pub fn service_metric_final_audit_ready_text(
  summary : ServiceSummary,
) -> String {
  service_metric_final_audit_ready_label(summary) +
  "|" +
  service_metric_final_audit_ready_message(summary)
}

///|
pub fn service_metric_final_audit_ready_code(summary : ServiceSummary) -> Int {
  if service_metric_final_audit_ready(summary) {
    0
  } else {
    1
  }
}

///|
pub fn service_metric_final_audit_ready_code_text(
  summary : ServiceSummary,
) -> String {
  service_metric_final_audit_ready_code(summary).to_string()
}

///|
pub fn service_metric_final_audit_ready_code_line(
  summary : ServiceSummary,
) -> String {
  "code=" + service_metric_final_audit_ready_code_text(summary)
}

///|
pub fn service_metric_final_audit_ready_code_ok(
  summary : ServiceSummary,
) -> Bool {
  service_metric_final_audit_ready_code(summary) == 0
}

///|
pub fn service_metric_final_audit_ready_code_label(
  summary : ServiceSummary,
) -> String {
  if service_metric_final_audit_ready_code_ok(summary) {
    "ok"
  } else {
    "error"
  }
}

///|
pub fn service_metric_final_audit_ready_code_message(
  summary : ServiceSummary,
) -> String {
  service_metric_final_audit_ready_code_label(summary) +
  "|" +
  service_metric_final_audit_ready_text(summary)
}

///|
pub fn service_metric_final_audit_ready_code_digest(
  summary : ServiceSummary,
) -> Array[Double] {
  [
    service_metric_final_audit_ready_code(summary).to_double(),
    service_metric_final_quality(summary),
  ]
}

///|
pub fn service_metric_final_audit_ready_code_vector(
  summary : ServiceSummary,
) -> Array[Double] {
  service_metric_final_audit_ready_code_digest(summary)
}

///|
pub fn service_metric_final_audit_ready_code_summary(
  summary : ServiceSummary,
) -> String {
  service_metric_final_audit_ready_code_message(summary)
}

///|
pub fn service_metric_final_audit_ready_code_value(
  summary : ServiceSummary,
) -> Double {
  service_metric_final_audit_ready_code(summary).to_double()
}