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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//! What:
//! The one failure type of the candidate layer,
//! with a closed list of causes.
//! Why:
//! Every candidate failure stops policy evaluation (a file that could not be read
//! was not checked),
//! and callers branch on the cause without parsing message text.
//!
//! In TS you'd write (pseudocode):
//! ```ts
//! class CandidateError extends Error { readonly failure: CandidateFailure }
//! ```
/// What:
/// Why candidate listing or reading failed.
/// `#[derive(...)]` generates copying,
/// debug printing and `==`.
/// Why:
/// The policy engine maps causes to engine-failure codes,
/// and tests name the
/// exact cause instead of matching diagnostic wording.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// type CandidateFailure = 'git-not-started' | 'git-failed' | 'listing-malformed' | ...;
/// ```
/// What:
/// One candidate failure:
/// its cause and a complete explanation.
/// `String` is a heap-allocated,
/// growable UTF-8 buffer this struct owns.
/// Sibling the reader might expect:
/// `&str`,
/// a borrowed view that owns nothing.
/// Why:
/// The error outlives the formatted text built at the failure site,
/// so a
/// borrowed `&str` would dangle.
/// Messages never contain file content or
/// pathnames:
/// a pathname can itself be a forbidden string.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// class CandidateError extends Error { failure: CandidateFailure; message: string }
/// ```
/// What:
/// `impl CandidateError { ... }` attaches functions to the struct,
/// like class statics.
/// Why:
/// Failure sites keep their condition next to its user-facing explanation.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// new CandidateError(failure, message);
/// ```
/// What:
/// `impl std::fmt::Display for CandidateError` supplies Rust's "print me" interface.
/// `::` walks module paths,
/// like `std.fmt.Display` would in TS.
/// Why:
/// The executable writes the message with ordinary formatting,
/// not field access.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// toString(): string { return this.message; }
/// ```
/// What:
/// An empty `impl` marks the type as a standard error value.
/// Why:
/// Generic error handling can carry it without converting it to a bare string.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// // `extends Error` already provides this in TypeScript.
/// ```
/// Message controls stay out of the release executable.