dx_forge/api/
codegen.rs

1//! Generated Code Governance APIs
2
3use anyhow::Result;
4use std::path::{Path, PathBuf};
5use std::collections::HashMap;
6use parking_lot::RwLock;
7use std::sync::Arc;
8
9#[derive(Debug, Clone)]
10pub struct GeneratedRegion {
11    pub start_line: usize,
12    pub end_line: usize,
13    pub generator_tool: String,
14    pub allow_manual_edit: bool,
15}
16
17static mut CODE_REGIONS: Option<Arc<RwLock<HashMap<PathBuf, Vec<GeneratedRegion>>>>> = None;
18static mut FILE_OWNERSHIP: Option<Arc<RwLock<HashMap<PathBuf, String>>>> = None;
19
20fn get_regions() -> Arc<RwLock<HashMap<PathBuf, Vec<GeneratedRegion>>>> {
21    unsafe {
22        if CODE_REGIONS.is_none() {
23            CODE_REGIONS = Some(Arc::new(RwLock::new(HashMap::new())));
24        }
25        CODE_REGIONS.as_ref().unwrap().clone()
26    }
27}
28
29fn get_ownership() -> Arc<RwLock<HashMap<PathBuf, String>>> {
30    unsafe {
31        if FILE_OWNERSHIP.is_none() {
32            FILE_OWNERSHIP = Some(Arc::new(RwLock::new(HashMap::new())));
33        }
34        FILE_OWNERSHIP.as_ref().unwrap().clone()
35    }
36}
37
38pub fn mark_code_region_as_dx_generated(
39    file: &Path,
40    start_line: usize,
41    end_line: usize,
42    generator_tool: &str
43) -> Result<()> {
44    let regions = get_regions();
45    let mut regions = regions.write();
46    
47    let region = GeneratedRegion {
48        start_line,
49        end_line,
50        generator_tool: generator_tool.to_string(),
51        allow_manual_edit: false,
52    };
53    
54    regions.entry(file.to_path_buf())
55        .or_insert_with(Vec::new)
56        .push(region);
57    
58    tracing::debug!("🏷️  Marked lines {}-{} in {:?} as generated by {}",
59        start_line, end_line, file, generator_tool);
60    
61    Ok(())
62}
63
64pub fn is_region_dx_generated(file: &Path, line: usize) -> Result<bool> {
65    let regions = get_regions();
66    let regions = regions.read();
67    
68    if let Some(file_regions) = regions.get(file) {
69        Ok(file_regions.iter().any(|r| line >= r.start_line && line <= r.end_line))
70    } else {
71        Ok(false)
72    }
73}
74
75pub fn allow_safe_manual_edit_of_generated_code(file: &Path, line: usize) -> Result<()> {
76    let regions = get_regions();
77    let mut regions = regions.write();
78    
79    if let Some(file_regions) = regions.get_mut(file) {
80        for region in file_regions {
81            if line >= region.start_line && line <= region.end_line {
82                region.allow_manual_edit = true;
83                tracing::info!("✏️  Allowed manual editing of generated region in {:?}", file);
84                return Ok(());
85            }
86        }
87    }
88    
89    anyhow::bail!("No generated region found at line {} in {:?}", line, file)
90}
91
92pub fn claim_full_ownership_of_file(file: &Path, owner_tool: &str) -> Result<()> {
93    let ownership = get_ownership();
94    let mut ownership = ownership.write();
95    
96    tracing::info!("🔒 Tool '{}' claimed ownership of {:?}", owner_tool, file);
97    ownership.insert(file.to_path_buf(), owner_tool.to_string());
98    
99    Ok(())
100}
101
102pub fn release_ownership_of_file(file: &Path) -> Result<()> {
103    let ownership = get_ownership();
104    let mut ownership = ownership.write();
105    
106    if ownership.remove(file).is_some() {
107        tracing::info!("🔓 Released ownership of {:?}", file);
108    }
109    
110    Ok(())
111}