Expand description
Plain text → walkable graph — the crate’s read core.
Underneath everything else sits the census
(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
StructuralFacts 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 map, and
reachability (reachable_files,
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 impled on Graph rather
than a graph type of its own, but they no longer require it: every
function here is bounded on ReadStorage and
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: 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 StructuralFacts rather than
prov’s Findings 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’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.
Re-exports§
pub use census::Backlink;pub use census::CensusEntry;pub use census::LinkSite;pub use census::Resolution;pub use census::StructuralFact;pub use census::inbound;pub use census::invert;pub use census::Walk;pub use census::reachable_set;pub use resolve::Target;pub use shadow::sidecar_candidates;pub use tree::Node;pub use tree::NodeKind;pub use tree::TreeOptions;
Modules§
- census
- The census types, the spanning-tree walker that fills them in, and the
reachability views built over the result. See the module doc at
crate::graphfor why the census is ground truth. - load
- The read primitive — root-escape clamp, read-scope memo, filesystem read,
Document::parse— that every pass built on top of the graph shares. See the module doc atcrate::graphfor how this sits besideresolveand the census. - manifest
- Reading manifests off the graph — the lookups every pass over a covered directory shares.
- probe
- Raw filesystem probes — root-join and delegate, nothing else.
- resolve
- Link resolution — turning one declared target (a path, an
id:reference, or a nominal[[alias]]) into aTargetagainst a workspace. See the module doc atcrate::graphfor how this sits beside the census and the read primitive inload. - scan
- Flat scans — the passes that read the tree as a directory, not as a graph.
- shadow
- Shadowed payloads — the files prov can read but must not.
- tree
- Traversal — materialize the spanning containment tree from a root document.
Structs§
- Graph
- A readable workspace: a root, a filesystem to read it through, an id index
to resolve
id:references against, and theReadSettingsthat say how its links are spelled. - Read
Settings - The settings a read of a workspace depends on — the whole of what traversal needs to be told about the workspace it is traversing.