"If the same input must always give the same output, it belongs in Rust — fast, testable, and never guessing."
What Lives in the Rust Core
Everything on the deterministic side of the seam lives in the Rust core: applying an export ruleset (the reborn WordPress-tag layer), parsing and writing frontmatter and tags, and reading/writing files. These are pure transforms — a document plus a ruleset yields exactly one output, the same every time. There's no model, no randomness, no 'it depends.' That property is what makes them safe to run without asking anyone.
Why Rust for Determinism
Rust suits the deterministic layer for three reasons. It's fast, so file and text transforms don't stall the UI. It's safe, so the layer that touches your files won't corrupt them through a memory bug. And it's reproducible and testable — a pure function with typed inputs and outputs is exactly what you want under the part of the app that must never surprise you. The judgment layer can afford to be probabilistic; the layer that writes your files cannot, and Rust enforces that discipline.
#[tauri::command]
fn apply_ruleset(doc: String, ruleset: Ruleset) -> Result<String, String> {
// Pure transform: same doc + same ruleset -> same output, always.
// No model call, no randomness — reproducible and unit-testable.
Ok(ruleset.apply(&doc))
}
File IO Is a Rust Command
Reading and writing the .md file is itself deterministic work, so it's a Rust command invoked over Tauri's IPC — not something the frontend does directly. This honors the seam (deterministic = Rust) and it avoids the fs-scope plumbing a webview file API would need. The frontend asks the Rust core to load or save; the Rust core is the only thing that touches disk. That single owner for file IO becomes important again in Track 7, where the filesystem is declared the source of truth.