| 1 | //! Shared constants for history transcript rendering. |
| 2 | //! |
| 3 | //! ## How the live tool-card budgets were chosen |
| 4 | //! |
| 5 | //! The caps below were measured, not guessed. The sample is 53 real saved |
| 6 | //! sessions from `~/.codewhale/sessions` — 5,470 tool results, 4,001 of them |
| 7 | //! `Bash` (the "run" cards) and 3,777 `Bash` commands. |
| 8 | //! |
| 9 | //! Observed `Bash` result length, in source lines: |
| 10 | //! `p25=3 p50=9 p75=25 p90=60 p95=113 max=1161`. |
| 11 | //! |
| 12 | //! Observed `Bash` command length: `p50=251 chars`, `p90=1404` — i.e. the |
| 13 | //! median command is multi-line once wrapped, not a one-liner. |
| 14 | //! |
| 15 | //! Each cap sits at the knee of its own coverage curve: the point past which |
| 16 | //! more rows buy very little more content. Going further chases a long tail |
| 17 | //! that a single card should never try to hold — that is what the details |
| 18 | //! pager is for. |
| 19 | |
| 20 | /// Wrapped rows of the *command* echoed inside a live tool card. |
| 21 | /// |
| 22 | /// Coverage of real `Bash` commands shown whole, at an 80-column terminal: |
| 23 | /// `3 → 45%`, `4 → 58%`, **`6 → 70%`**, `8 → 75%`, `10 → 77%`. |
| 24 | /// Six is the knee: +25 points over the old cap of 3, where 8 adds only 4 |
| 25 | /// more and 10 only 2. At 3 the *median* command was clipped, which is the |
| 26 | /// "run cards never show enough" complaint at its source. |
| 27 | pub(super) const TOOL_COMMAND_LINE_LIMIT: usize = 6; |
| 28 | |
| 29 | /// Wrapped rows of tool *output* shown in a live card before the details |
| 30 | /// affordance takes over. |
| 31 | /// |
| 32 | /// Fraction of real `Bash` results shown whole: `8 → 50%`, `12 → 60%`, |
| 33 | /// `16 → 68%`, **`20 → 72%`**, `24 → 75%`, `32 → 80%`. |
| 34 | /// Twenty covers three quarters of real results while still leaving half of |
| 35 | /// a 40-row terminal for everything else; 24 buys under three points for |
| 36 | /// four more rows. |
| 37 | pub(super) const TOOL_OUTPUT_LINE_LIMIT: usize = 20; |
| 38 | |
| 39 | /// Rows of output a *successful* live `run` card shows before the details |
| 40 | /// affordance takes over. |
| 41 | /// |
| 42 | /// This used to be zero: success collapsed to the bare header, so a card told |
| 43 | /// you a command finished but nothing at all about what it produced. Against |
| 44 | /// the sampled corpus (3,465 `Bash` results with no error marker, |
| 45 | /// `p25=3 p50=8 p75=26`), a six-row preview shows ~45% of successful runs in |
| 46 | /// their entirety and the opening of the rest. Eight rows would reach ~51%, |
| 47 | /// but it spends two more rows on *every* successful card, and the transcript |
| 48 | /// now also spends a separator row between blocks. Failures are unaffected — |
| 49 | /// they keep the full `TOOL_OUTPUT_LINE_LIMIT` budget, because an error you |
| 50 | /// cannot read is the expensive one. |
| 51 | pub(super) const TOOL_SUCCESS_OUTPUT_PREVIEW_LINES: usize = 6; |
| 52 | |
| 53 | pub(super) const TOOL_TEXT_LIMIT: usize = 300; |
| 54 | |
| 55 | /// Characters of the summary shown after `·` in a tool-card header. Real |
| 56 | /// commands run far longer than any header (p50 = 251 chars), so this is a |
| 57 | /// glance budget, not a fit budget — the header line is width-clipped |
| 58 | /// downstream regardless. 72 keeps the header inside an 80-column terminal |
| 59 | /// while showing meaningfully more of the command on a wide one. |
| 60 | pub(super) const TOOL_HEADER_SUMMARY_LIMIT: usize = 72; |
| 61 | |
| 62 | /// Contiguous rows taken from the start of a truncated output. |
| 63 | /// |
| 64 | /// `p50` of a real `Bash` result is 9 source lines, so a 10-row head shows |
| 65 | /// the whole opening of a median result rather than a fragment of it. |
| 66 | pub(super) const TOOL_OUTPUT_HEAD_LINES: usize = 10; |
| 67 | |
| 68 | /// Contiguous rows taken from the end of a truncated output — where exit |
| 69 | /// status, totals, and error summaries land. Head + tail = 16 of the 20-row |
| 70 | /// budget, leaving 4 rows for importance-ranked lines from the middle. |
| 71 | pub(super) const TOOL_OUTPUT_TAIL_LINES: usize = 6; |
| 72 | #[cfg(test)] |
| 73 | pub(super) const TOOL_RUNNING_SYMBOLS: [&str; 8] = crate::tui::spinner::BRAILLE_SPINNER_FRAMES; |
| 74 | #[cfg(test)] |
| 75 | pub(super) const TOOL_STATUS_SYMBOL_MS: u64 = crate::tui::spinner::BRAILLE_SPINNER_FRAME_MS; |
| 76 | /// Visual marker for the user role at the start of their message line. Solid |
| 77 | /// vertical bar — no animation; user input is a finished thing. |
| 78 | pub(super) const USER_GLYPH: &str = crate::tui::glyphs::USER; |
| 79 | /// Visual marker for the assistant role. Solid bullet that pulses at 2s |
| 80 | /// cycle while the response is streaming, holds full brightness when idle. |
| 81 | pub(super) const ASSISTANT_GLYPH: &str = crate::tui::glyphs::CURRENT; |
| 82 | /// Transcript body left rail. Solid 1/8 block (`▏`) followed by a space — |
| 83 | /// used as a visual left-margin anchor for continuation lines, tool-card |
| 84 | /// detail rows, and affordance lines. Dimmed so it guides the eye without |
| 85 | /// competing with content. |
| 86 | pub(super) const TRANSCRIPT_RAIL: &str = crate::tui::glyphs::TRANSCRIPT_RAIL; |
| 87 | /// Total rendered rows a non-failed tool card keeps when `show_tool_details` |
| 88 | /// is off — the shipped default, so this is the cap almost every user |
| 89 | /// actually sees. |
| 90 | /// |
| 91 | /// It was an unnamed literal `2`: header plus a single row, then an "expand" |
| 92 | /// affordance. Three rows spent to learn that *something* ran. Every other |
| 93 | /// budget in this file was invisible underneath it. Six rows is a header, up |
| 94 | /// to four rows of real content, and the affordance — enough to answer "what |
| 95 | /// did that do?" without opening anything, and still a card rather than a |
| 96 | /// wall. Failures are excluded from this path entirely and keep their full |
| 97 | /// budget. |
| 98 | pub(super) const TOOL_SUMMARY_CARD_LINES: usize = 6; |
| 99 | |
| 100 | /// Total rendered rows a non-failed tool card keeps in calm mode — also on by |
| 101 | /// default, and applied *after* the `show_tool_details` summary cap above. |
| 102 | /// |
| 103 | /// It was 4, i.e. stricter than the summary cap, which inverted the two: a |
| 104 | /// user who turned tool details *on* while leaving calm mode alone saw fewer |
| 105 | /// rows than one who left both at their defaults. Calm mode is about quiet, |
| 106 | /// not about hiding, so it bounds the card at the header plus the full |
| 107 | /// successful-run preview plus the expand affordance. |
| 108 | pub(super) const TOOL_CARD_SUMMARY_LINES: usize = TOOL_SUCCESS_OUTPUT_PREVIEW_LINES + 2; |
| 109 | pub(super) const TOOL_DONE_SYMBOL: &str = crate::tui::glyphs::DONE; |
| 110 | pub(super) const TOOL_FAILED_SYMBOL: &str = crate::tui::glyphs::FAILED; |
| 111 | /// Compact Ctrl+B affordance for foreground shell waits in the live transcript. |
| 112 | pub(super) const FOREGROUND_SHELL_WAIT_HINT: &str = "Ctrl+B → /jobs"; |
| 113 |