1use std::path::PathBuf;
2
3use crate::task::Status;
4
5pub type Result<T> = std::result::Result<T, Error>;
6
7#[derive(Debug, thiserror::Error)]
8pub enum Error {
9 #[error("not initialized: no `.bears` directory found")]
10 NotInitialized,
11
12 #[error("task not found: {0}")]
13 TaskNotFound(String),
14
15 #[error("ambiguous prefix '{prefix}' matches multiple tasks: {matches}")]
16 AmbiguousPrefix { prefix: String, matches: String },
17
18 #[error("task {0} is not an epic — plans can only be generated for epics")]
19 NotAnEpic(String),
20
21 #[error("parent {0} is not an epic — only epics can have child tasks")]
22 ParentNotEpic(String),
23
24 #[error("adding dependency would create a cycle: {from} -> {to}")]
25 CycleDetected { from: String, to: String },
26
27 #[error("unknown dependency ID(s): {}", ids.join(", "))]
28 UnknownDependency { ids: Vec<String> },
29
30 #[error("invalid config: {reason}")]
31 InvalidConfig { reason: String },
32
33 #[error("{0}")]
34 InvalidUsage(String),
35
36 #[error("invalid frontmatter in {path}: {reason}")]
37 InvalidFrontmatter { path: PathBuf, reason: String },
38
39 #[error("editor failed: {reason}")]
40 EditorFailed { reason: String },
41
42 #[error("task {id} is not archivable — active dependents: {}", blockers.join(", "))]
44 NotArchivable { id: String, blockers: Vec<String> },
45
46 #[error("cannot {action} task {id}: expected status {expected}, but it is {actual}")]
52 InvalidStatus {
53 id: String,
54 action: &'static str,
55 expected: Status,
56 actual: Status,
57 },
58
59 #[error("task {id} is already claimed by '{assignee}'")]
65 AlreadyClaimed { id: String, assignee: String },
66
67 #[error("fence violation on task {id}: expected assignee '{expected}', but it is '{actual}'")]
74 FenceViolation {
75 id: String,
76 expected: String,
77 actual: String,
78 },
79
80 #[error("task not found in archive: {0}")]
82 NotArchived(String),
83
84 #[error(transparent)]
85 Io(#[from] std::io::Error),
86
87 #[error(transparent)]
88 Yaml(#[from] serde_yml::Error),
89
90 #[error(transparent)]
91 Json(#[from] serde_json::Error),
92}