Skip to main content

omne_cli/
scaffold.rs

1//! Volume directory scaffolding.
2//!
3//! Creates the `.omne/` directory structure, writes the `CLAUDE.md`
4//! bootloader, and writes the stamped `MANIFEST.md`. All operations
5//! are idempotent — `create_dir_all` does not error on existing dirs.
6
7// Items below are first used when Unit 8a wires this module into
8// `init::run`. Until then, only the inline test module uses them.
9#![allow(dead_code)]
10
11use std::io;
12use std::path::Path;
13
14/// Bootloader content written to `CLAUDE.md` at the volume root.
15///
16/// Uses Claude Code `@path` import syntax so the MANIFEST (and everything
17/// it transitively imports) is auto-loaded into context. Prose-style
18/// `Read X` directives were unreliable — the model had to consciously
19/// follow them each turn.
20const BOOTLOADER_CONTENT: &str = "\
21# CLAUDE.md
22
23> Bootloader — loads the omne kernel.
24
25@.omne/MANIFEST.md
26";
27
28/// Create the `.omne/` directory structure with `cfg/` and `log/`.
29pub fn create_volume_dirs(root: &Path) -> io::Result<()> {
30    let omne = root.join(".omne");
31    std::fs::create_dir_all(omne.join("cfg"))?;
32    std::fs::create_dir_all(omne.join("log"))?;
33    Ok(())
34}
35
36/// Write the `CLAUDE.md` bootloader to the volume root.
37pub fn write_bootloader(root: &Path) -> io::Result<()> {
38    std::fs::write(root.join("CLAUDE.md"), BOOTLOADER_CONTENT)
39}
40
41/// Write stamped manifest content to `.omne/MANIFEST.md`.
42pub fn write_manifest(root: &Path, content: &str) -> io::Result<()> {
43    std::fs::write(root.join(".omne").join("MANIFEST.md"), content)
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use tempfile::TempDir;
50
51    // -- create_volume_dirs --
52
53    #[test]
54    fn creates_omne_dir() {
55        let tmp = TempDir::new().unwrap();
56        create_volume_dirs(tmp.path()).unwrap();
57        assert!(tmp.path().join(".omne").is_dir());
58    }
59
60    #[test]
61    fn creates_cfg_dir() {
62        let tmp = TempDir::new().unwrap();
63        create_volume_dirs(tmp.path()).unwrap();
64        assert!(tmp.path().join(".omne").join("cfg").is_dir());
65    }
66
67    #[test]
68    fn creates_log_dir() {
69        let tmp = TempDir::new().unwrap();
70        create_volume_dirs(tmp.path()).unwrap();
71        assert!(tmp.path().join(".omne").join("log").is_dir());
72    }
73
74    #[test]
75    fn idempotent() {
76        let tmp = TempDir::new().unwrap();
77        create_volume_dirs(tmp.path()).unwrap();
78        create_volume_dirs(tmp.path()).unwrap();
79        assert!(tmp.path().join(".omne").is_dir());
80    }
81
82    // -- write_bootloader --
83
84    #[test]
85    fn creates_claude_md() {
86        let tmp = TempDir::new().unwrap();
87        write_bootloader(tmp.path()).unwrap();
88        assert!(tmp.path().join("CLAUDE.md").is_file());
89    }
90
91    #[test]
92    fn bootloader_references_manifest() {
93        let tmp = TempDir::new().unwrap();
94        write_bootloader(tmp.path()).unwrap();
95        let content = std::fs::read_to_string(tmp.path().join("CLAUDE.md")).unwrap();
96        assert!(content.contains(".omne/MANIFEST.md"));
97    }
98
99    // -- write_manifest --
100
101    #[test]
102    fn writes_manifest_file() {
103        let tmp = TempDir::new().unwrap();
104        std::fs::create_dir_all(tmp.path().join(".omne")).unwrap();
105        write_manifest(tmp.path(), "test content").unwrap();
106        let path = tmp.path().join(".omne").join("MANIFEST.md");
107        assert!(path.is_file());
108        assert_eq!(std::fs::read_to_string(path).unwrap(), "test content");
109    }
110}