1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright (C) 2026 Michael S. Klishin and Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// See LICENSE-APACHE and LICENSE-MIT for details.
//! Compact per-result projection emitted by `--formatter summary`
//! and `--formatter text-summary`.
use std::num::NonZeroU32;
use serde::{Deserialize, Serialize};
use crate::model::names::{CommitSha, SeriesName, vocabulary};
use crate::model::verdict::{TouchedKinds, Verdict};
/// One row in the summary output: a compact projection of a single
/// `SeriesEvaluation` result. JSON and text formatters share the type.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct SummaryRow {
pub sha: CommitSha,
pub verdict: VerdictKind,
pub touched: TouchedKinds,
/// Total tracked-dep symbol references summed over every evaluated
/// pin. Zero means the patch references no tracked-dep API; the
/// row is safe to skip at a glance.
pub tracked: u32,
pub subject: String,
/// The series the row was evaluated against. `None` for
/// pin-targeted single evaluations and pre-v7 envelopes.
#[serde(default)]
pub series: Option<SeriesName>,
/// Parent count of the evaluated commit; `None` for patch and PR
/// inputs (no commit identity) and pre-v7 envelopes.
#[serde(default)]
pub parent_count: Option<NonZeroU32>,
/// Paths the apply forecast predicts will conflict on the target.
/// Zero when the forecast is clean or was not evaluated; the
/// verdict kind never reflects it, so the row states it itself.
#[serde(default)]
pub apply_conflicts: u32,
/// Symbol-axis findings on the target. Zero when the axis found
/// nothing or was not evaluated; the verdict kind on an
/// all-inapplicable row never reflects it, so the row states it.
#[serde(default)]
pub target_findings: u32,
}
vocabulary!(
/// Kind-only projection of `Verdict`: drops the variant payloads so a
/// summary row stays single-line.
pub enum VerdictKind: "verdict kind" {
Compatible => "compatible",
RequiresAdaptation => "requires_adaptation",
Incompatible => "incompatible",
Inapplicable => "inapplicable",
}
);
impl From<&Verdict> for VerdictKind {
fn from(v: &Verdict) -> Self {
match v {
Verdict::Compatible => Self::Compatible,
Verdict::RequiresAdaptation { .. } => Self::RequiresAdaptation,
Verdict::Incompatible { .. } => Self::Incompatible,
Verdict::Inapplicable { .. } => Self::Inapplicable,
}
}
}