use std::collections::BTreeSet;
const ERROR_RS: &str = include_str!("../src/error.rs");
const CONNECTION_RS: &str = include_str!("../src/connection.rs");
const SECTION_7: &str = include_str!("../docs/architecture/s6-s10-flows-to-dependencies.md");
const APPENDIX_A: &str = include_str!("../docs/architecture/appendices.md");
fn block_after<'a>(text: &'a str, header: &str) -> &'a str {
let start = text
.find(header)
.unwrap_or_else(|| panic!("{header:?} not found"))
+ header.len();
let rest = &text[start..];
let mut depth = 1usize;
for (i, c) in rest.char_indices() {
match c {
'{' => depth += 1,
'}' => {
depth -= 1;
if depth == 0 {
return &rest[..i];
}
}
_ => {}
}
}
panic!("unbalanced braces after {header:?}");
}
fn variant_names(body: &str) -> BTreeSet<String> {
body.lines()
.filter_map(|line| {
let trimmed = line.trim_start();
if trimmed.starts_with("//") || trimmed.starts_with('#') {
return None;
}
let indent = line.len() - trimmed.len();
if indent != 4 {
return None;
}
let name: String = trimmed
.chars()
.take_while(|c| c.is_alphanumeric() || *c == '_')
.collect();
match name.chars().next() {
Some(c) if c.is_ascii_uppercase() => Some(name),
_ => None,
}
})
.collect()
}
#[test]
fn the_documented_error_enum_matches_the_code() {
let in_code = variant_names(block_after(ERROR_RS, "pub enum DbError {"));
let in_docs = variant_names(block_after(SECTION_7, "pub enum DbError {"));
assert!(
in_code.len() >= 27,
"only {} variants parsed out of src/error.rs — the parser has broken, \
not the docs",
in_code.len()
);
assert_eq!(
in_code,
in_docs,
"§7's copy of DbError has drifted.\n missing from the docs: {:?}\n \
in the docs but not the code: {:?}\n\
§7 is a reproduction of src/error.rs; regenerate it rather than \
patching one variant.",
in_code.difference(&in_docs).collect::<Vec<_>>(),
in_docs.difference(&in_code).collect::<Vec<_>>(),
);
}
fn public_database_methods() -> BTreeSet<String> {
let mut out = BTreeSet::new();
for line in CONNECTION_RS.lines() {
let t = line.trim_start();
for prefix in ["pub async fn ", "pub fn "] {
if let Some(rest) = t.strip_prefix(prefix) {
let name: String = rest
.chars()
.take_while(|c| c.is_alphanumeric() || *c == '_')
.collect();
if !name.is_empty() {
out.insert(name);
}
}
}
}
out
}
#[test]
fn every_public_database_method_appears_in_appendix_a() {
const EXEMPT: &[(&str, &str)] = &[
(
"raw",
"#[doc(hidden)] — D-068/D-091: reachable, not advertised",
),
(
"new",
"constructors of other types in the same file, not handle methods",
),
(
"start",
"`Turn::start`, an internal actor helper in the same file",
),
("elapsed", "`HoldTimer::elapsed`, internal"),
("epoch", "`Turn::epoch`, internal"),
(
"estimated_bulk_hold",
"free function, documented in A.1 under its own name",
),
("content", "`ConceptUpsert` builder setter"),
("embedding_model", "`ConceptUpsert` builder setter"),
("valid_from", "builder setter"),
("valid_to", "builder setter"),
("retired", "`ConceptUpsert` builder setter"),
("normalized", "builder finaliser, described in prose"),
("chunk_rows", "module, not a method"),
];
let exempt: BTreeSet<&str> = EXEMPT.iter().map(|(n, _)| *n).collect();
let missing: Vec<String> = public_database_methods()
.into_iter()
.filter(|m| !exempt.contains(m.as_str()))
.filter(|m| !APPENDIX_A.contains(m.as_str()))
.collect();
assert!(
missing.is_empty(),
"Appendix A is normative and does not mention: {missing:?}\n\
Add them to A.1, or add an entry to EXEMPT saying why they do not \
belong in the public surface."
);
}
const REGISTER: &str = include_str!("../docs/architecture/s13-decision-register.md");
fn closure_markers(version: &str) -> [String; 2] {
[
format!("DELIVERED in {version}"),
format!("RESCHEDULED from {version}"),
]
}
const SCHEDULING: &[&str] = &[
"scheduled for",
"scheduled in",
"deferred to",
"deferred until",
"revisit at",
"revisited at",
"revisit in",
];
struct Claim {
entry: String,
phrase: String,
version: String,
at: usize,
}
fn semver(text: &str) -> Option<(u32, u32, u32)> {
let mut parts = text.split('.');
let major = parts.next()?.parse().ok()?;
let minor = parts.next()?.parse().ok()?;
let patch = match parts.next() {
Some(p) => p.parse().ok()?,
None => 0,
};
if parts.next().is_some() {
return None;
}
Some((major, minor, patch))
}
fn version_at(rest: &str) -> Option<String> {
let rest = rest.trim_start();
let rest = rest.strip_prefix('`').unwrap_or(rest);
let rest = rest.strip_prefix('v').unwrap_or(rest);
let token: String = rest
.chars()
.take_while(|c| c.is_ascii_digit() || *c == '.')
.collect();
let token = token.trim_end_matches('.').to_string();
if token.contains('.') && semver(&token).is_some() {
Some(token)
} else {
None
}
}
fn entry_containing(text: &str, offset: usize) -> String {
match text[..offset].rmatch_indices("<a id=\"d-").next() {
Some((i, m)) => {
let id: String = text[i + m.len()..].chars().take_while(|c| *c != '"').collect();
format!("D-{id}")
}
None => "(no enclosing decision entry)".to_string(),
}
}
fn entry_body(text: &str, offset: usize) -> &str {
let start = text[..offset]
.rmatch_indices("<a id=\"d-")
.next()
.map(|(i, _)| i)
.unwrap_or(0);
let end = text[start + 1..]
.find("<a id=\"d-")
.map(|i| start + 1 + i)
.unwrap_or(text.len());
&text[start..end]
}
fn is_quoted(text: &str, at: usize) -> bool {
matches!(
text[..at].chars().last(),
Some('"') | Some('\'') | Some('\u{201c}') | Some('\u{2018}')
)
}
fn scheduling_claims(text: &str) -> Vec<Claim> {
let lower = text.to_lowercase();
let mut found: Vec<Claim> = SCHEDULING
.iter()
.flat_map(|phrase| {
lower.match_indices(phrase).filter_map(move |(at, _)| {
if is_quoted(text, at) {
return None;
}
version_at(&text[at + phrase.len()..]).map(|version| Claim {
entry: entry_containing(text, at),
phrase: (*phrase).to_string(),
version,
at,
})
})
})
.collect();
found.sort_by_key(|c| c.at);
found
}
#[test]
fn no_decision_still_awaits_a_release_that_has_shipped() {
let current =
semver(env!("CARGO_PKG_VERSION")).expect("CARGO_PKG_VERSION is not a semver triple");
let overdue: Vec<String> = scheduling_claims(REGISTER)
.into_iter()
.filter(|c| semver(&c.version).is_some_and(|v| v <= current))
.filter(|c| {
let body = entry_body(REGISTER, c.at);
!closure_markers(&c.version).iter().any(|m| body.contains(m))
})
.map(|c| format!("{}: \"{} {}\"", c.entry, c.phrase, c.version))
.collect();
assert!(
overdue.is_empty(),
"current version is {}, and these decisions are still waiting for a \
release that has already shipped:\n {}\n\n\
This is exactly how D-087 and D-089 sat wrong through the whole of \
0.7.0 with a green suite. Do one of two things, and not a third:\n\
\x20 - it shipped: write `DELIVERED in <that version>` into the entry;\n\
\x20 - it did not ship: write `RESCHEDULED from <that version>`, and say \
which release it waits for now.\n\
Leave the original sentence exactly as it stands. It was true when it was \
written, and a deferral that leaves no trace is the failure this test \
exists to catch.",
env!("CARGO_PKG_VERSION"),
overdue.join("\n "),
);
}
#[test]
fn the_schedule_pattern_reads_versions_and_not_prose() {
for text in [
"Scheduled for 0.7.0 alongside the other schema work.",
"scheduled for `0.9.0` with the API break named.",
"Deferred to 1.0 because the surface freezes there.",
"revisit at v0.8.0 once the measurement exists.",
] {
assert_eq!(
scheduling_claims(text).len(),
1,
"should have found a scheduling claim in: {text}"
);
}
for text in [
"the integer-index rewrite of `Subgraph` is deferred until something measures it",
"`rowid_pk` on `concepts` is deferred to the release that implements erasure",
"deferred to 2 releases later",
"Scheduled for the next cycle.",
"D-087 and D-089 both read *\"Scheduled for 0.7.0\"*, and nothing went red.",
] {
assert!(
scheduling_claims(text).is_empty(),
"should not have fired on prose: {text}"
);
}
}
#[test]
fn the_delivery_marker_is_what_settles_an_overdue_entry() {
let settled = |text: &str, version: &str| {
let claim = &scheduling_claims(text)[0];
let body = entry_body(text, claim.at);
closure_markers(version).iter().any(|m| body.contains(m))
};
let bare = "<a id=\"d-999\"></a>D-999 - a thing. Scheduled for 0.1.0.\n";
assert_eq!(scheduling_claims(bare)[0].entry, "D-999");
assert!(!settled(bare, "0.1.0"), "an unmarked entry is overdue");
let shipped = "<a id=\"d-999\"></a>D-999 - a thing. Scheduled for 0.1.0. \
Prose in between. **DELIVERED in 0.1.0.**\n";
assert!(
settled(shipped, "0.1.0"),
"the marker must be found anywhere in the entry, not only beside the phrase"
);
let missed = "<a id=\"d-999\"></a>D-999 - a thing. Scheduled for 0.1.0. \
**RESCHEDULED from 0.1.0** to 0.2.0.\n";
assert!(settled(missed, "0.1.0"), "a missed release is closed out too");
assert!(
!settled(missed, "0.2.0"),
"a marker naming one release must not settle a claim on another"
);
}
const QUICKREF: &str = include_str!("../docs/quickref.md");
const SUBGRAPH_RS: &str = include_str!("../src/graph/subgraph.rs");
const PRIVATE_FIELD_TYPES: &[&str] = &["Subgraph", "NodeData", "EdgeRef"];
fn documented_struct_body<'a>(doc: &'a str, name: &str) -> Option<&'a str> {
let header = format!("pub struct {name} ");
let at = doc
.find(&header)
.or_else(|| doc.find(&format!("pub struct {name} {{")))?;
let open = at + doc[at..].find('{')?;
let mut depth = 0usize;
for (i, c) in doc[open..].char_indices() {
match c {
'{' => depth += 1,
'}' => {
depth -= 1;
if depth == 0 {
return Some(&doc[open + 1..open + i]);
}
}
_ => {}
}
}
None
}
fn public_methods_of(source: &str, header: &str) -> BTreeSet<String> {
block_after(source, header)
.lines()
.filter_map(|l| l.trim().strip_prefix("pub "))
.map(|l| l.trim_start_matches("async ").trim_start_matches("fn "))
.filter_map(|l| l.split(['(', '<', ' ']).next())
.filter(|n| !n.is_empty())
.map(str::to_string)
.collect()
}
#[test]
fn no_document_still_advertises_a_field_b1_made_private() {
let leaked: Vec<String> = PRIVATE_FIELD_TYPES
.iter()
.filter_map(|name| {
let body = documented_struct_body(QUICKREF, name)?;
body.contains("pub ")
.then(|| format!("{name} {{{}}}", body.trim()))
})
.collect();
assert!(
leaked.is_empty(),
"docs/quickref.md still declares public fields on types B1 made \
private:\n {}\n\
The accessors are the surface now. A document that reproduces a \
declaration has the same failure mode as a copied error enum: nobody \
executes it.",
leaked.join("\n ")
);
for name in PRIVATE_FIELD_TYPES {
assert!(
documented_struct_body(QUICKREF, name).is_some(),
"docs/quickref.md no longer declares `{name}` — either it was \
dropped from the document, or this test is looking for the wrong \
thing and is now passing vacuously"
);
}
}
#[test]
fn the_quoted_subgraph_surface_lists_every_public_method() {
let declared = public_methods_of(SUBGRAPH_RS, "impl Subgraph {");
assert!(
declared.len() > 10,
"parsed only {} methods off `impl Subgraph`, which means this test is \
reading the wrong thing rather than that the type shrank: {declared:?}",
declared.len()
);
let missing: Vec<&String> = declared
.iter()
.filter(|m| !QUICKREF.contains(m.as_str()))
.collect();
assert!(
missing.is_empty(),
"`impl Subgraph` has public methods that docs/quickref.md does not \
mention: {missing:?}\n\
quickref reproduces this surface verbatim, so an accessor added \
without it is a document that describes a smaller type than the crate \
has."
);
}