use workflow_context::{ContextStore, Vgcs, DocOS, DocManager, DocNodeKind}; use tempfile::TempDir; use std::sync::Arc; const ZERO_OID: &str = "0000000000000000000000000000000000000000"; #[test] fn test_docos_basic() -> anyhow::Result<()> { let temp_dir = TempDir::new()?; let store = Arc::new(Vgcs::new(temp_dir.path())); let req_id = "req-docos-1"; store.init_repo(req_id)?; // 1. Init DocOS with empty repo let mut docos = DocOS::new(store.clone(), req_id, ZERO_OID); // 2. Create a file (Leaf) docos.write_content("Introduction", "Intro Content")?; let _commit_1 = docos.save("Add Intro")?; // 3. Verify outline let outline = docos.get_outline()?; // Root -> [Introduction (Leaf)] assert_eq!(outline.children.len(), 1); let intro_node = &outline.children[0]; assert_eq!(intro_node.name, "Introduction"); assert_eq!(intro_node.kind, DocNodeKind::Leaf); // 4. Read content let content = docos.read_content("Introduction")?; assert_eq!(content, "Intro Content"); Ok(()) } #[test] fn test_docos_fission() -> anyhow::Result<()> { let temp_dir = TempDir::new()?; let store = Arc::new(Vgcs::new(temp_dir.path())); let req_id = "req-docos-2"; store.init_repo(req_id)?; let mut docos = DocOS::new(store.clone(), req_id, ZERO_OID); // 1. Start with a Leaf: "Analysis" docos.write_content("Analysis", "General Analysis")?; let commit_1 = docos.save("Init Analysis")?; // 2. Insert subsection "Revenue" into "Analysis" // This should promote "Analysis" to Composite docos.reload(&commit_1)?; docos.insert_subsection("Analysis", "Revenue", "Revenue Data")?; let commit_2 = docos.save("Split Analysis")?; // 3. Verify Structure docos.reload(&commit_2)?; let outline = docos.get_outline()?; // Root -> [Analysis (Composite)] assert_eq!(outline.children.len(), 1); let analysis_node = &outline.children[0]; assert_eq!(analysis_node.name, "Analysis"); assert_eq!(analysis_node.kind, DocNodeKind::Composite); // Analysis -> [Revenue (Leaf)] (index.md is hidden in outline) assert_eq!(analysis_node.children.len(), 1); let revenue_node = &analysis_node.children[0]; assert_eq!(revenue_node.name, "Revenue"); assert_eq!(revenue_node.kind, DocNodeKind::Leaf); // 4. Verify Content // Reading "Analysis" should now read "Analysis/index.md" which contains "General Analysis" let analysis_content = docos.read_content("Analysis")?; assert_eq!(analysis_content, "General Analysis"); let revenue_content = docos.read_content("Analysis/Revenue")?; assert_eq!(revenue_content, "Revenue Data"); Ok(()) } #[test] fn test_docos_fusion_and_outline() -> anyhow::Result<()> { let temp_dir = TempDir::new()?; let store = Arc::new(Vgcs::new(temp_dir.path())); let req_id = "req-docos-3"; store.init_repo(req_id)?; let mut docos = DocOS::new(store.clone(), req_id, ZERO_OID); // 1. Create a composite structure (Pre-fissioned state) // Root -> [Chapter1 (Composite)] -> [SectionA (Leaf), SectionB (Leaf)] docos.write_content("Chapter1/index.md", "Chapter 1 Intro")?; docos.write_content("Chapter1/SectionA", "Content A")?; docos.write_content("Chapter1/SectionB", "Content B")?; let commit_1 = docos.save("Setup Structure")?; docos.reload(&commit_1)?; // Verify Initial Outline let outline_1 = docos.get_outline()?; let ch1 = &outline_1.children[0]; assert_eq!(ch1.kind, DocNodeKind::Composite); assert_eq!(ch1.children.len(), 2); // SectionA, SectionB // 2. Demote (Fusion) docos.demote("Chapter1")?; let commit_2 = docos.save("Demote Chapter 1")?; // 3. Verify Fusion Result docos.reload(&commit_2)?; let outline_2 = docos.get_outline()?; // Now Chapter1 should be a Leaf let ch1_fused = &outline_2.children[0]; assert_eq!(ch1_fused.name, "Chapter1"); assert_eq!(ch1_fused.kind, DocNodeKind::Leaf); // But wait! Because of our Outline Enhancement (Markdown Headers), // we expect the Fused file to have children (Sections) derived from headers! // The demote logic appends children with "# Name". // So "SectionA" became "# SectionA". // Let's inspect the children of the Fused node // We expect 2 children: "SectionA" and "SectionB" (as Sections) assert_eq!(ch1_fused.children.len(), 2); assert_eq!(ch1_fused.children[0].name, "SectionA"); assert_eq!(ch1_fused.children[0].kind, DocNodeKind::Section); assert_eq!(ch1_fused.children[1].name, "SectionB"); // 4. Verify Content of Fused File let content = docos.read_content("Chapter1")?; // Should contain Intro + # SectionA ... + # SectionB ... assert!(content.contains("Chapter 1 Intro")); assert!(content.contains("# SectionA")); assert!(content.contains("Content A")); assert!(content.contains("# SectionB")); Ok(()) }