1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! The core `BrailleRule` trait — the plugin interface.
//!
//! Every rule implements this trait. The `RuleEngine` calls `matches()` then `apply()`
//! for each registered rule in priority order.
use RuleMeta;
use RuleContext;
/// Result of applying a rule.
/// Execution phase — rules run in phase order, then by priority within a phase.
/// The plugin interface for braille rules.
///
/// Each rule is a self-contained unit:
/// - Has stable metadata (name, standard reference)
/// - Can inspect the current context (character, state, position)
/// - Can produce output and mutate state
/// - Is independently testable
///
/// # Example
/// ```ignore
/// struct Rule11VowelYe;
///
/// impl BrailleRule for Rule11VowelYe {
/// fn meta(&self) -> &'static RuleMeta { &META }
/// fn phase(&self) -> Phase { Phase::InterCharacter }
/// fn matches(&self, ctx: &RuleContext) -> bool { /* check conditions */ }
/// fn apply(&self, ctx: &mut RuleContext) -> Result<RuleResult, String> {
/// ctx.emit(36); // ⠤ separator
/// Ok(RuleResult::Continue)
/// }
/// }
/// ```