1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! Error types for the skills subsystem.
use std::path::PathBuf;
/// Result alias used throughout `devboy-skills`.
pub type Result<T> = std::result::Result<T, SkillError>;
/// Errors that can surface while loading, parsing, or installing a skill.
#[derive(Debug, thiserror::Error)]
pub enum SkillError {
/// The skill body did not open with a YAML frontmatter block
/// (`---` at line 1, closing `---` on a subsequent line).
#[error("skill `{skill}`: missing YAML frontmatter delimiter `---`")]
MissingFrontmatter {
/// Identifier of the offending skill (directory name).
skill: String,
},
/// The YAML frontmatter parsed but did not contain a required field.
#[error("skill `{skill}`: required frontmatter field `{field}` is missing")]
MissingRequiredField {
/// Identifier of the offending skill.
skill: String,
/// Name of the missing field.
field: &'static str,
},
/// The YAML frontmatter parsed but a field had the wrong type.
#[error("skill `{skill}`: frontmatter field `{field}` has invalid type ({reason})")]
InvalidFieldType {
/// Identifier of the offending skill.
skill: String,
/// Name of the offending field.
field: &'static str,
/// Why the value is rejected.
reason: String,
},
/// The `category` field references a category that is not in the
/// known enum. Provide one of the shipped categories (self-bootstrap,
/// issue-tracking, code-review, self-feedback, meeting-notes, messenger)
/// or extend [`crate::skill::Category`] before shipping a new one.
#[error("skill `{skill}`: unknown category `{category}`")]
UnknownCategory {
/// Identifier of the offending skill.
skill: String,
/// The string that failed to parse as a category.
category: String,
},
/// Underlying YAML parser failure (syntax error inside the frontmatter).
#[error("skill `{skill}`: invalid YAML in frontmatter: {source}")]
InvalidYaml {
/// Identifier of the offending skill.
skill: String,
/// Wrapped YAML error.
#[source]
source: serde_yaml::Error,
},
/// A skill lookup was asked for a name that the source does not know
/// about.
#[error("skill `{name}` not found in source `{source_name}`")]
NotFound {
/// Name that was requested.
name: String,
/// The source that was queried.
source_name: &'static str,
},
/// Filesystem operation failed while reading or writing a skill / manifest.
#[error("filesystem error at `{path}`: {source}")]
Io {
/// Path that was being accessed.
path: PathBuf,
/// Wrapped IO error.
#[source]
source: std::io::Error,
},
/// Manifest JSON parse failure.
#[error("manifest at `{path}`: invalid JSON ({source})")]
InvalidManifest {
/// Path to the offending manifest.
path: PathBuf,
/// Wrapped serde_json error.
#[source]
source: serde_json::Error,
},
/// Non-manifest JSON (de)serialisation failure — used by the trace
/// subsystem for `trace.jsonl` records and `meta.json` writes so
/// callers do not see a misleading "manifest … invalid JSON"
/// error for a record that is not a manifest.
#[error("failed to {operation} JSON at `{path}`: {source}")]
SerdeJson {
/// What was being done when the failure happened
/// (`serialise trace record`, `write session meta`, …).
operation: &'static str,
/// Path associated with the record.
path: PathBuf,
/// Wrapped serde_json error.
#[source]
source: serde_json::Error,
},
}