Skip to main content

adze_bdd_grid_core/
lib.rs

1//! Core BDD grid contracts used for feature/progress reporting.
2//!
3//! This crate intentionally owns only scenario-grid concerns (what is tracked and how it
4//! is summarized) so governance and parser crates can compose behavior without inheriting
5//! unrelated policy details.
6
7#![forbid(unsafe_op_in_unsafe_fn)]
8#![deny(missing_docs)]
9#![cfg_attr(feature = "strict_api", deny(unreachable_pub))]
10#![cfg_attr(not(feature = "strict_api"), warn(unreachable_pub))]
11#![cfg_attr(feature = "strict_docs", deny(missing_docs))]
12#![cfg_attr(not(feature = "strict_docs"), allow(missing_docs))]
13
14use core::fmt::Write;
15
16pub use adze_bdd_scenario_core::{BddPhase, BddScenario, BddScenarioStatus};
17
18/// GLR conflict-preservation scenario ledger.
19pub const GLR_CONFLICT_PRESERVATION_GRID: &[BddScenario] = &[
20    BddScenario {
21        id: 1,
22        title: "Detect shift/reduce conflicts in ambiguous grammars",
23        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
24        core_status: BddScenarioStatus::Implemented,
25        runtime_status: BddScenarioStatus::Implemented,
26    },
27    BddScenario {
28        id: 2,
29        title: "Preserve conflicts with precedence ordering (PreferShift)",
30        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
31        core_status: BddScenarioStatus::Implemented,
32        runtime_status: BddScenarioStatus::Implemented,
33    },
34    BddScenario {
35        id: 3,
36        title: "Preserve conflicts with precedence ordering (PreferReduce)",
37        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
38        core_status: BddScenarioStatus::Implemented,
39        runtime_status: BddScenarioStatus::Implemented,
40    },
41    BddScenario {
42        id: 4,
43        title: "Use Fork for No Precedence Information",
44        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
45        core_status: BddScenarioStatus::Implemented,
46        runtime_status: BddScenarioStatus::Implemented,
47    },
48    BddScenario {
49        id: 5,
50        title: "Use Fork for Non-Associative Conflicts",
51        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
52        core_status: BddScenarioStatus::Implemented,
53        runtime_status: BddScenarioStatus::Implemented,
54    },
55    BddScenario {
56        id: 6,
57        title: "Generate multi-action cells in parse tables",
58        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
59        core_status: BddScenarioStatus::Implemented,
60        runtime_status: BddScenarioStatus::Implemented,
61    },
62    BddScenario {
63        id: 7,
64        title: "GLR runtime explores both paths",
65        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
66        core_status: BddScenarioStatus::Deferred {
67            reason: "runtime2 integration pending",
68        },
69        runtime_status: BddScenarioStatus::Implemented,
70    },
71    BddScenario {
72        id: 8,
73        title: "Precedence ordering affects tree selection",
74        reference: "docs/archive/plans/BDD_GLR_CONFLICT_PRESERVATION.md",
75        core_status: BddScenarioStatus::Deferred {
76            reason: "runtime2 integration pending",
77        },
78        runtime_status: BddScenarioStatus::Implemented,
79    },
80];
81
82/// Aggregate progress for a phase.
83///
84/// # Examples
85///
86/// ```
87/// use adze_bdd_grid_core::*;
88///
89/// let scenarios = [BddScenario {
90///     id: 1,
91///     title: "example",
92///     reference: "REF-1",
93///     core_status: BddScenarioStatus::Implemented,
94///     runtime_status: BddScenarioStatus::Deferred { reason: "todo" },
95/// }];
96/// let (done, total) = bdd_progress(BddPhase::Core, &scenarios);
97/// assert_eq!(done, 1);
98/// assert_eq!(total, 1);
99/// ```
100pub fn bdd_progress(phase: BddPhase, scenarios: &[BddScenario]) -> (usize, usize) {
101    let mut implemented = 0usize;
102    for scenario in scenarios {
103        if scenario.status(phase).implemented() {
104            implemented += 1;
105        }
106    }
107    (implemented, scenarios.len())
108}
109
110/// Shared formatting for BDD progress summaries.
111///
112/// # Examples
113///
114/// ```
115/// use adze_bdd_grid_core::*;
116///
117/// let report = bdd_progress_report(
118///     BddPhase::Runtime,
119///     GLR_CONFLICT_PRESERVATION_GRID,
120///     "Runtime",
121/// );
122/// assert!(report.contains("Runtime"));
123/// assert!(report.contains("Scenario 1"));
124/// ```
125pub fn bdd_progress_report(
126    phase: BddPhase,
127    scenarios: &[BddScenario],
128    phase_title: &str,
129) -> String {
130    let mut out = String::new();
131
132    let (implemented, total) = bdd_progress(phase, scenarios);
133    out.push_str("\n=== BDD GLR Conflict Preservation Test Summary ===\n");
134    out.push_str(phase_title);
135    out.push('\n');
136    out.push('\n');
137
138    for scenario in scenarios {
139        let status = scenario.status(phase);
140        let _ = write!(
141            out,
142            "{} Scenario {}: {} - {}",
143            status.icon(),
144            scenario.id,
145            scenario.title,
146            status.label()
147        );
148        let detail = status.detail();
149        if !detail.is_empty() {
150            out.push_str(" (");
151            out.push_str(detail);
152            out.push(')');
153        }
154        out.push('\n');
155    }
156
157    out.push('\n');
158    let _ = write!(
159        out,
160        "{}: {}/{} scenarios complete",
161        phase_title, implemented, total
162    );
163    if implemented < total {
164        out.push_str("\nNext: Implement remaining deferred scenarios.");
165    }
166
167    out
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173
174    #[test]
175    fn grid_has_expected_item_count() {
176        assert_eq!(GLR_CONFLICT_PRESERVATION_GRID.len(), 8);
177    }
178
179    #[test]
180    fn progress_summary_reports_counts() {
181        let (implemented, total) = bdd_progress(BddPhase::Core, GLR_CONFLICT_PRESERVATION_GRID);
182        assert_eq!(implemented, 6);
183        assert_eq!(total, 8);
184    }
185
186    #[test]
187    fn progress_report_text_includes_title() {
188        let report =
189            bdd_progress_report(BddPhase::Runtime, GLR_CONFLICT_PRESERVATION_GRID, "Runtime");
190        assert!(report.contains("Runtime"));
191        assert!(report.contains("Scenario 1"));
192    }
193}