|
| 1 | +use serde::{Deserialize, Serialize}; |
| 2 | + |
| 3 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 4 | +#[serde(rename_all = "camelCase")] |
| 5 | +pub struct WorkspaceRule { |
| 6 | + /// A UUID unique identifier for the rule. |
| 7 | + id: String, |
| 8 | + /// The time when the rule was created, represented as a Unix timestamp in milliseconds. |
| 9 | + created_at: chrono::NaiveDateTime, |
| 10 | + /// Whether the rule is currently enabled or not. |
| 11 | + enabled: bool, |
| 12 | + /// The trigger of the rule is what causes it to be evaluated in the app. |
| 13 | + trigger: Trigger, |
| 14 | + /// These filtes determine what files or changes the rule applies to. |
| 15 | + /// Within a rule, multiple filters are combined with OR logic (i.e. it's sufficient to match any of the filters) |
| 16 | + filters: Vec<Filter>, |
| 17 | + /// The action determines what happens to the files or changes that matched the filters. |
| 18 | + action: Action, |
| 19 | +} |
| 20 | + |
| 21 | +/// Represents the kinds of events in the app that can cause a rule to be evaluated. |
| 22 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 23 | +#[serde(rename_all = "camelCase")] |
| 24 | +pub enum Trigger { |
| 25 | + /// When a file is added, removed or modified in the Git worktree. |
| 26 | + FileSytemChange, |
| 27 | +} |
| 28 | + |
| 29 | +/// A filter is a condition that determines what files or changes the rule applies to. |
| 30 | +/// Within a filter, multiple conditions are combined with AND logic (i.e. to match all conditions must be met) |
| 31 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 32 | +#[serde(rename_all = "camelCase")] |
| 33 | +pub enum Filter { |
| 34 | + /// Matches the file path (relative to the repository root) against all provided regex patterns. |
| 35 | + #[serde(with = "serde_regex")] |
| 36 | + PathMatchesRegex(Vec<regex::Regex>), |
| 37 | + /// Match the file content against all provided regex patterns. |
| 38 | + #[serde(with = "serde_regex")] |
| 39 | + ContentMatchesRegex(Vec<regex::Regex>), |
| 40 | + /// Matches the file change operation type (e.g. addition, deletion, modification, rename) |
| 41 | + FileChangeType(TreeStatus), |
| 42 | + /// Matches the semantic type of the change. |
| 43 | + SemanticType(SemanticType), |
| 44 | +} |
| 45 | + |
| 46 | +/// Represents the type of change that occurred in the Git worktree. |
| 47 | +/// Matches the TreeStatus of the TreeChange |
| 48 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 49 | +#[serde(rename_all = "camelCase")] |
| 50 | +pub enum TreeStatus { |
| 51 | + /// Something was added or scheduled to be added. |
| 52 | + Addition, |
| 53 | + /// Something was deleted. |
| 54 | + Deletion, |
| 55 | + /// A tracked entry was modified, which might mean. |
| 56 | + Modification, |
| 57 | + /// An entry was renamed. |
| 58 | + Rename, |
| 59 | +} |
| 60 | + |
| 61 | +/// Represents a semantic type of change that was inferred for the change. |
| 62 | +/// Typically this means a heuristic or an LLM determinded that a change represents a refactor, a new feature, a bug fix, or documentation update. |
| 63 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 64 | +#[serde(rename_all = "camelCase")] |
| 65 | +pub enum SemanticType { |
| 66 | + /// A change that is a refactor, meaning it does not change the external behavior of the code but improves its structure. |
| 67 | + Refactor, |
| 68 | + /// A change that introduces a new feature or functionality to the codebase. |
| 69 | + NewFeature, |
| 70 | + /// A change that fixes a bug or an issue in the code. |
| 71 | + BugFix, |
| 72 | + /// A change that updates or adds documentation, such as code inline docs, comments or README files. |
| 73 | + Documentation, |
| 74 | + /// A change that is not recognized or does not fit into the predefined categories. |
| 75 | + UserDefined(String), |
| 76 | +} |
| 77 | + |
| 78 | +/// Represents an action that can be taken based on the rule evaluation. |
| 79 | +/// An action can be either explicit, meaning the user defined something like "Assign in Lane A" or "Ammend into Commit X" |
| 80 | +/// or it is implicit, meaning the action was determined by heuristics or AI, such as "Assign to appropriate branch" or "Absorb in dependent commit". |
| 81 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 82 | +#[serde(rename_all = "camelCase")] |
| 83 | +pub enum Action { |
| 84 | + /// An action that has an explicit operation defined by the user. |
| 85 | + Explicit(Operation), |
| 86 | + /// An action where the operation is determined by heuristics or AI. |
| 87 | + Implicit(ImplicitOperation), |
| 88 | +} |
| 89 | + |
| 90 | +/// Represents the operation that a user can configure to be performed in an explicit action. |
| 91 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 92 | +#[serde(rename_all = "camelCase")] |
| 93 | +pub enum Operation { |
| 94 | + /// Assign the matched changes to a specific stack ID. |
| 95 | + Assign { stack_id: String }, |
| 96 | + /// Amend the matched changes into a specific commit. |
| 97 | + Amend { commit_id: String }, |
| 98 | + /// Create a new commit with the matched changes on a specific branch. |
| 99 | + NewCommit { branch_name: String }, |
| 100 | +} |
| 101 | + |
| 102 | +/// Represents the implicit operation that is determined by heuristics or AI. |
| 103 | +#[derive(Serialize, Deserialize, Debug, Clone)] |
| 104 | +#[serde(rename_all = "camelCase")] |
| 105 | +pub enum ImplicitOperation { |
| 106 | + /// Assign the matched changes to the appropriate branch based on offline heuristics. |
| 107 | + AssignToAppropriateBranch, |
| 108 | + /// Absorb the matched changes into a dependent commit based on offline heuristics. |
| 109 | + AbsorbIntoDependentCommit, |
| 110 | + /// Perform an operation based on LLM-driven analysis and tool calling. |
| 111 | + LLMPrompt(String), |
| 112 | +} |
0 commit comments