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
//! Plan-phase validators for [`PackManifest`].
//!
//! Stage B of M3 introduces **plan-phase** validation — checks that run
//! after [`crate::pack::parse`] succeeds but before any execute-time work
//! (variable expansion, filesystem touches, child-pack traversal). The
//! validators here operate on the already-parsed manifest in its
//! pre-expansion, literal form.
//!
//! # Framework shape
//!
//! A [`Validator`] receives an immutable [`PackManifest`] and returns a
//! `Vec<PackValidationError>` — never fail-first. [`run_all`] composes the
//! default validator set and concatenates their findings so callers see
//! the full diagnostic set in one pass. This slice ships one validator
//! ([`DuplicateSymlinkValidator`]); subsequent M3 slices (cycle detect,
//! cross-pack conflict, `depends_on` verification) plug into the same
//! surface without touching orchestrator code.
//!
//! # Non-goals for this slice
//!
//! * No filesystem IO, no git, no platform probing.
//! * No variable expansion — validators compare literal `dst` strings.
//! * No cross-pack reasoning (later slices).
use Error;
use PackManifest;
use cratePackGraph;
pub use CycleValidator;
pub use DependsOnValidator;
pub use DuplicateSymlinkValidator;
/// Errors raised by plan-phase validators.
///
/// Marked `#[non_exhaustive]` so future slices (slices 3–6) can add variants
/// without breaking downstream `match` arms.
/// A single plan-phase validator.
///
/// Implementations run against a fully parsed manifest and return every
/// problem they observe — never `Result`, because aggregation across
/// validators is the point.
/// Run every default validator against `pack`, concatenating their
/// findings.
///
/// The current default set is:
///
/// 1. [`DuplicateSymlinkValidator`] — two symlinks with the same literal
/// `dst`.
///
/// Later slices extend this list; callers should prefer
/// [`PackManifest::validate_plan`] over instantiating validators manually,
/// so the default set stays discoverable.
/// Plan-phase validator that operates on an assembled [`PackGraph`].
///
/// Separate trait from [`Validator`] on purpose: graph-level checks need
/// the full graph, not a single manifest, and mixing the two into one
/// trait would force every per-manifest validator to accept a graph it
/// doesn't need. Two traits keep each call site's surface minimal and
/// type-safe.
/// Run every default [`GraphValidator`] against `graph`, concatenating
/// their findings.
///
/// Current default set:
///
/// 1. [`CycleValidator`] — belt-and-suspenders for cycles the walker
/// should have caught.
/// 2. [`DependsOnValidator`] — verify every `depends_on` entry resolves.