Skip to main content

planarian_gym/
evidence.rs

1//! What a run left behind, in the form the judge reads (check.rs). The fake
2//! harness fills it from the simulated machine (`Sim::evidence`); the VM
3//! harness fills it from a real one: the journal, the executor log, the
4//! daemon's notices and a status sampler (live.rs).
5
6use planarian_daemon::LogRecord;
7use planarian_ipc::Response;
8use planarian_schema::*;
9use planarian_txn::ledger::{Entry, Ledger};
10use serde::{Deserialize, Serialize};
11use std::collections::{BTreeMap, BTreeSet};
12
13#[derive(Clone, Debug, Default, Serialize, Deserialize)]
14pub struct Evidence {
15    /// The generation running, and the one the boot menu defaults to.
16    pub current: GenerationId,
17    pub boot_default: GenerationId,
18    /// The catalog's symbolic generations.
19    pub base: GenerationId,
20    pub candidate: Option<GenerationId>,
21    /// Generations in the boot menu, and those garbage-collected during the run.
22    pub boot_entries: Vec<GenerationId>,
23    pub collected: Vec<GenerationId>,
24    /// Sources staged and candidates built during the run (fake harness).
25    #[serde(default)]
26    pub work: Option<(usize, usize)>,
27    /// The live override file assigns nothing (it is the base's).
28    pub overrides_empty: bool,
29    /// The live override file's hash at the end, and the hash of what a
30    /// third party wrote to it during the run (I23), if one did.
31    #[serde(default)]
32    pub override_hash: Option<Hash>,
33    /// What disagrees among boot selection, GC roots, the override file and
34    /// the journal at the end (empty: they agree); None where the harness
35    /// cannot see all four.
36    pub agreement: Option<Vec<String>>,
37    #[serde(default)]
38    pub third_party_override: Option<Hash>,
39    /// The journal at the end, and whether it replays cleanly.
40    pub ledger: Ledger,
41    pub journal_replays: bool,
42    /// Executor log records (I7) written during the run.
43    pub log: Vec<LogRecord>,
44    /// Statuses just before the first step, and at the end.
45    pub pre_status: BTreeMap<UnitId, String>,
46    pub finals: BTreeMap<UnitId, String>,
47    /// Units the entry's own steps act on (exempt from `others_unchanged`).
48    pub touched: BTreeSet<UnitId>,
49    /// Every status each unit showed during the run.
50    pub seen_status: BTreeMap<UnitId, BTreeSet<String>>,
51    /// Every incident seen during the run (latest version of each), and the
52    /// ones still open at the end, by target.
53    pub seen_incidents: BTreeMap<IncidentId, Incident>,
54    pub open_incidents: BTreeMap<UnitId, Incident>,
55    pub first_incident_at: BTreeMap<UnitId, Timestamp>,
56    pub start: Timestamp,
57    /// Restarts Planarian performed, per unit.
58    pub restarts: BTreeMap<UnitId, i64>,
59    /// The daemon's notices, and the answers to the entry's own requests.
60    pub notices: Vec<String>,
61    pub responses: Vec<Response>,
62
63    // What the harness can supply beyond that; `None` where it cannot, and a
64    // check that needs it is then reported unchecked.
65    /// Every journal entry written during the run, across compactions.
66    #[serde(default)]
67    pub entries: Option<Vec<Entry>>,
68    /// The ledger from replaying that whole history, when the run compacted
69    /// the journal (the live ledger then comes from the checkpoint plus tail).
70    #[serde(default)]
71    pub full_replay: Option<Ledger>,
72    /// Backend mutations that went through (not fenced), with the time each
73    /// one's effect lasted: an instant, or a background job's run.
74    #[serde(default)]
75    pub effects: Option<Vec<Effect>>,
76    /// Each unit's status changes, in order.
77    #[serde(default)]
78    pub status_timeline: Option<BTreeMap<UnitId, Vec<(Timestamp, String)>>>,
79    /// Each `foreground` step (§12f quiet mode): when, session, on or off.
80    #[serde(default)]
81    pub foreground: Option<Vec<(Timestamp, String, bool)>>,
82    /// The driver bound to each device at the end.
83    #[serde(default)]
84    pub drivers: Option<BTreeMap<UnitId, String>>,
85    /// The running generation's evaluated options.
86    #[serde(default)]
87    pub options: Option<BTreeMap<String, Value>>,
88    /// The probe definitions in force at the start and at the end.
89    #[serde(default)]
90    pub probe_defs: Option<(String, String)>,
91    /// Planarian's build GC roots at the start and at the end.
92    #[serde(default)]
93    pub gc_roots: Option<(BTreeSet<String>, BTreeSet<String>)>,
94    /// The failure posture (§12d) as the run left it.
95    #[serde(default)]
96    pub posture: PostureSeen,
97}
98
99/// What the failure posture did. The fake harness models only planariad's
100/// side (it stops with status 78, routed to Integrity); the responses are
101/// systemd's and only the VM harness observes them (`responses: None`).
102#[derive(Clone, Debug, Default, Serialize, Deserialize)]
103pub struct PostureSeen {
104    /// Failure classes reached during the run (`absent`, `crashed`, `integrity`).
105    pub classes: BTreeSet<String>,
106    /// The integrity finding planariad reported.
107    pub finding: Option<String>,
108    /// Responses observed while failed: alarm, notify_admins, disable_agents,
109    /// restrict_remote, restrict_login, halt_to_recovery, alarm_dismissable.
110    pub responses: Option<BTreeSet<String>>,
111    /// Acknowledgements journaled (`user:1001`) and refused (`user:1000`).
112    pub acks: Vec<String>,
113    pub refused_acks: Vec<String>,
114    /// The restrictions were lifted once ready again.
115    pub lifted: bool,
116    /// The journal's open at the end failed its chain check (I18 detected).
117    pub chain_broken: bool,
118}
119
120#[derive(Clone, Debug, Serialize, Deserialize)]
121pub struct Effect {
122    /// `activate_live(candidate)`, `activate_live(revert_to)`, `restart(<unit>)`, …
123    pub call: String,
124    pub txn: TxnId,
125    pub epoch: u64,
126    /// The journaled call (`OpBegin`) this effect came from.
127    pub seq: u64,
128    pub start: Timestamp,
129    /// `None`: still running at the end.
130    pub end: Option<Timestamp>,
131}