Skip to main content

dejavu/reduce/
envelope.rs

1//! The common compact-output envelope (spec §16.1).
2
3use crate::commands::fmt_int;
4
5pub struct Envelope<'a> {
6    pub status: &'a str,
7    pub command: &'a str,
8    pub exit_code: i32,
9    /// An optional emphasis line under the header (e.g. exit-code change).
10    pub headline: Option<&'a str>,
11    /// An optional note (e.g. git-state annotation).
12    pub note: Option<&'a str>,
13    pub body: &'a str,
14    pub suppressed_tokens: i64,
15    pub run_id_short: &'a str,
16    pub prev_id_short: Option<&'a str>,
17    /// `Full output` / `Full diff` / `Full logs`.
18    pub full_label: &'a str,
19}
20
21/// Render the envelope to a string. Never leaks internal fields
22/// (hashes/command_key/sqlite paths) — only the opaque short ids appear.
23pub fn render(env: &Envelope) -> String {
24    let mut out = String::new();
25    out.push_str(&format!("dejavu: {}\n", env.status));
26    out.push_str(&format!("Command: {}\n", env.command));
27    out.push_str(&format!("Exit code: {}\n", env.exit_code));
28    if let Some(headline) = env.headline {
29        out.push_str(headline);
30        out.push('\n');
31    }
32    if let Some(note) = env.note {
33        out.push_str(note);
34        out.push('\n');
35    }
36    if !env.body.trim().is_empty() {
37        out.push('\n');
38        out.push_str(env.body.trim_end());
39        out.push('\n');
40    }
41    out.push_str(&format!(
42        "\nSuppressed ~{} estimated tokens.\n",
43        fmt_int(env.suppressed_tokens)
44    ));
45    out.push_str(&format!(
46        "{}: dejavu show {} --stdout\n",
47        env.full_label, env.run_id_short
48    ));
49    if let Some(prev) = env.prev_id_short {
50        out.push_str(&format!("Previous output: dejavu show {prev} --stdout\n"));
51    }
52
53    debug_assert!(
54        !out.contains("normalized_hash") && !out.contains("runs.sqlite"),
55        "compact output must not leak internal fields"
56    );
57    out
58}