Skip to main content

dejavu/exec/
mod.rs

1//! Execution core: shim generation, PATH handling, anti-recursion real-binary
2//! resolution, process spawning, and classification/passthrough policy.
3
4pub mod classify;
5pub mod command_key;
6pub mod interactive;
7pub mod path;
8pub mod resolve;
9pub mod shim;
10pub mod spawn;
11
12use std::time::Duration;
13
14/// Command families that Dejavu can optimize (spec §10.1).
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum Family {
17    Validation,
18    Search,
19    Tree,
20    GitReadonly,
21    Logs,
22}
23
24impl Family {
25    pub fn as_str(&self) -> &'static str {
26        match self {
27            Family::Validation => "validation",
28            Family::Search => "search",
29            Family::Tree => "tree",
30            Family::GitReadonly => "git_readonly",
31            Family::Logs => "logs",
32        }
33    }
34}
35
36/// The decision the classifier hands to the runtime.
37#[derive(Debug, Clone)]
38pub enum ExecMode {
39    /// Capture output for reduction.
40    Optimize { family: Family, command_key: String },
41    /// Run with inherited stdio; no capture, no reduction.
42    Passthrough(PassthroughReason),
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum PassthroughReason {
47    Disabled,
48    RepoDisabled,
49    ConfigExcluded,
50    UnknownShim,
51    UnsupportedSubcommand,
52    ArgsNotWhitelisted,
53    Interactive,
54    MutatingGit,
55    DangerousDocker,
56    SideEffecting,
57    /// A machine-readable git form (`--porcelain`, `-z`, `@{upstream}`, …) that a
58    /// program parses — reducing it would corrupt shell prompts / IDE SCM.
59    /// (Outside an agent context entirely, `run_shim` short-circuits to a pure
60    /// exec before classification — no reason is ever recorded there.)
61    MachineReadable,
62}
63
64impl PassthroughReason {
65    pub fn as_str(&self) -> &'static str {
66        match self {
67            PassthroughReason::Disabled => "disabled",
68            PassthroughReason::RepoDisabled => "repo_disabled",
69            PassthroughReason::ConfigExcluded => "config_excluded",
70            PassthroughReason::UnknownShim => "unknown_shim",
71            PassthroughReason::UnsupportedSubcommand => "unsupported_subcommand",
72            PassthroughReason::ArgsNotWhitelisted => "args_not_whitelisted",
73            PassthroughReason::Interactive => "interactive",
74            PassthroughReason::MutatingGit => "mutating_git",
75            PassthroughReason::DangerousDocker => "dangerous_docker",
76            PassthroughReason::SideEffecting => "side_effecting",
77            PassthroughReason::MachineReadable => "machine_readable",
78        }
79    }
80}
81
82/// The result of running the real command.
83#[derive(Debug, Clone)]
84pub struct ExecOutcome {
85    pub stdout: Vec<u8>,
86    pub stderr: Vec<u8>,
87    /// Already normalized: `code()` if exited, else `128 + signal`.
88    pub exit_code: i32,
89    pub duration: Duration,
90    /// Whether we captured (Optimize) or passed stdio through (Passthrough).
91    pub captured: bool,
92    /// Whether the raw output was truncated to the storage cap (spec §21.4).
93    pub truncated_raw: bool,
94}