rto_render/lib.rs
1//! Renderers over the Roteiro graph. All outputs — docs site, OKF bundle,
2//! and the optional MCP server (feature `mcp`) — are build products of the
3//! same store, so humans and agents always see the same data.
4
5mod docs;
6/// The OKF bundle renderer (#663) — the open-format successor to the vault.
7pub mod okf;
8/// The one place a tool's class is written, and the report that stands in for a
9/// class an operator did not load (#664).
10pub mod tool_class;
11/// The one place each shared tool description is written (#590).
12pub mod tool_text;
13
14#[cfg(feature = "mcp")]
15pub mod mcp;
16
17pub use docs::{
18 IndexEntry, NavEntry, PublishedPages, RenderedAdr, SourceBase, markdown_to_html, render_adr,
19 render_adr_index, render_doc, render_doc_at, render_nav, render_site_page, replace_site_nav,
20};
21
22/// A render target for the graph.
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum Target {
25 /// Static documentation website (ADRs, blueprints, AI context pages).
26 DocsSite,
27 /// An Open Knowledge Format bundle (OKF v0.2).
28 ///
29 /// Replaced `ObsidianVault` in 4.0.0. The vault was one-way — Roteiro wrote
30 /// it, nothing read it back, and only Obsidian could consume it. An OKF
31 /// bundle is markdown with YAML frontmatter in nested directories, so
32 /// Obsidian still opens it as a vault; what changed is that the output now
33 /// targets a specification with other consumers rather than one
34 /// application's conventions.
35 OkfBundle,
36}
37
38impl Target {
39 /// Stable CLI name for this target.
40 #[must_use]
41 pub fn as_str(self) -> &'static str {
42 match self {
43 Self::DocsSite => "docs",
44 Self::OkfBundle => "okf",
45 }
46 }
47
48 /// Parse a target from its CLI name.
49 #[must_use]
50 pub fn parse(s: &str) -> Option<Self> {
51 match s {
52 "docs" => Some(Self::DocsSite),
53 "okf" => Some(Self::OkfBundle),
54 _ => None,
55 }
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::Target;
62
63 #[test]
64 fn target_names_are_stable() {
65 assert_eq!(Target::DocsSite.as_str(), "docs");
66 assert_eq!(Target::OkfBundle.as_str(), "okf");
67 assert_eq!(Target::parse("docs"), Some(Target::DocsSite));
68 assert_eq!(Target::parse("okf"), Some(Target::OkfBundle));
69 // The removed target must not silently resolve to something else: a
70 // script still passing `obsidian` should be told, not quietly redirected.
71 assert_eq!(Target::parse("obsidian"), None);
72 assert_eq!(Target::parse("nope"), None);
73 }
74}