Skip to main content

omena_lsp_server/
frame_aware_refresh.rs

1use omena_cascade::DiagnosticFrameFootprintV0;
2use omena_incremental::select_frame_aware_recheck_set;
3use serde::Serialize;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
6#[serde(rename_all = "camelCase")]
7pub struct FrameAwareRefreshReportV0 {
8    pub schema_version: &'static str,
9    pub product: &'static str,
10    pub feature_gate: &'static str,
11    pub selective_refresh_enabled: bool,
12    pub edited_module_count: usize,
13    pub selected_diagnostic_instance_ids: Vec<String>,
14    pub skipped_diagnostic_instance_ids: Vec<String>,
15    pub layer_marker: &'static str,
16}
17
18#[derive(Debug, Clone, PartialEq, Serialize)]
19#[serde(rename_all = "camelCase")]
20pub struct FrameAwareRefreshComparisonV0 {
21    pub schema_version: &'static str,
22    pub product: &'static str,
23    pub fixed_workspace_fixture: &'static str,
24    pub diagnostic_frame_count: usize,
25    pub edited_module_count: usize,
26    pub unconditional_selected_count: usize,
27    pub selective_selected_count: usize,
28    pub skipped_diagnostic_count: usize,
29    pub selected_work_reduction_count: usize,
30    pub selected_work_reduction_ratio: f64,
31    pub measured_latency_proxy: &'static str,
32    pub selective_refresh_enabled_by_default: bool,
33    pub feature_gate: &'static str,
34    pub disable_gate: &'static str,
35    pub layer_marker: &'static str,
36}
37
38pub fn refresh_diagnostics_with_frame(
39    frames: &[DiagnosticFrameFootprintV0],
40    edited_module_ids: Vec<String>,
41) -> FrameAwareRefreshReportV0 {
42    let selective_refresh_enabled = frame_aware_refresh_enabled_from_env();
43    refresh_diagnostics_with_frame_policy(frames, edited_module_ids, selective_refresh_enabled)
44}
45
46pub fn refresh_diagnostics_with_frame_policy(
47    frames: &[DiagnosticFrameFootprintV0],
48    edited_module_ids: Vec<String>,
49    selective_refresh_enabled: bool,
50) -> FrameAwareRefreshReportV0 {
51    let edited_module_count = edited_module_ids.len();
52    let selection = if selective_refresh_enabled {
53        select_frame_aware_recheck_set(frames, edited_module_ids)
54    } else {
55        select_frame_aware_recheck_set(frames, frames_to_module_ids(frames))
56    };
57
58    FrameAwareRefreshReportV0 {
59        schema_version: "0",
60        product: "omena-lsp-server.frame-aware-refresh",
61        feature_gate: "OMENA_LSP_ENABLE_FRAME_AWARE_REFRESH",
62        selective_refresh_enabled,
63        edited_module_count,
64        selected_diagnostic_instance_ids: selection.selected_diagnostic_instance_ids,
65        skipped_diagnostic_instance_ids: selection.skipped_diagnostic_instance_ids,
66        layer_marker: "frame-rule",
67    }
68}
69
70pub fn compare_frame_refresh_against_unconditional_baseline(
71    frames: &[DiagnosticFrameFootprintV0],
72    edited_module_ids: Vec<String>,
73) -> FrameAwareRefreshComparisonV0 {
74    let unconditional =
75        refresh_diagnostics_with_frame_policy(frames, edited_module_ids.clone(), false);
76    let selective = refresh_diagnostics_with_frame_policy(frames, edited_module_ids, true);
77    let unconditional_selected_count = unconditional.selected_diagnostic_instance_ids.len();
78    let selective_selected_count = selective.selected_diagnostic_instance_ids.len();
79    let selected_work_reduction_count =
80        unconditional_selected_count.saturating_sub(selective_selected_count);
81    let selected_work_reduction_ratio = if unconditional_selected_count == 0 {
82        0.0
83    } else {
84        selected_work_reduction_count as f64 / unconditional_selected_count as f64
85    };
86
87    FrameAwareRefreshComparisonV0 {
88        schema_version: "0",
89        product: "omena-lsp-server.frame-aware-refresh-comparison",
90        fixed_workspace_fixture: "m4-alpha-fixed-workspace-frame-refresh",
91        diagnostic_frame_count: frames.len(),
92        edited_module_count: unconditional.edited_module_count,
93        unconditional_selected_count,
94        selective_selected_count,
95        skipped_diagnostic_count: selective.skipped_diagnostic_instance_ids.len(),
96        selected_work_reduction_count,
97        selected_work_reduction_ratio,
98        measured_latency_proxy: "selected-diagnostic-work-count",
99        selective_refresh_enabled_by_default: frame_aware_refresh_enabled(false, false),
100        feature_gate: "OMENA_LSP_ENABLE_FRAME_AWARE_REFRESH",
101        disable_gate: "OMENA_LSP_DISABLE_FRAME_AWARE_REFRESH",
102        layer_marker: "frame-rule",
103    }
104}
105
106fn frames_to_module_ids(frames: &[DiagnosticFrameFootprintV0]) -> Vec<String> {
107    frames
108        .iter()
109        .flat_map(|frame| frame.evidence_module_ids.iter().cloned())
110        .collect()
111}
112
113fn frame_aware_refresh_enabled_from_env() -> bool {
114    frame_aware_refresh_enabled(
115        std::env::var_os("OMENA_LSP_ENABLE_FRAME_AWARE_REFRESH").is_some(),
116        std::env::var_os("OMENA_LSP_DISABLE_FRAME_AWARE_REFRESH").is_some(),
117    )
118}
119
120fn frame_aware_refresh_enabled(enable_requested: bool, disable_requested: bool) -> bool {
121    enable_requested && !disable_requested
122}
123
124#[cfg(test)]
125mod tests {
126    use omena_cascade::derive_frame_for_diagnostic;
127
128    use super::*;
129
130    #[test]
131    fn refresh_report_selects_only_intersecting_frames() {
132        let frame = derive_frame_for_diagnostic(
133            "missing-static-class",
134            "d1",
135            vec!["file:///workspace/a.module.css".to_string()],
136        );
137        let report = refresh_diagnostics_with_frame(
138            &[frame],
139            vec!["file:///workspace/a.module.css".to_string()],
140        );
141
142        assert_eq!(report.schema_version, "0");
143        assert_eq!(report.layer_marker, "frame-rule");
144        assert_eq!(report.feature_gate, "OMENA_LSP_ENABLE_FRAME_AWARE_REFRESH");
145        assert_eq!(report.selected_diagnostic_instance_ids, vec!["d1"]);
146    }
147
148    #[test]
149    fn refresh_report_preserves_full_refresh_when_disabled() {
150        let selected = derive_frame_for_diagnostic(
151            "missing-static-class",
152            "selected",
153            vec!["file:///workspace/a.module.css".to_string()],
154        );
155        let otherwise_skipped = derive_frame_for_diagnostic(
156            "missing-static-class",
157            "otherwise-skipped",
158            vec!["file:///workspace/b.module.css".to_string()],
159        );
160        let report = refresh_diagnostics_with_frame_policy(
161            &[selected, otherwise_skipped],
162            vec!["file:///workspace/a.module.css".to_string()],
163            false,
164        );
165
166        assert!(!report.selective_refresh_enabled);
167        assert_eq!(
168            report.selected_diagnostic_instance_ids,
169            vec!["selected", "otherwise-skipped"]
170        );
171        assert!(report.skipped_diagnostic_instance_ids.is_empty());
172    }
173
174    #[test]
175    fn refresh_policy_is_positive_opt_in() {
176        assert!(!frame_aware_refresh_enabled(false, false));
177        assert!(frame_aware_refresh_enabled(true, false));
178        assert!(!frame_aware_refresh_enabled(true, true));
179        assert!(!frame_aware_refresh_enabled(false, true));
180    }
181
182    #[test]
183    fn fixed_workspace_comparison_reports_work_reduction_when_enabled() {
184        let frames = (0..100)
185            .map(|index| {
186                derive_frame_for_diagnostic(
187                    "missing-static-class",
188                    format!("d{index}"),
189                    vec![format!("file:///workspace/module-{index}.module.css")],
190                )
191            })
192            .collect::<Vec<_>>();
193        let report = compare_frame_refresh_against_unconditional_baseline(
194            &frames,
195            vec!["file:///workspace/module-7.module.css".to_string()],
196        );
197
198        assert_eq!(report.schema_version, "0");
199        assert_eq!(report.layer_marker, "frame-rule");
200        assert_eq!(report.feature_gate, "OMENA_LSP_ENABLE_FRAME_AWARE_REFRESH");
201        assert!(!report.selective_refresh_enabled_by_default);
202        assert_eq!(report.diagnostic_frame_count, 100);
203        assert_eq!(report.unconditional_selected_count, 100);
204        assert_eq!(report.selective_selected_count, 1);
205        assert_eq!(report.skipped_diagnostic_count, 99);
206        assert!(report.selected_work_reduction_ratio >= 0.99);
207    }
208}