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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//! Plain text → walkable graph — the crate's read core.
//!
//! Underneath everything else sits the **census**
//! ([`census`](Graph::census)): one traversal that
//! yields every forward link reachable from a root — frontmatter relation
//! edges *and* body `[[…]]` wikilinks alike — each tagged with where it is
//! written ([`LinkSite`]) and how it resolves ([`Resolution`]), plus the
//! [`StructuralFact`]s the same pass raises from traversal state (a document
//! that would not load, a broken single-parent invariant, and so on). Because
//! it is read straight from the documents, the census is *ground truth*:
//! `prov`'s `validate`'s findings, the
//! [`backlinks`](Graph::backlinks) map, and
//! reachability ([`reachable_files`](Graph::reachable_files),
//! [`reachable_documents`](Graph::reachable_documents))
//! are all views over it, and any stored index heals *toward* the census,
//! never the reverse.
//!
//! Alongside it sits [`tree`]'s materialized [`Node`] walk — the same edges,
//! but a spanning-only DFS that renders a `contents`/`part_of` outline rather
//! than a flat link census. See `tree`'s module doc for why it stays a
//! second walker instead of a view over the census.
//!
//! This is the plain-text-workspace promise (crate root docs) made concrete:
//! follow the links declared in a document's own metadata and body, and the
//! structure unfolds without a side channel — no cache to trust instead of the
//! documents themselves. `validate`'s findings and `mutate`'s inbound-rename
//! maintenance are both built on what is censused here; nothing above this
//! module re-derives an edge from anywhere but a document's own bytes.
//!
//! Housed here: the read primitive ([`load`]) every pass shares, link
//! resolution ([`resolve`], [`Target`]) built on top of it, the census types
//! with the spanning-tree walker that fills them in, and the [`tree`] walker.
//! They stay `impl`ed on [`Graph`] rather
//! than a graph type of its own, but they no longer *require* it: every
//! function here is bounded on [`ReadStorage`](crate::fs::ReadStorage) and
//! [`IdIndex`](crate::index::IdIndex) — the read halves of the two ports — and
//! on nothing else. That is a compiler-checked statement, not a convention: the
//! read core cannot write a byte or change a registration, because the traits
//! it is generic over have no method that could.
//!
//! Those two splits exist for a consumer that does not exist yet: a language
//! server, a renderer, a browser viewer — anything that must traverse a
//! workspace without the authority to change it, and without linking the
//! machinery that would. Narrowing the bounds is the step that proves such a
//! consumer is *possible*; extracting a `prov-graph` crate is the step that
//! makes it *cheap*, and follows from here as a file move rather than a
//! redesign.
//!
//! `graph` is also the crate's sole *surface* onto
//! [`ReadStorage`](crate::fs::ReadStorage): every other module reaches the
//! filesystem for reads through a `Workspace` method housed here rather than
//! calling `self.fs()` directly. Most of that surface is [`load`] — clamped
//! against root escape and served from the read-scope memo — but a handful of
//! call sites (existence checks, a directory listing, a raw byte read for
//! something that is not a document) never wanted the clamp or the memo; those
//! go through [`probe`]'s raw primitives instead.
//!
//! **What this module does not depend on.** `graph` imports the mechanism
//! layers below it — [`crate::document`], [`crate::link`], [`crate::title`],
//! [`crate::identity`], and the generic [`crate::index::IdIndex`] — but
//! never a *policy* module (`crate::config`, `crate::validate`,
//! `crate::about`). The census walk raises [`StructuralFact`]s rather than
//! `prov`'s `Finding`s for exactly this reason: `Finding`
//! is `validate`'s vocabulary, and a walker that constructed one directly
//! would pull that policy layer's whole enum (and its config-, fixity-, and
//! vocabulary-flavored variants) down into the read core. `validate::check`
//! derives each `Finding` from a `StructuralFact` or a [`CensusEntry`]'s
//! [`Resolution`] one for one — the walk already knows exactly what
//! happened; `validate` only names it.
//! [`resolve_link_with`](Graph::resolve_link_with)'s
//! only reach beyond a bare path/id resolver is [`crate::title::TitleIndex`], which
//! is itself a derived cache with no policy of its own (DESIGN §5) — the same
//! dependency [`census`] already carries. That is a stable seam, not a design
//! gap the coupling papers over, so no `Resolve` trait was introduced here: it
//! would exist only to abstract a single already-generic parameter
//! (`Ix: IdIndex`) and a self-contained cache type, and would cost a layer
//! of indirection for no dependency this module does not already own.
//!
//! [`crate::peer`] is not that trait arriving late. It abstracts a dependency
//! this module genuinely does not have — a map from a workspace *name* to a
//! location, which only a host holds — and nothing here consumes it: no method
//! below takes a resolver and [`Graph`] grows no third parameter for one.
//! Following a foreign reference is a step a caller takes after resolution
//! returns [`Target::Foreign`], so a traversal that never follows one is
//! unchanged by the port existing.
pub use ;
pub use ;
pub use Target;
pub use sidecar_candidates;
pub use ;
use ;
use ;
use crateIdStorage;
use crate;
use crateRelationSet;
/// The settings a *read* of a workspace depends on — the whole of what
/// traversal needs to be told about the workspace it is traversing.
///
/// Three fields out of the ten a full workspace is configured with, and the cut
/// is not arbitrary: these are the only ones that change what a link *resolves
/// to*. [`relations`](Self::relations) says which metadata fields are edges at
/// all; [`workspace_id`](Self::workspace_id) is what lets a foreign
/// `id:<ws>/<id>` reference be recognized as pointing back here rather than
/// away; [`id_storage`](Self::id_storage) says whether a document's own
/// frontmatter is a place an id can be found. The other seven — link style,
/// reference style, embed format and style, fixity, history — govern how prov
/// *writes*, and a reader that never writes has no use for any of them.
/// A readable workspace: a root, a filesystem to read it through, an id index
/// to resolve `id:` references against, and the [`ReadSettings`] that say how
/// its links are spelled.
///
/// This is the whole of what traversal needs, and — because `FS` is only ever
/// bounded by [`ReadStorage`](crate::fs::ReadStorage) and `Ix` by
/// [`IdIndex`](crate::index::IdIndex) — the whole of what it *can* do. There is
/// no method here that changes a byte on disk or a registration in the index,
/// and no way to add one without changing a trait bound in this crate.
///
/// `prov`'s `Workspace` owns one of these and forwards every read to it, adding
/// the identity policy, the change/journal machinery, and the config layer on
/// top. A consumer that only needs to *see* the workspace — a language server,
/// a renderer, a viewer — can hold a `Graph` directly and link none of that.