pub mod conform;
pub mod inspect;
pub mod read;
pub mod view;
use std::collections::BTreeMap;
use std::fmt::Write as _;
use rto_graph::{Explanation, NodeSummary, Provenance};
pub const OKF_VERSION: &str = "0.2";
pub const INDEX_FILE: &str = "index.md";
pub const LOG_FILE: &str = "log.md";
const EXTREF_PREFIX: &str = "extref:";
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BundleFile {
pub path: String,
pub content: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Actor {
Human(String),
Tool(String, String),
Process(String),
}
impl Actor {
#[must_use]
pub fn as_token(&self) -> String {
match self {
Self::Human(id) => format!("human:{id}"),
Self::Tool(producer, version) => format!("{producer}/{version}"),
Self::Process(id) => format!("process:{id}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Origin {
pub by: Actor,
pub at: String,
pub confirms: bool,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Frontmatter {
pub type_: String,
pub title: Option<String>,
pub description: Option<String>,
pub resource: Option<String>,
pub tags: Vec<String>,
pub status: Option<String>,
pub origin: Option<Origin>,
pub sources: Vec<String>,
}
fn yaml_scalar(s: &str) -> String {
let mut out = String::with_capacity(s.len() + 2);
out.push('"');
for ch in s.chars() {
match ch {
'\\' => out.push_str("\\\\"),
'"' => out.push_str("\\\""),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
c if c.is_control() => {
let _ = write!(out, "\\u{:04x}", u32::from(c));
}
c => out.push(c),
}
}
out.push('"');
out
}
impl Frontmatter {
#[must_use]
pub fn render(&self) -> String {
let mut out = String::from("---\n");
let _ = writeln!(out, "type: {}", yaml_scalar(&self.type_));
for (key, value) in [
("title", self.title.as_deref()),
("description", self.description.as_deref()),
("resource", self.resource.as_deref()),
("status", self.status.as_deref()),
] {
if let Some(v) = value {
let _ = writeln!(out, "{key}: {}", yaml_scalar(v));
}
}
if !self.tags.is_empty() {
out.push_str("tags:\n");
for t in &self.tags {
let _ = writeln!(out, " - {}", yaml_scalar(t));
}
}
if let Some(origin) = &self.origin {
let _ = writeln!(
out,
"generated:\n by: {}\n at: {}",
yaml_scalar(&origin.by.as_token()),
yaml_scalar(&origin.at)
);
if origin.confirms {
let _ = writeln!(
out,
"verified:\n - by: {}\n at: {}",
yaml_scalar(&origin.by.as_token()),
yaml_scalar(&origin.at)
);
}
}
if !self.sources.is_empty() {
out.push_str("sources:\n");
for s in &self.sources {
let _ = writeln!(out, " - resource: {}", yaml_scalar(s));
}
}
out.push_str("---\n");
out
}
}
#[must_use]
pub fn section_for(kind: &str) -> &'static str {
match kind {
"adr" | "adr_section" => "decisions",
"blueprint" => "blueprints",
"doc" => "docs",
"file" => "files",
"marker" => "debt",
_ => "symbols",
}
}
const MAX_SLUG: usize = 200;
#[must_use]
pub fn slug(key: &str) -> String {
let mut out = String::with_capacity(key.len());
let mut last_dash = false;
for ch in key.chars() {
if ch.is_ascii_alphanumeric() {
out.push(ch.to_ascii_lowercase());
last_dash = false;
} else if !last_dash && !out.is_empty() {
out.push('-');
last_dash = true;
}
}
let trimmed = out.trim_end_matches('-').to_owned();
if trimmed.is_empty() {
return "concept".to_owned();
}
if trimmed.len() <= MAX_SLUG {
return trimmed;
}
let keep = MAX_SLUG - 9;
format!("{}-{}", &trimmed[..keep], short_digest(key))
}
#[must_use]
pub fn concept_path(node: &NodeSummary) -> String {
format!("/{}/{}.md", section_for(&node.kind), slug(&node.key))
}
#[must_use]
pub fn origin_for(prov: Provenance, at: &str, tool: &Actor, human: Option<&Actor>) -> Origin {
match prov {
Provenance::Authored | Provenance::ExternalDerived | Provenance::ExternalAuthored => {
match human {
Some(actor) => Origin {
by: actor.clone(),
at: at.to_owned(),
confirms: true,
},
None => Origin {
by: tool.clone(),
at: at.to_owned(),
confirms: false,
},
}
}
Provenance::Derived => Origin {
by: tool.clone(),
at: at.to_owned(),
confirms: true,
},
Provenance::Inferred | Provenance::ExternalInferred => Origin {
by: tool.clone(),
at: at.to_owned(),
confirms: false,
},
}
}
#[must_use]
pub fn render_concept(
ex: &Explanation,
fm: &Frontmatter,
body: Option<&str>,
resolve: &dyn Fn(&str) -> Option<String>,
) -> BundleFile {
let mut content = fm.render();
content.push('\n');
let text = body.map(str::trim).filter(|t| !t.is_empty());
let body_leads_with_heading = text.is_some_and(|t| t.starts_with("# "));
if !body_leads_with_heading {
let _ = writeln!(
content,
"# {}\n",
fm.title.as_deref().unwrap_or(&ex.node.name)
);
}
if let Some(text) = text {
content.push_str(text);
content.push_str("\n\n");
}
let mut groups: BTreeMap<&str, Vec<String>> = BTreeMap::new();
for (edge, direction) in ex
.outgoing
.iter()
.map(|e| (e, "→"))
.chain(ex.incoming.iter().map(|e| (e, "←")))
{
if let Some(target) = resolve(&edge.node) {
let label = edge.node.rsplit(':').next().unwrap_or(&edge.node);
let confidence = edge
.confidence
.map(|c| format!(" (confidence {c:.2})"))
.unwrap_or_default();
groups
.entry(edge.kind.as_str())
.or_default()
.push(format!("* {direction} [{label}]({target}){confidence}"));
}
}
if !groups.is_empty() {
content.push_str("## Relationships\n\n");
for (kind, mut links) in groups {
links.sort();
links.dedup();
let _ = writeln!(content, "### {kind}\n");
for link in links {
let _ = writeln!(content, "{link}");
}
content.push('\n');
}
}
BundleFile {
path: concept_path(&ex.node),
content,
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IndexEntry {
pub title: String,
pub target: String,
pub description: Option<String>,
}
#[must_use]
pub fn render_index(heading: &str, entries: &[IndexEntry]) -> String {
let mut out = format!("# {heading}\n\n");
for e in entries {
let desc = e
.description
.as_deref()
.map(|d| format!(" - {d}"))
.unwrap_or_default();
let _ = writeln!(out, "* [{}]({}){desc}", e.title, e.target);
}
out
}
#[must_use]
pub fn render_root_index(heading: &str, entries: &[IndexEntry]) -> String {
let mut out = format!("---\nokf_version: {}\n---\n\n", yaml_scalar(OKF_VERSION));
out.push_str(&render_index(heading, entries));
out
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LogDay {
pub date: String,
pub entries: Vec<String>,
}
#[must_use]
pub fn render_log(heading: &str, days: &[LogDay]) -> String {
let mut out = format!("# {heading}\n\n");
for day in days {
let _ = writeln!(out, "## {}\n", day.date);
for entry in &day.entries {
let _ = writeln!(out, "* {entry}");
}
out.push('\n');
}
out
}
pub struct Concept<'a> {
pub explanation: &'a Explanation,
pub frontmatter: Frontmatter,
pub body: Option<String>,
pub member: Option<String>,
}
struct Placed<'a> {
member: Option<String>,
dir: String,
concepts: Vec<(Concept<'a>, String)>,
}
#[must_use]
pub fn assemble(concepts: Vec<Concept<'_>>, title: &str, log: &[LogDay]) -> Vec<BundleFile> {
let mut by_section: BTreeMap<(Option<String>, &'static str), Vec<Concept<'_>>> =
BTreeMap::new();
let mut ordered = concepts;
ordered.sort_by(|a, b| a.explanation.node.key.cmp(&b.explanation.node.key));
for c in ordered {
by_section
.entry((c.member.clone(), section_for(&c.explanation.node.kind)))
.or_default()
.push(c);
}
let mut placed: Vec<Placed<'_>> = Vec::new();
let mut index: BTreeMap<Option<String>, BTreeMap<String, String>> = BTreeMap::new();
for ((member, section), members) in by_section {
let dir = member
.as_deref()
.map_or_else(|| section.to_owned(), |m| format!("{}/{section}", slug(m)));
let mut taken: BTreeMap<String, usize> = BTreeMap::new();
let mut concepts: Vec<(Concept<'_>, String)> = Vec::with_capacity(members.len());
let member_index = index.entry(member.clone()).or_default();
for c in members {
let base = slug(&c.explanation.node.key);
let name = match taken.get(&base) {
None => base.clone(),
Some(_) => format!("{base}-{}", short_digest(&c.explanation.node.key)),
};
*taken.entry(base).or_insert(0) += 1;
let path = format!("/{dir}/{name}.md");
member_index.insert(c.explanation.node.key.clone(), path.clone());
concepts.push((c, path));
}
placed.push(Placed {
member,
dir,
concepts,
});
}
let mut files = Vec::new();
let mut sections: Vec<IndexEntry> = Vec::new();
for section in placed {
let member_index = index.get(§ion.member);
let dir = §ion.dir;
let mut entries: Vec<IndexEntry> = Vec::with_capacity(section.concepts.len());
for (c, path) in §ion.concepts {
let title = c
.frontmatter
.title
.clone()
.unwrap_or_else(|| c.explanation.node.name.clone());
entries.push(IndexEntry {
title,
target: path.clone(),
description: c.frontmatter.description.clone(),
});
let mut file =
render_concept(c.explanation, &c.frontmatter, c.body.as_deref(), &|key| {
cross_member_target(&index, key)
.or_else(|| member_index.and_then(|m| m.get(key)).cloned())
});
file.path.clone_from(path);
files.push(file);
}
files.push(BundleFile {
path: format!("/{dir}/{INDEX_FILE}"),
content: render_index(dir, &entries),
});
sections.push(IndexEntry {
title: dir.clone(),
target: format!("/{dir}/{INDEX_FILE}"),
description: Some(format!("{} concept(s)", section.concepts.len())),
});
}
if !log.is_empty() {
files.push(BundleFile {
path: format!("/{LOG_FILE}"),
content: render_log("Update Log", log),
});
}
files.push(BundleFile {
path: format!("/{INDEX_FILE}"),
content: render_root_index(title, §ions),
});
files.sort_by(|a, b| a.path.cmp(&b.path));
files
}
fn cross_member_target(
index: &BTreeMap<Option<String>, BTreeMap<String, String>>,
key: &str,
) -> Option<String> {
let qualified = key.strip_prefix(EXTREF_PREFIX).unwrap_or(key);
let (project, bare) = rto_graph::parse_qualified(qualified)?;
index.get(&Some(project.to_owned()))?.get(bare).cloned()
}
fn short_digest(key: &str) -> String {
let mut h: u64 = 0xcbf2_9ce4_8422_2325;
for b in key.as_bytes() {
h ^= u64::from(*b);
h = h.wrapping_mul(0x0000_0100_0000_01b3);
}
format!("{:08x}", h & 0xffff_ffff)
}
#[cfg(test)]
mod tests {
use super::*;
fn node(key: &str, kind: &str, name: &str) -> NodeSummary {
NodeSummary {
key: key.to_owned(),
kind: kind.to_owned(),
name: name.to_owned(),
path: None,
lang: None,
}
}
fn explanation(key: &str, kind: &str, name: &str) -> Explanation {
Explanation {
schema: rto_graph::SCHEMA,
node: node(key, kind, name),
meta: serde_json::Value::Null,
outgoing: Vec::new(),
incoming: Vec::new(),
}
}
fn concept<'a>(ex: &'a Explanation, type_: &str) -> Concept<'a> {
Concept {
explanation: ex,
frontmatter: Frontmatter {
type_: type_.to_owned(),
..Frontmatter::default()
},
body: None,
member: None,
}
}
fn edge(to: &str) -> rto_graph::EdgeRef {
rto_graph::EdgeRef {
kind: "references".to_owned(),
provenance: "authored",
confidence: None,
node: to.to_owned(),
}
}
fn internal_links(files: &[BundleFile]) -> Vec<(String, String)> {
let mut out = Vec::new();
for f in files {
let mut rest = f.content.as_str();
while let Some(open) = rest.find("](/") {
rest = &rest[open + 2..];
let Some(close) = rest.find(')') else { break };
out.push((f.path.clone(), rest[..close].to_owned()));
rest = &rest[close..];
}
}
out
}
#[test]
fn every_emitted_link_resolves_to_a_file_that_exists() {
let section = {
let mut ex = explanation(
"blueprint:docs/blueprint/roteiro.md#1-crate-placement",
"blueprint_section",
"1 · Crate placement",
);
ex.outgoing = vec![edge("blueprint:docs/blueprint/roteiro.md")];
ex
};
let plan = {
let mut ex = explanation(
"blueprint:docs/blueprint/roteiro.md",
"blueprint",
"roteiro.md",
);
ex.outgoing = vec![
edge("blueprint:docs/blueprint/roteiro.md#1-crate-placement"),
edge("sym:rust:a/b.rs#Thing"),
edge("sym:rust:a-b.rs#thing"),
];
ex
};
let thing_a = explanation("sym:rust:a/b.rs#Thing", "fn", "Thing");
let thing_b = explanation("sym:rust:a-b.rs#thing", "fn", "thing");
assert_eq!(
slug(&thing_a.node.key),
slug(&thing_b.node.key),
"the fixture must actually collide, or the digest suffix is never exercised"
);
let concepts: Vec<Concept<'_>> = [
(§ion, "blueprint_section"),
(&plan, "blueprint"),
(&thing_a, "fn"),
(&thing_b, "fn"),
]
.into_iter()
.map(|(ex, type_)| {
let mut c = concept(ex, type_);
c.member = Some("Alpha".to_owned());
c
})
.collect();
let files = assemble(concepts, "Workspace", &[]);
let emitted: std::collections::BTreeSet<&str> =
files.iter().map(|f| f.path.as_str()).collect();
assert!(
emitted
.iter()
.all(|p| *p == "/index.md" || p.starts_with("/alpha/")),
"every concept must nest under its member: {emitted:?}"
);
assert!(
emitted.contains("/alpha/symbols/sym-rust-a-b-rs-thing.md"),
"the first collision partner keeps the bare slug: {emitted:?}"
);
assert!(
emitted
.iter()
.any(|p| p.starts_with("/alpha/symbols/sym-rust-a-b-rs-thing-")),
"the second takes a digest suffix: {emitted:?}"
);
assert!(
emitted.contains(
"/alpha/symbols/blueprint-docs-blueprint-roteiro-md-1-crate-placement.md"
),
"a `blueprint_section` files under `symbols`, not under its key's \
`blueprints`: {emitted:?}"
);
let links = internal_links(&files);
assert_eq!(links.len(), 4 + 4 + 2, "{links:?}");
for (from, target) in &links {
assert!(
emitted.contains(target.as_str()),
"{from} links to {target}, which the bundle does not contain: {emitted:?}"
);
}
let plan_path = "/alpha/blueprints/blueprint-docs-blueprint-roteiro-md.md";
let from_plan: std::collections::BTreeSet<&str> = links
.iter()
.filter(|(from, _)| from == plan_path)
.map(|(_, target)| target.as_str())
.collect();
assert_eq!(
from_plan.len(),
plan.outgoing.len(),
"{plan_path} has {} edges to distinct concepts but links to {} file(s): {from_plan:?}",
plan.outgoing.len(),
from_plan.len()
);
}
#[test]
fn every_emitted_bundle_is_conformant() {
let a = explanation("adr:0001#decision", "adr", "ADR-0001");
let b = explanation("sym:rust:src/main.rs#greet", "fn", "greet");
let files = assemble(
vec![concept(&a, "adr"), concept(&b, "fn")],
"Roteiro",
&[LogDay {
date: "2026-08-28".into(),
entries: vec!["**Update**: rebuilt.".into()],
}],
);
for f in &files {
let reserved = f.path.ends_with(INDEX_FILE) || f.path.ends_with(LOG_FILE);
if reserved {
continue;
}
assert!(
f.content.starts_with("---\n"),
"{} opens with no frontmatter block",
f.path
);
let end = f.content[4..]
.find("\n---\n")
.expect("frontmatter must terminate");
let block = &f.content[4..4 + end];
assert!(
block
.lines()
.any(|l| l.starts_with("type: ") && l.len() > 8),
"{} carries no non-empty `type`: {block}",
f.path
);
}
let nested = files
.iter()
.find(|f| f.path == "/decisions/index.md")
.expect("a per-directory index");
assert!(!nested.content.starts_with("---"), "{}", nested.content);
let root = files
.iter()
.find(|f| f.path == "/index.md")
.expect("a root index");
assert!(
root.content.contains("okf_version: \"0.2\""),
"{}",
root.content
);
}
#[test]
fn a_body_with_its_own_heading_is_not_double_titled() {
let ex = explanation("adr:0010", "adr", "ADR-0010");
let fm = Frontmatter {
type_: "adr".into(),
title: Some("Explorer web app".into()),
..Frontmatter::default()
};
let with = render_concept(
&ex,
&fm,
Some("# ADR-0010: Explorer web app\n\nBody."),
&|_| None,
);
let h1s = |c: &str| c.lines().filter(|l| l.starts_with("# ")).count();
assert_eq!(h1s(&with.content), 1, "exactly one H1: {}", with.content);
assert!(with.content.contains("# ADR-0010: Explorer web app"));
assert!(
!with.content.contains("# Explorer web app\n\n# ADR-0010"),
"the frontmatter title must not be stacked above the document's own"
);
let without = render_concept(&ex, &fm, Some("Just prose."), &|_| None);
assert!(
without.content.contains("# Explorer web app"),
"a headingless body still gets the title: {}",
without.content
);
assert_eq!(h1s(&without.content), 1);
}
#[test]
fn two_members_sharing_a_key_both_survive() {
let a = explanation("file:README.md", "file", "README.md");
let b = explanation("file:README.md", "file", "README.md");
let mut ca = concept(&a, "file");
ca.member = Some("app".to_owned());
let mut cb = concept(&b, "file");
cb.member = Some("lib".to_owned());
let files = assemble(vec![ca, cb], "Workspace", &[]);
let concepts: Vec<&BundleFile> = files
.iter()
.filter(|f| !f.path.ends_with(INDEX_FILE) && !f.path.ends_with(LOG_FILE))
.collect();
assert_eq!(concepts.len(), 2, "both members' README must be written");
assert!(
concepts.iter().any(|f| f.path.starts_with("/app/")),
"one under its member: {:?}",
concepts.iter().map(|f| &f.path).collect::<Vec<_>>()
);
assert!(concepts.iter().any(|f| f.path.starts_with("/lib/")));
}
#[test]
fn the_placeholder_prefix_is_the_graphs() {
assert_eq!(rto_graph::external_ref_key(""), EXTREF_PREFIX);
}
#[test]
fn a_cross_repo_reference_reaches_the_other_members_concept() {
let real = explanation("file:README.md", "file", "README.md");
let stub = explanation(
"extref:app::file:README.md",
"external_ref",
"app::file:README.md",
);
let referrer = {
let mut ex = explanation("doc:deploy.md", "doc", "deploy.md");
ex.outgoing = vec![edge("extref:app::file:README.md")];
ex
};
let member = |ex, type_, name: &str| {
let mut c = concept(ex, type_);
c.member = Some(name.to_owned());
c
};
let files = assemble(
vec![
member(&real, "file", "app"),
member(&stub, "external_ref", "deploy"),
member(&referrer, "doc", "deploy"),
],
"Workspace",
&[],
);
let emitted: std::collections::BTreeSet<&str> =
files.iter().map(|f| f.path.as_str()).collect();
let target = "/app/files/file-readme-md.md";
assert!(
emitted.contains(target),
"the fixture must place the real concept: {emitted:?}"
);
let stub_path = "/deploy/symbols/extref-app-file-readme-md.md";
assert!(
emitted.contains(stub_path),
"the placeholder must still be a concept: {emitted:?}"
);
let links = internal_links(&files);
let targets: Vec<&str> = links
.iter()
.filter(|(from, _)| from == "/deploy/docs/doc-deploy-md.md")
.map(|(_, t)| t.as_str())
.collect();
assert_eq!(
targets,
vec![target],
"the reference must reach `app`'s concept rather than `deploy`'s stub"
);
}
#[test]
fn an_index_lists_a_section_and_a_member_directory_is_a_container() {
let readme = explanation("file:README.md", "file", "README.md");
let thing = explanation("sym:rust:a.rs#thing", "fn", "thing");
let member = |ex, type_, name: &str| {
let mut c = concept(ex, type_);
c.member = Some(name.to_owned());
c
};
let files = assemble(
vec![
member(&readme, "file", "app"),
member(&thing, "fn", "deploy"),
],
"Workspace",
&[],
);
let emitted: std::collections::BTreeSet<&str> =
files.iter().map(|f| f.path.as_str()).collect();
assert!(
emitted.contains("/app/files/file-readme-md.md")
&& emitted.contains("/deploy/symbols/sym-rust-a-rs-thing.md"),
"the fixture must place a concept in each member: {emitted:?}"
);
let index_suffix = format!("/{INDEX_FILE}");
let indexes: Vec<&str> = files
.iter()
.map(|f| f.path.as_str())
.filter(|p| p.ends_with(&index_suffix))
.collect();
assert_eq!(
indexes,
vec![
"/app/files/index.md",
"/deploy/symbols/index.md",
"/index.md"
],
"the bundle root and every section directory carry an index, and a \
member directory carries none"
);
let from_root: Vec<String> = internal_links(&files)
.into_iter()
.filter(|(from, _)| from == "/index.md")
.map(|(_, target)| target)
.collect();
assert_eq!(
from_root,
vec![
"/app/files/index.md".to_owned(),
"/deploy/symbols/index.md".to_owned()
],
"the root index must reach each section directly, since the member \
directory between them carries no index of its own"
);
}
#[test]
fn an_overlong_key_is_truncated_without_colliding() {
let long = "sym:rust:".to_owned() + &"a".repeat(400);
let a = format!("{long}#one");
let b = format!("{long}#two");
assert!(
slug(&a).len() <= MAX_SLUG,
"slug must fit: {}",
slug(&a).len()
);
assert!(slug(&b).len() <= MAX_SLUG);
assert_ne!(
slug(&a),
slug(&b),
"two keys sharing a truncated prefix must not slug to one name"
);
assert!(slug(&a).len() + ".md".len() + 9 <= 255);
}
#[test]
fn colliding_slugs_do_not_lose_a_concept() {
let a = explanation("sym:rust:a/b.rs#Thing", "fn", "Thing");
let b = explanation("sym:rust:a-b.rs#thing", "fn", "thing");
assert_eq!(
slug(&a.node.key).to_ascii_lowercase(),
slug(&b.node.key).to_ascii_lowercase(),
"fixture must actually collide, or this test proves nothing"
);
let files = assemble(vec![concept(&a, "fn"), concept(&b, "fn")], "T", &[]);
let concepts: Vec<&BundleFile> = files
.iter()
.filter(|f| !f.path.ends_with(INDEX_FILE) && !f.path.ends_with(LOG_FILE))
.collect();
assert_eq!(concepts.len(), 2, "both concepts must be written");
let paths: std::collections::BTreeSet<String> = concepts
.iter()
.map(|f| f.path.to_ascii_lowercase())
.collect();
assert_eq!(
paths.len(),
2,
"and to distinct files even when case is folded: {paths:?}"
);
}
#[test]
fn assembly_is_deterministic() {
let a = explanation("sym:rust:a.rs#a", "fn", "a");
let b = explanation("sym:rust:z.rs#z", "fn", "z");
assert_eq!(
section_for(&a.node.kind),
section_for(&b.node.kind),
"the fixtures must share a section, or ordering is not under test"
);
let once = assemble(vec![concept(&a, "fn"), concept(&b, "fn")], "T", &[]);
let twice = assemble(vec![concept(&b, "fn"), concept(&a, "fn")], "T", &[]);
assert_eq!(once, twice, "input order must not change the bundle");
}
fn tool() -> Actor {
Actor::Tool("roteiro".into(), "4.0.0".into())
}
#[test]
fn the_only_required_field_is_type() {
let fm = Frontmatter {
type_: "adr".into(),
..Frontmatter::default()
};
let rendered = fm.render();
assert_eq!(rendered, "---\ntype: \"adr\"\n---\n");
}
#[test]
fn actors_use_the_forms_the_spec_requires() {
assert_eq!(Actor::Human("pixie79".into()).as_token(), "human:pixie79");
assert_eq!(tool().as_token(), "roteiro/4.0.0");
assert_eq!(
Actor::Process("nightly".into()).as_token(),
"process:nightly"
);
}
#[test]
fn provenance_maps_onto_the_trust_tiers() {
let human = Actor::Human("pixie79".into());
let at = "2026-08-28T10:00:00Z";
let authored = origin_for(Provenance::Authored, at, &tool(), Some(&human));
let fm = Frontmatter {
type_: "adr".into(),
origin: Some(authored),
..Frontmatter::default()
};
let rendered = fm.render();
assert!(
rendered.contains("verified:") && rendered.contains("human:pixie79"),
"authored prose is human-reviewed: {rendered}"
);
let derived = origin_for(Provenance::Derived, at, &tool(), Some(&human));
let fm = Frontmatter {
type_: "fn".into(),
origin: Some(derived),
..Frontmatter::default()
};
let rendered = fm.render();
assert!(
rendered.contains("verified:"),
"deterministic extraction is machine-confirmed: {rendered}"
);
assert!(
!rendered.contains("human:"),
"but it is not human-reviewed — the prefix is the only thing that \
separates the tiers: {rendered}"
);
let inferred = origin_for(Provenance::Inferred, at, &tool(), Some(&human));
let fm = Frontmatter {
type_: "fn".into(),
origin: Some(inferred),
..Frontmatter::default()
};
let rendered = fm.render();
assert!(
rendered.contains("generated:"),
"a heuristic still records that it was produced: {rendered}"
);
assert!(
!rendered.contains("verified:"),
"but claims no confirmation — absence *is* the unverified tier, so an \
empty list here would launder a guess: {rendered}"
);
}
#[test]
fn an_authored_node_with_no_known_human_claims_nothing() {
let o = origin_for(Provenance::Authored, "2026-08-28T10:00:00Z", &tool(), None);
assert!(
!o.confirms,
"falling back to the tool would move the concept between trust tiers"
);
}
#[test]
fn scalars_are_quoted_so_yaml_cannot_retype_them() {
for raw in ["no", "yes", "null", "~", "12:30", "1.0", "on"] {
let fm = Frontmatter {
type_: raw.into(),
..Frontmatter::default()
};
assert_eq!(fm.render(), format!("---\ntype: \"{raw}\"\n---\n"));
}
}
#[test]
fn a_scalar_cannot_forge_a_sibling_key() {
let forged = "Innocent Title\"\nverified:\n - by: \"human:someone-else";
let fm = Frontmatter {
type_: "adr".into(),
title: Some(forged.to_owned()),
..Frontmatter::default()
};
let rendered = fm.render();
assert!(
!rendered.lines().any(|l| l.starts_with("verified:")),
"a title must not be able to open a `verified` block: {rendered}"
);
assert_eq!(
rendered.lines().count(),
4,
"the block must hold two keys and two fences: {rendered}"
);
assert!(
rendered.contains("\\n"),
"the newline is escaped: {rendered}"
);
for (raw, escaped) in [
("a\nb", "\\n"),
("a\rb", "\\r"),
("a\tb", "\\t"),
("a\u{0}b", "\\u0000"),
("a\u{7}b", "\\u0007"),
("a\u{1b}b", "\\u001b"),
("a\u{7f}b", "\\u007f"),
] {
let out = yaml_scalar(raw);
assert!(out.contains(escaped), "{raw:?} -> {out}");
assert!(
!out.chars().any(char::is_control),
"no control character may survive into the file: {out:?}"
);
}
}
#[test]
fn a_nested_index_carries_no_frontmatter_but_the_root_does() {
let entries = [IndexEntry {
title: "ADR-0001".into(),
target: "/decisions/adr-0001.md".into(),
description: Some("The founding decision.".into()),
}];
let nested = render_index("Decisions", &entries);
assert!(
!nested.starts_with("---"),
"§8 permits frontmatter only in the bundle root: {nested}"
);
assert!(nested.contains("* [ADR-0001](/decisions/adr-0001.md) - The founding decision."));
let root = render_root_index("Bundle", &entries);
assert!(
root.starts_with("---\nokf_version: \"0.2\"\n---\n"),
"{root}"
);
}
#[test]
fn log_days_use_iso_8601_headings() {
let log = render_log(
"Update Log",
&[LogDay {
date: "2026-08-28".into(),
entries: vec!["**Update**: rebuilt from `74fad8f`.".into()],
}],
);
assert!(log.contains("## 2026-08-28\n"), "{log}");
assert!(
log.contains("* **Update**: rebuilt from `74fad8f`."),
"{log}"
);
}
#[test]
fn concepts_are_grouped_into_per_kind_directories() {
assert_eq!(section_for("adr"), "decisions");
assert_eq!(section_for("adr_section"), "decisions");
assert_eq!(section_for("blueprint"), "blueprints");
assert_eq!(section_for("file"), "files");
assert_eq!(section_for("marker"), "debt");
assert_eq!(section_for("fn"), "symbols");
assert_eq!(section_for("struct"), "symbols");
assert_eq!(section_for("trait"), "symbols");
}
#[test]
fn slugs_are_stable_and_filesystem_safe() {
assert_eq!(
slug("sym:rust:src/main.rs#greet"),
"sym-rust-src-main-rs-greet"
);
assert_eq!(slug("adr:0001#decision"), "adr-0001-decision");
assert_eq!(slug("a//b"), "a-b");
assert_eq!(slug("trailing///"), "trailing");
assert_eq!(slug("###"), "concept");
}
#[test]
fn the_digest_is_always_eight_hex_digits() {
let mut keys: Vec<String> = vec![
String::new(),
"a".into(),
"sym:rust:src/main.rs#greet".into(),
"ünïcødé::key".into(),
"x".repeat(4096),
];
keys.extend((0..512).map(|i| format!("sym:rust:crates/a/src/b{i}.rs#Thing{i}")));
for key in &keys {
let digest = short_digest(key);
assert_eq!(digest.len(), 8, "{key:?} -> {digest}");
assert!(
digest
.chars()
.all(|c| c.is_ascii_digit() || ('a'..='f').contains(&c)),
"lowercase hex only: {key:?} -> {digest}"
);
}
assert_eq!(short_digest("adr:0001"), short_digest("adr:0001"));
}
}