caixa_theme/style.rs
1//! The small semantic-style enum every caixa tool agrees on.
2
3use serde::{Deserialize, Serialize};
4
5#[derive(
6 Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, gen_platform::IsVariant,
7)]
8pub enum Semantic {
9 /// Language keywords — `defcaixa`, `defteia`, `let`, `lambda`, etc.
10 Keyword,
11 /// Non-keyword symbols — identifiers, function names, variant names.
12 Symbol,
13 /// `:keyword-positioned` atoms.
14 KeywordArg,
15 /// `"string literals"`.
16 String,
17 /// `42`, `3.14`.
18 Number,
19 /// `#t`, `#f`, `nil`.
20 Literal,
21 /// `; comments`.
22 Comment,
23 /// Primary accent — useful for highlights, carets, focused tokens.
24 Accent,
25 /// Dim text — metadata, line numbers, help text.
26 Muted,
27
28 // Diagnostic severities.
29 Error,
30 Warning,
31 Info,
32 Hint,
33
34 // Diff decorations — used by formatter preview and lint output.
35 Added,
36 Removed,
37 Unchanged,
38}
39
40impl Semantic {
41 /// Every variant of [`Semantic`] in declaration order.
42 ///
43 /// The single canonical arm-list every substrate consumer that has
44 /// to walk the closed 15-arm semantic-style partition (the two
45 /// theme overlays' exhaustive-match resolver functions
46 /// `blackmatter_dark_color` / `blackmatter_light_color` in
47 /// [`crate::blackmatter`], the future LSP-side per-Semantic
48 /// `SemanticTokenType` dispatch at
49 /// `caixa-lsp/src/main.rs`, a future
50 /// `feira lint --list-styles` operator-facing enumeration verb)
51 /// reads for. Peer of the sibling closed-set fieldless typed
52 /// enums' `ALL` slices already carried by
53 /// [`caixa_core::CaixaKind`] /
54 /// [`caixa_core::supervisor::RestartStrategy`] /
55 /// [`caixa_core::supervisor::RestartPolicy`] /
56 /// [`caixa_core::aplicacao::PlacementStrategy`] /
57 /// [`caixa_core::upgrade::UpgradeInstruction`] /
58 /// `caixa_lint::diagnostic::Severity` /
59 /// `caixa_lint::diagnostic::FixSafety` /
60 /// `caixa_arch::InvariantKind` / `caixa_arch::ArchVerdict` /
61 /// `caixa_provedor::FerriteRuntime` closed-set typed-enum
62 /// discriminator axes.
63 pub const ALL: &'static [Self] = &[
64 Self::Keyword,
65 Self::Symbol,
66 Self::KeywordArg,
67 Self::String,
68 Self::Number,
69 Self::Literal,
70 Self::Comment,
71 Self::Accent,
72 Self::Muted,
73 Self::Error,
74 Self::Warning,
75 Self::Info,
76 Self::Hint,
77 Self::Added,
78 Self::Removed,
79 Self::Unchanged,
80 ];
81
82 /// Canonical kebab-case discriminator scalar for this variant — the
83 /// single substrate-primitive `&'static str` projection every
84 /// downstream consumer of the closed 16-arm [`Semantic`] partition
85 /// (a future LSP-side per-Semantic `SemanticTokenType` name-mapping
86 /// dispatch at `caixa-lsp/src/main.rs`, a future
87 /// `feira lint --list-styles` operator-facing enumeration verb, a
88 /// future `caixa.nvim` per-Semantic highlight-group name resolver
89 /// that reaches for a stable kebab identifier per arm, a future
90 /// `blackmatter-shell` per-arm classname the terminal emitter
91 /// composes into a `data-semantic="<kebab>"` attribute) reaches
92 /// through. Kebab-case matches the peer
93 /// [`gen_platform::IsVariant`]-derived kebab discriminant convention
94 /// the sibling closed-set typed enums
95 /// ([`caixa_core::CaixaKind::as_str`],
96 /// [`caixa_core::supervisor::RestartStrategy::as_str`],
97 /// [`caixa_core::supervisor::RestartPolicy::as_str`],
98 /// [`caixa_core::aplicacao::PlacementStrategy::as_str`],
99 /// [`caixa_core::upgrade::UpgradeInstruction::as_str`],
100 /// `caixa_lint::diagnostic::Severity::as_str`,
101 /// `caixa_lint::diagnostic::FixSafety::as_str`,
102 /// `caixa_arch::InvariantKind::as_str`,
103 /// `caixa_arch::ArchVerdict::as_str`,
104 /// `caixa_provedor::FerriteRuntime::variant_slug`) already emit
105 /// on their canonical `&'static str` projection axis.
106 ///
107 /// The 16 arms return the kebab-case forms of their `PascalCase`
108 /// variant names (`Keyword` → `"keyword"`, `KeywordArg` →
109 /// `"keyword-arg"`, `Unchanged` → `"unchanged"`, etc.), matching
110 /// the peer closed-set typed-enum canonical byte-string conventions.
111 ///
112 /// Peer of the [`std::fmt::Display`] and [`AsRef<str>`] impls on
113 /// this enum, which both route through this accessor so
114 /// `format!("{s}")`, `s.as_str()`, and
115 /// `<Semantic as AsRef<str>>::as_ref(&s)` resolve to the same
116 /// per-arm byte-string.
117 #[must_use]
118 pub const fn as_str(self) -> &'static str {
119 match self {
120 Self::Keyword => "keyword",
121 Self::Symbol => "symbol",
122 Self::KeywordArg => "keyword-arg",
123 Self::String => "string",
124 Self::Number => "number",
125 Self::Literal => "literal",
126 Self::Comment => "comment",
127 Self::Accent => "accent",
128 Self::Muted => "muted",
129 Self::Error => "error",
130 Self::Warning => "warning",
131 Self::Info => "info",
132 Self::Hint => "hint",
133 Self::Added => "added",
134 Self::Removed => "removed",
135 Self::Unchanged => "unchanged",
136 }
137 }
138
139 /// Reverse projection on the [`Semantic`] closed 16-arm enum's
140 /// canonical kebab-tag axis — parses a `"keyword"` / `"symbol"` /
141 /// `"keyword-arg"` / `"string"` / `"number"` / `"literal"` /
142 /// `"comment"` / `"accent"` / `"muted"` / `"error"` / `"warning"` /
143 /// `"info"` / `"hint"` / `"added"` / `"removed"` / `"unchanged"` wire
144 /// byte-string back to the typed enum, or returns `None` when `s`
145 /// lies outside the 16-arm accept-set [`Self::as_str`] emits. The
146 /// single `&str → Self` projection every future re-entry point on
147 /// the caixa-theme semantic-style axis dispatches through (a future
148 /// `feira lint --list-styles` operator-facing enumeration verb
149 /// hydrating a per-arm row from a stored kebab identifier back to
150 /// the typed enum before rendering, a future `caixa-lsp`-side
151 /// per-`SemanticTokenType` re-parse binding a prior
152 /// [`Self::as_str`] output back to the typed enum for
153 /// per-Semantic-highlight dispatch, a future `caixa.nvim` per-
154 /// Semantic highlight-group resolver re-loading a stored kebab
155 /// identifier back to the typed enum, a future `blackmatter-shell`
156 /// per-arm classname reverse-lookup binding a
157 /// `data-semantic="<kebab>"` DOM attribute back to the typed enum
158 /// for per-arm style dispatch, a `tracing::field::Value::Str`-arm
159 /// structured-log re-loader binding a prior emission's
160 /// [`Self::as_str`] output back to the typed enum for cross-run
161 /// per-Semantic-paint-histogram diff) would have had to re-inline a
162 /// 16-arm `match s` cascade that expressed no compile-time link back
163 /// to the substrate primitive.
164 ///
165 /// Same closed-set-reverse-projection discipline the sibling
166 /// [`caixa_core::CaixaKind::from_wire`] (2aa6d23),
167 /// [`caixa_core::CaixaDialeto::from_wire`] (d0e65ea),
168 /// [`caixa_core::supervisor::RestartStrategy::from_wire`] (4eec29c),
169 /// [`caixa_core::supervisor::RestartPolicy::from_wire`] (dd32ccf),
170 /// [`caixa_core::aplicacao::PlacementStrategy::from_wire`] (18c7342),
171 /// [`caixa_core::dep::DepList::from_wire`] (45ee563),
172 /// [`caixa_core::render::PathShapeViolation::from_wire`] (aebd9c6),
173 /// `caixa_arch::invariants::InvariantKind::from_wire` (b9e4e61),
174 /// `caixa_arch::report::ArchVerdict::from_wire` (6afe564),
175 /// `caixa_lint::diagnostic::Severity::from_wire` (5afff0e), and
176 /// `caixa_lint::diagnostic::FixSafety::from_wire` (bd505a1) typed
177 /// enums carry on the peer wire-side `str → Self` axes — extends
178 /// the substrate-wide `(as_str, from_wire)` round-trip family onto
179 /// the caixa-theme closed-set fieldless typed-enum axis (the first
180 /// closed-set fieldless typed enum on `caixa-theme` to converge on
181 /// the reverse-projection discipline), matching the same two-way
182 /// `str ↔ Self` round-trip every sibling closed-set enum already
183 /// carries. Method-named `from_wire` (not `from_str`) to match the
184 /// peer shapes verbatim and side-step a
185 /// `clippy::should_implement_trait` lint that a plain `from_str`
186 /// name would otherwise trigger without paired
187 /// [`std::str::FromStr`] impl scaffolding this axis does not carry
188 /// today. Returns `Option<Self>` (rather than `Result<Self, _>`) to
189 /// match the peer shapes: the caller picks the diagnostic form
190 /// appropriate for its use site (a `feira lint --list-styles` CLI
191 /// arg-parse renders its own per-verb error message; a future
192 /// admission-webhook rejection body wraps the `None` outcome with
193 /// the accepted-set enumeration `Semantic::ALL.iter().map(…)` for
194 /// operator diagnostics).
195 ///
196 /// Pinned load-bearing at the substrate-primitive level by
197 /// [`tests::semantic_from_wire_accepts_every_as_str_output`]
198 /// (round-trip witness against the peer [`Self::as_str`] axis) and
199 /// [`tests::semantic_from_wire_rejects_unknown_byte_strings`]
200 /// (rejection witness against silent accept-set widening).
201 #[must_use]
202 pub fn from_wire(s: &str) -> Option<Self> {
203 match s {
204 "keyword" => Some(Self::Keyword),
205 "symbol" => Some(Self::Symbol),
206 "keyword-arg" => Some(Self::KeywordArg),
207 "string" => Some(Self::String),
208 "number" => Some(Self::Number),
209 "literal" => Some(Self::Literal),
210 "comment" => Some(Self::Comment),
211 "accent" => Some(Self::Accent),
212 "muted" => Some(Self::Muted),
213 "error" => Some(Self::Error),
214 "warning" => Some(Self::Warning),
215 "info" => Some(Self::Info),
216 "hint" => Some(Self::Hint),
217 "added" => Some(Self::Added),
218 "removed" => Some(Self::Removed),
219 "unchanged" => Some(Self::Unchanged),
220 _ => None,
221 }
222 }
223}
224
225/// [`std::fmt::Display`] routed through [`Semantic::as_str`], so the
226/// pretty-printed byte-string every consumer that formats the semantic
227/// style as user-facing text lands on (a future `feira lint --list-styles`
228/// operator-facing enumeration verb's per-arm line, a future
229/// `caixa-lsp` diagnostic-source line naming the offending semantic,
230/// a future `caixa.nvim` per-Semantic highlight-group name emitter,
231/// a `tracing::field::display(&sem)` structured-log recorder on the
232/// paint-side emit path) reaches for the same lifted kebab-case
233/// per-arm byte-string [`Semantic::as_str`] returns.
234///
235/// Peer of the sibling [`std::fmt::Display`] impls on the closed-set
236/// typed enums the substrate carries — [`caixa_core::CaixaKind`],
237/// [`caixa_core::supervisor::RestartStrategy`],
238/// [`caixa_core::supervisor::RestartPolicy`],
239/// [`caixa_core::aplicacao::PlacementStrategy`],
240/// [`caixa_core::upgrade::UpgradeInstruction`],
241/// `caixa_lint::diagnostic::Severity`,
242/// `caixa_lint::diagnostic::FixSafety`,
243/// `caixa_arch::InvariantKind`, `caixa_arch::ArchVerdict`,
244/// `caixa_provedor::FerriteRuntime` — extended to the second-to-last
245/// un-lifted `caixa-theme` closed-set fieldless typed enum on the
246/// substrate-wide `(as_str, AsRef<str>, Display)` canonical-projection
247/// triple ratchet the prior lifts converged onto.
248impl std::fmt::Display for Semantic {
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 f.write_str(self.as_str())
251 }
252}
253
254/// Substrate-canonical [`AsRef<str>`] projection on the caixa-theme
255/// [`Semantic`] closed-set fieldless typed enum — routes through the
256/// same [`Semantic::as_str`] `pub const fn` scalar accessor the paired
257/// [`std::fmt::Display`] impl already reaches for.
258///
259/// Peer of the sibling [`AsRef<str>`] impls the substrate carries on
260/// [`caixa_core::CaixaKind`], [`caixa_core::CaixaVersion`],
261/// [`caixa_core::CaixaDialeto`], [`caixa_core::dep::DepList`],
262/// [`caixa_core::supervisor::RestartStrategy`],
263/// [`caixa_core::supervisor::RestartPolicy`],
264/// [`caixa_core::aplicacao::PlacementStrategy`],
265/// [`caixa_core::aplicacao::RateLimitUnit`],
266/// `caixa_lint::diagnostic::Severity`,
267/// `caixa_arch::InvariantKind`, `caixa_arch::ArchVerdict`,
268/// `caixa_provedor::FerriteRuntime` — extends the substrate-wide
269/// `(as_str, AsRef<str>, Display)` canonical-projection triple onto
270/// the caixa-theme closed-set typed-enum axis, so a future consumer
271/// bound through the trait-idiomatic `.as_ref()` (a
272/// `HashMap::get::<str>(sem.as_ref())` per-Semantic style-lookup, a
273/// future `caixa-lsp` `SemanticTokenType::new(sem.as_ref())`
274/// registration site, any `impl AsRef<str>`-bound generic function)
275/// reaches the same kebab byte-string [`Semantic::as_str`] returns
276/// rather than an open-coded `.as_str()` projection at every
277/// wire-up.
278impl AsRef<str> for Semantic {
279 fn as_ref(&self) -> &str {
280 self.as_str()
281 }
282}
283
284/// Trait-idiomatic reverse projection on the [`Semantic`] closed 16-arm
285/// caixa-theme semantic-style axis — routes byte-for-byte through the
286/// paired substrate-primitive [`Semantic::from_wire`] `Option<Self>`
287/// accessor so every future consumer that binds a canonical semantic
288/// tag through the standard-library `.try_into()` / [`TryFrom`] axis
289/// (a future `feira lint --semantic=<kebab>` CLI arg-parse that
290/// composes into `let sem: Semantic = s.try_into()?`, a future
291/// `caixa-lsp` per-token re-parse hydrating a prior
292/// [`Semantic::as_str`] output back to the typed enum for
293/// `SemanticTokenType` dispatch, a future `caixa.nvim` per-highlight-
294/// group re-loader binding a stored kebab byte-string back through the
295/// typed enum, a generic `<T: TryFrom<&str>>`-bound theme-overlay
296/// re-loader over any of the substrate's closed-set typed enums)
297/// reaches the same 16-arm accept-set the sibling
298/// [`Semantic::from_wire`] resolver parses through and the sibling
299/// [`Semantic::as_str`] emits, rather than an open-coded per-arm
300/// `match s { "keyword" => …, "symbol" => …, … _ => … }` cascade whose
301/// arm-set has no compile-time link back to the substrate primitive.
302///
303/// Complements the pre-existing forward-projection triple
304/// ([`std::fmt::Display`], [`AsRef<str>`], [`Semantic::as_str`]) with
305/// the paired trait-idiomatic reverse-projection axis: Rust-side
306/// newtype/typed-enum convention pairs [`AsRef<str>`] with either
307/// [`std::str::FromStr`] or [`TryFrom<&str>`] on the same primitive so
308/// a caller who can project *out to* a `&str` can also project *in
309/// from* one. The [`TryFrom<&str>`] axis is deliberately chosen over
310/// [`std::str::FromStr`] to sidestep the `clippy::should_implement_trait`
311/// lint the sibling method-named [`Semantic::from_wire`] would trigger
312/// under a `FromStr` impl (the same design tradeoff the peer
313/// [`caixa_core::CaixaKind`] (3c83606),
314/// [`caixa_core::CaixaDialeto`] (bf33136),
315/// [`caixa_core::aplicacao::PlacementStrategy`] (6fd00cd),
316/// [`caixa_core::supervisor::RestartStrategy`] (5b828ed),
317/// [`caixa_core::supervisor::RestartPolicy`] (6fdd0d9),
318/// [`caixa_core::aplicacao::WitShape`] (5472902),
319/// [`caixa_core::aplicacao::RateLimitUnit`] (bf78400),
320/// [`caixa_core::render::PathShapeViolation`] (e67e48a),
321/// `caixa_arch::invariants::InvariantKind` (e21a857),
322/// `caixa_arch::report::ArchVerdict` (0a4cc45),
323/// `caixa_lint::diagnostic::Severity` (a7bf74c), and
324/// `caixa_lint::diagnostic::FixSafety` (df86c94) blocks note) — this
325/// impl closes the trait-idiomatic reverse axis without disturbing the
326/// method-named `from_wire` shape every peer closed-set typed enum
327/// already carries.
328///
329/// `type Error = ()` matches the sibling [`Semantic::from_wire`]'s
330/// `Option<Self>` return-shape's deliberate deferral of error typing:
331/// the caller picks the diagnostic form appropriate for its use site
332/// (a future `feira lint --semantic` CLI arg-parse composes its own
333/// per-verb "unknown semantic-style tag: <arg> — accepted: {…}"
334/// message enumerating [`Semantic::ALL`], a future admission-webhook
335/// rejection body wraps the `Err(())` outcome with the accepted-set
336/// enumeration for operator diagnostics, a `Result::map_err` at the
337/// call site lifts the axis-error to a per-verb error type). Same
338/// shape the peer sibling reverse-projection axes carry. The return-
339/// shape uses fully-qualified `<Self as TryFrom<&str>>::Error` because
340/// the associated-type name would otherwise collide with the
341/// [`Self::Error`] variant on the same primitive (the identical
342/// ambiguous-associated-item defect the sibling
343/// `impl TryFrom<&str> for Severity` (a7bf74c) already threads around
344/// under `#[deny(future_incompatible)]`).
345///
346/// The paired [`TryFrom<&str>`] impl reaches the same 16-arm accept-
347/// set the [`Semantic::from_wire`] resolver dispatches through, so any
348/// future arm addition (a `Namespace` tier between [`Self::Symbol`]
349/// and [`Self::KeywordArg`] for the M4 tatara-lisp module system's
350/// qualified-name semantic-token dispatch, a `Deleted` tier for a
351/// hard-delete-mark distinct from [`Self::Removed`] the future 3-way
352/// diff surface grows — both trajectory items the sibling
353/// [`Semantic::ALL`] doc block already names) grows the trait-
354/// idiomatic axis by construction: one caixa-theme edit on
355/// [`Semantic::from_wire`] extends both the method-named reverse
356/// projection every existing consumer keys off and the trait-
357/// idiomatic reverse projection this impl exposes, without a
358/// coordinated rewrite across every future `TryFrom<&str>`-bound
359/// consumer's arm-set.
360///
361/// Extends the substrate-wide closed-set-enum trait-idiomatic
362/// reverse-projection family ([`caixa_core::CaixaKind`] via 3c83606,
363/// [`caixa_core::CaixaDialeto`] via bf33136,
364/// [`caixa_core::aplicacao::PlacementStrategy`] via 6fd00cd,
365/// [`caixa_core::supervisor::RestartStrategy`] via 5b828ed,
366/// [`caixa_core::supervisor::RestartPolicy`] via 6fdd0d9,
367/// [`caixa_core::aplicacao::WitShape`] via 5472902,
368/// [`caixa_core::aplicacao::RateLimitUnit`] via bf78400,
369/// [`caixa_core::render::PathShapeViolation`] via e67e48a,
370/// `caixa_arch::invariants::InvariantKind` via e21a857,
371/// `caixa_arch::report::ArchVerdict` via 0a4cc45,
372/// `caixa_lint::diagnostic::Severity` via a7bf74c, and
373/// `caixa_lint::diagnostic::FixSafety` via df86c94) onto the first
374/// closed-set fieldless typed enum on the caixa-theme surface — the
375/// semantic-style 16-arm accept-set every per-Semantic paint dispatch,
376/// every future `caixa-lsp` per-SemanticTokenType wire-up, and every
377/// future `caixa.nvim` per-highlight-group re-loader keys off. The
378/// thirteenth peer on the substrate surface, and the first inside
379/// `caixa-theme`; with `caixa_provedor::FerriteRuntime` remaining as
380/// the only outside-caixa-core closed-set fieldless typed enum whose
381/// trait-idiomatic axis is still open.
382///
383/// Pinned load-bearing by
384/// [`tests::semantic_try_from_str_routes_through_from_wire_accessor`]
385/// (byte-parity pin against [`Semantic::from_wire`] across the 16-arm
386/// accept-set) and
387/// [`tests::semantic_try_from_str_rejects_unknown_byte_strings`]
388/// (rejection witness against silent accept-set widening).
389impl TryFrom<&str> for Semantic {
390 type Error = ();
391
392 fn try_from(s: &str) -> Result<Self, <Self as TryFrom<&str>>::Error> {
393 Self::from_wire(s).ok_or(())
394 }
395}
396
397/// Standard-library trait-idiomatic forward projection on the
398/// [`Semantic`] closed 16-arm caixa-theme semantic-style axis. Routes
399/// byte-for-byte through the paired substrate-primitive
400/// [`Semantic::as_str`] `pub const fn` accessor so
401/// `<&'static str>::from(sem)` / `sem.into::<&'static str>()` reaches
402/// the same 16-arm canonical-lowercase kebab emit-set the sibling
403/// method-named accessor dispatches through and the sibling
404/// [`std::fmt::Display for Semantic`] / [`AsRef<str> for Semantic`]
405/// impls also route through.
406///
407/// Extends the substrate-wide closed-set-enum trait-idiomatic
408/// forward-projection family
409/// ([`caixa_core::supervisor::RestartStrategy`] via 523157d,
410/// [`caixa_core::supervisor::RestartPolicy`] via 9fb37d0,
411/// [`caixa_core::CaixaKind`] via edb827b,
412/// [`caixa_core::CaixaDialeto`] via c189a6f,
413/// [`caixa_core::aplicacao::PlacementStrategy`] via afa3562,
414/// [`caixa_core::aplicacao::WitShape`] via 56998ec,
415/// [`caixa_core::aplicacao::RateLimitUnit`] via 7fdfbf4,
416/// [`caixa_core::render::PathShapeViolation`] via 070a6de,
417/// [`caixa_arch::invariants::InvariantKind`] via f2ca7bc,
418/// [`caixa_arch::report::ArchVerdict`] via d4559cb,
419/// `caixa_lint::diagnostic::Severity` via 5cc3b8b, and
420/// `caixa_lint::diagnostic::FixSafety` via 2a56127) onto the first
421/// closed-set fieldless typed enum on the caixa-theme surface — the
422/// semantic-style 16-arm accept-set every per-Semantic paint dispatch,
423/// every future `caixa-lsp` per-`SemanticTokenType` wire-up, every
424/// future `caixa.nvim` per-highlight-group re-loader, and every future
425/// `blackmatter-shell` per-arm `data-semantic="<kebab>"` DOM emission
426/// keys off. The thirteenth peer on the substrate surface, closing the
427/// caixa-theme closed-set fieldless typed-enum axis onto the trait-
428/// idiomatic forward-projection axis and matching the paired trait-
429/// idiomatic reverse-projection axis (already closed via bd7da69 on
430/// this enum), with only `caixa_provedor::FerriteRuntime` remaining as
431/// the last outside-caixa-core closed-set fieldless typed enum whose
432/// trait-idiomatic forward axis is still open.
433///
434/// Pairs with the sibling [`TryFrom<&str> for Semantic`] impl (bd7da69)
435/// to close the two-way `Self ↔ &'static str` round-trip on the
436/// trait-idiomatic axis pair, mirroring the pre-existing method-named
437/// [`Semantic::as_str`] + [`Semantic::from_wire`] pair on the
438/// substrate-primitive axis pair.
439///
440/// Return type is `&'static str` by construction — every
441/// [`Semantic::as_str`] arm resolves to an inline `"keyword"` /
442/// `"symbol"` / `"keyword-arg"` / `"string"` / `"number"` /
443/// `"literal"` / `"comment"` / `"accent"` / `"muted"` / `"error"` /
444/// `"warning"` / `"info"` / `"hint"` / `"added"` / `"removed"` /
445/// `"unchanged"` `&'static str` literal, so the trait's return-type
446/// promise is upheld structurally without a [`String::leak`] cast or a
447/// per-arm inline literal outside the paired [`Semantic::as_str`]
448/// dispatch.
449///
450/// The paired [`Semantic::as_str`] accessor's 16-arm emit-set is the
451/// single source of truth — every future arm addition (a `Namespace`
452/// tier between [`Self::Symbol`] and [`Self::KeywordArg`] for the M4
453/// tatara-lisp module system's qualified-name semantic-token dispatch,
454/// a `Deleted` tier for a hard-delete-mark distinct from
455/// [`Self::Removed`] the future 3-way diff surface grows — both
456/// trajectory items the sibling [`Semantic::ALL`] doc block already
457/// names) grows the trait-idiomatic forward axis by construction: one
458/// caixa-theme edit on [`Semantic::as_str`] extends every one of the
459/// sibling forward-projection paths ([`std::fmt::Display`],
460/// [`AsRef<str>`], [`Semantic::as_str`] itself, and this
461/// [`From<Self> for &'static str`]) without a coordinated rewrite
462/// across every future `Into<&'static str>`-bound consumer's arm-set.
463///
464/// Pinned load-bearing by
465/// [`tests::semantic_from_into_static_str_routes_through_as_str_accessor`]
466/// (byte-parity pin against [`Semantic::as_str`] across the 16-arm
467/// emit-set, plus a `const`-context materialization witness for the
468/// `&'static str` lifetime promise routed through the paired
469/// [`Semantic::as_str`] `pub const fn` accessor, plus a paired
470/// `.into()` shape assertion covering the blanket-derived
471/// `Into<&'static str>` shape) and
472/// [`tests::semantic_from_into_static_str_and_as_str_partition_the_emit_set`]
473/// (partition pin asserting `<&'static str as From<Semantic>>::from`
474/// and [`Semantic::as_str`] agree on every arm, plus a two-way direct
475/// round-trip witness through the paired trait-idiomatic
476/// [`TryFrom<&str>`] axis that closes the two-way
477/// `Self ↔ &'static str` round-trip on the trait-idiomatic axis pair
478/// — the emit-side [`Semantic::as_str`] and the parse-side
479/// [`Semantic::from_wire`] dispatch on the same 16 inline canonical-
480/// lowercase kebab byte-strings by construction, so round-tripping
481/// composes the two trait impls directly).
482impl From<Semantic> for &'static str {
483 fn from(sem: Semantic) -> &'static str {
484 sem.as_str()
485 }
486}
487
488/// Trait-idiomatic *borrowed-input* forward projection on the
489/// [`Semantic`] closed 16-arm caixa-theme semantic-style axis onto the
490/// `&'static str` axis — the borrowed-input companion to the paired
491/// owned-input [`From<Semantic> for &'static str`] impl immediately
492/// above. Routes byte-for-byte through the same substrate-primitive
493/// [`Semantic::as_str`] `pub const fn` accessor so every consumer that
494/// binds a `&Semantic` through the standard-library `.into()` /
495/// [`From<&Self> for &'static str`] axis (a
496/// `Semantic::ALL.iter().map(<&'static str>::from).collect::<Vec<_>>()`
497/// per-arm accept-set materializer — whose iterator over
498/// `&'static [Semantic]` yields `&Semantic`, not `Semantic`, so the
499/// owned-input [`From<Semantic>`] axis alone forces every call site
500/// through an explicit `.copied()` / dereference / [`Copy`]-bound
501/// restatement rather than the direct trait-idiomatic projection; a
502/// future `feira lint --list-styles` operator-facing enumeration verb
503/// composed via `Semantic::ALL.iter().map(Into::into)`; a future
504/// `caixa-lsp` per-`SemanticTokenType` registration walk that borrows
505/// `&Semantic` off a stored per-style row; a future `caixa.nvim` per-
506/// highlight-group re-loader that borrows `&Semantic` off the loaded
507/// theme-overlay table; a future
508/// `HashMap::<&'static str, _>::from_iter(Semantic::ALL.iter().map(
509/// |sem| (<&'static str>::from(sem), 0)))` per-Semantic-paint
510/// histogram seed a future `blackmatter-shell` per-arm
511/// `data-semantic="<kebab>"` DOM-attribute emit path composes) reaches
512/// the same 16-arm `"keyword"` / `"symbol"` / `"keyword-arg"` /
513/// `"string"` / `"number"` / `"literal"` / `"comment"` / `"accent"` /
514/// `"muted"` / `"error"` / `"warning"` / `"info"` / `"hint"` /
515/// `"added"` / `"removed"` / `"unchanged"` canonical-lowercase kebab
516/// emit-set the paired owned-input [`From<Semantic> for &'static str`],
517/// the sibling [`std::fmt::Display`], [`AsRef<str>`], and
518/// [`Semantic::as_str`] surfaces already return.
519///
520/// Fifteenth and final peer on the substrate-wide trait-idiomatic
521/// *borrowed-input* `&'static str`-returning forward-projection family
522/// already carried by [`caixa_core::dep::DepList`] (64aa742,
523/// first-mover), [`caixa_core::CaixaKind`],
524/// [`caixa_core::CaixaDialeto`],
525/// [`caixa_core::supervisor::RestartStrategy`],
526/// [`caixa_core::supervisor::RestartPolicy`],
527/// [`caixa_core::aplicacao::PlacementStrategy`],
528/// [`caixa_core::aplicacao::WitShape`],
529/// [`caixa_core::aplicacao::RateLimitUnit`],
530/// [`caixa_core::render::PathShapeViolation`] (cdf4e95, first render-
531/// side arm), [`caixa_arch::invariants::InvariantKind`] (238d886,
532/// first outside-`caixa-core` arm), [`caixa_arch::report::ArchVerdict`]
533/// (73bda50), `caixa_lint::diagnostic::Severity` (2b9003f),
534/// `caixa_lint::diagnostic::FixSafety` (d8769ab), and
535/// `caixa_provedor::FerriteRuntime` (676d693). Rust's `From` trait does
536/// not auto-derive the `From<&Self>` sibling from a `From<Self>` impl
537/// (the blanket `impl<T, U> From<&T> for U where T: Copy, U: From<T>`
538/// does not exist in `core`), so every closed-set typed enum that
539/// carries the owned-input axis but not the borrowed-input axis forces
540/// every borrowed-input call site through a `.copied()` /
541/// `<&'static str>::from(*sem)` / `sem.as_str()` detour whose type
542/// bounds have no compile-time link to the substrate primitive.
543/// Lifting the borrowed-input axis on the caixa-theme semantic-style
544/// 16-arm closed-set fieldless typed enum closes that gap on the same
545/// trajectory the paired owned-input axis
546/// ([`impl From<Semantic> for &'static str`] immediately above) already
547/// opened, and closes the trait-idiomatic *borrowed-input*
548/// `&'static str`-returning axis on the last remaining substrate-wide
549/// closed-set fieldless typed enum whose borrowed-input axis was still
550/// open — the substrate-wide 2×2-completion campaign now covers every
551/// closed-set fieldless typed enum on the caixa surface on the
552/// borrowed-input `&'static str`-returning axis.
553///
554/// Pinned load-bearing by
555/// [`tests::semantic_from_borrowed_into_static_str_routes_through_as_str_accessor`]
556/// (byte-parity pin against [`Semantic::as_str`] across the 16-arm
557/// emit-set via a borrowed input, plus a `const`-context
558/// materialization witness for the `&'static str` lifetime promise)
559/// and
560/// [`tests::semantic_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
561/// (cross-axis partition pin against the paired owned-input
562/// [`From<Semantic> for &'static str`] impl, plus a
563/// `.iter().map(Into::into)` pipe witness over [`Semantic::ALL`] whose
564/// iterator yields `&Semantic` by construction so this borrowed-input
565/// axis is what routes the pipe through the substrate-primitive
566/// accessor without a spurious `Copy` deref).
567impl From<&Semantic> for &'static str {
568 fn from(sem: &Semantic) -> &'static str {
569 sem.as_str()
570 }
571}
572
573/// Trait-idiomatic *owned-input, owned-`String` output* forward
574/// projection on the [`Semantic`] closed 16-arm caixa-theme
575/// semantic-style axis — the owned-`String` companion to the paired
576/// [`From<Semantic> for &'static str`] and
577/// [`From<&Semantic> for &'static str`] siblings immediately above.
578/// Routes byte-for-byte through the substrate-primitive
579/// [`Semantic::as_str`] `pub const fn` accessor via
580/// [`str::to_owned`] so every consumer that binds a [`Semantic`]
581/// through the standard-library `.into()` / [`From<Self> for String`]
582/// axis (a `let key: String = sem.into();`-shaped downstream call
583/// site; a future `serde_json::Value::String(sem.into())` structured-
584/// payload composer where the `Value::String` arm typing demands an
585/// owned [`String`] and the sibling `&'static str`-returning axes
586/// force an explicit `.to_owned()` / [`String::from`] restatement at
587/// every call site; a future
588/// `HashMap::<String, Semantic>::from_iter` per-semantic lookup on
589/// a future `caixa-lsp` per-`SemanticTokenType` registration path
590/// where the map's key type is owned [`String`] rather than
591/// `&'static str`; a future
592/// [`std::borrow::Cow::<'static, str>::Owned(sem.into())`] composer
593/// on a future `feira lint --list-styles` operator-facing enumeration
594/// verb's per-arm row where an owned [`Cow`] arm typing rules;
595/// a future `caixa.nvim` per-highlight-group re-loader that stores
596/// the per-Semantic kebab identifier as an owned [`String`] on the
597/// theme-overlay table; a future `blackmatter-shell` per-arm
598/// `data-semantic="<kebab>"` DOM emission whose serializer's
599/// [`Serialize`] impl on [`String`] owns the emit-path) reaches the
600/// same 16-arm `"keyword"` / `"symbol"` / `"keyword-arg"` /
601/// `"string"` / `"number"` / `"literal"` / `"comment"` / `"accent"` /
602/// `"muted"` / `"error"` / `"warning"` / `"info"` / `"hint"` /
603/// `"added"` / `"removed"` / `"unchanged"` canonical-lowercase kebab
604/// emit-set the paired `&'static str`-returning axes, the sibling
605/// [`std::fmt::Display`], [`AsRef<str>`], and [`Semantic::as_str`]
606/// surfaces already return — no `.to_owned()` /
607/// `String::from(sem.as_str())` detour whose type bounds have no
608/// compile-time link to the substrate primitive.
609///
610/// Rust's standard library does not carry a blanket
611/// `impl<T: AsRef<str>> From<T> for String` (nor an
612/// `impl<T: fmt::Display> From<T> for String`), so every closed-set
613/// typed enum that carries the paired [`AsRef<str>`] /
614/// [`std::fmt::Display`] / [`From<Self> for &'static str`] /
615/// [`From<&Self> for &'static str`] quadruple but not the owned-
616/// `String` axis forces every owned-string call site through the
617/// detour above. This lift closes that axis on the sole closed-set
618/// fieldless typed enum on the caixa-theme surface (the semantic-
619/// style 16-arm axis), extending the substrate-wide
620/// `{Self, &Self} × {&'static str, String}` 2×2-completion campaign
621/// onto the sixth outside-`caixa-core` closed-set fieldless typed
622/// enum on the caixa surface — matching the trajectory each of the
623/// twelve prior peer enums —
624/// [`caixa_core::supervisor::RestartStrategy`] (7baa18a, first-mover
625/// on this axis), [`caixa_core::supervisor::RestartPolicy`] (7851725),
626/// [`caixa_core::CaixaKind`] (231a18c),
627/// [`caixa_core::CaixaDialeto`] (88942cd),
628/// [`caixa_core::dep::DepList`] (32b0ee8),
629/// [`caixa_core::aplicacao::PlacementStrategy`] (1154c2f),
630/// [`caixa_core::aplicacao::WitShape`] (79a8723),
631/// [`caixa_core::aplicacao::RateLimitUnit`] (c7d687d),
632/// [`caixa_core::render::PathShapeViolation`] (6e0479a, first render-
633/// side arm), [`caixa_arch::invariants::InvariantKind`] (1afd8d5,
634/// first outside-`caixa-core` arm — the paired severity-classification
635/// axis on the caixa-arch invariant-kind closed-set enum),
636/// [`caixa_arch::report::ArchVerdict`] (cc80a53, the paired verdict-
637/// outcome axis on the sibling caixa-arch closed-set enum),
638/// `caixa_lint::diagnostic::Severity` (4635d4e),
639/// `caixa_lint::diagnostic::FixSafety` (e4d73c6), and
640/// `caixa_provedor::FerriteRuntime` (1e14fde, the paired ferrite-
641/// runtime axis on the sole caixa-provedor closed-set enum) —
642/// followed on the same 2×2-completion campaign.
643///
644/// Pinned load-bearing by
645/// [`tests::semantic_from_into_owned_string_routes_through_as_str_accessor`]
646/// (byte-parity pin against [`Semantic::as_str`] across the 16-arm
647/// emit-set via the owned-`String` surface, plus a blanket-derived
648/// `Into<String>` shape witness) and
649/// [`tests::semantic_from_into_owned_string_and_static_str_agree_on_every_arm`]
650/// (cross-axis partition pin against the paired owned-input
651/// `&'static str`-returning [`From<Semantic> for &'static str`] impl
652/// and the [`ToString::to_string`]-through-[`std::fmt::Display`]
653/// surface, plus a `.iter().copied().map(String::from)` pipe witness
654/// over [`Semantic::ALL`], plus a direct `Self → String → Self`
655/// round-trip witness through the paired [`TryFrom<&str>`] axis on
656/// the owned-[`String`]'s [`String::as_str`] borrow).
657impl From<Semantic> for String {
658 fn from(sem: Semantic) -> String {
659 sem.as_str().to_owned()
660 }
661}
662
663/// Trait-idiomatic *borrowed-input, owned-`String` output* forward
664/// projection on the [`Semantic`] closed 16-arm caixa-theme semantic-
665/// style axis — the borrowed-input companion to the paired owned-
666/// input [`From<Semantic> for String`] (5ea146c) immediately above,
667/// the paired borrowed-input [`From<&Semantic> for &'static str`]
668/// (ffc0f26), and the paired owned-input
669/// [`From<Semantic> for &'static str`] siblings above. Routes byte-
670/// for-byte through the substrate-primitive [`Semantic::as_str`]
671/// `pub const fn` accessor via [`str::to_owned`] so every consumer
672/// that binds a [`Semantic`] through the standard-library `.into()` /
673/// [`From<&Self> for String`] axis reaches the same 16-arm
674/// `"keyword"` / `"symbol"` / `"keyword-arg"` / `"string"` /
675/// `"number"` / `"literal"` / `"comment"` / `"accent"` / `"muted"` /
676/// `"error"` / `"warning"` / `"info"` / `"hint"` / `"added"` /
677/// `"removed"` / `"unchanged"` canonical-lowercase kebab emit-set
678/// the paired [`std::fmt::Display`], [`AsRef<str>`],
679/// [`Semantic::as_str`], and the three other trait-idiomatic
680/// forward-projection impls already return — no
681/// `sem.as_str().to_owned()` / `String::from(*sem)` (with a spurious
682/// [`Copy`] deref) / `sem.to_string()` (through
683/// [`std::fmt::Display`]) detour whose type bounds have no compile-
684/// time link to the substrate primitive.
685///
686/// Fills the *last* remaining corner of the substrate-wide
687/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
688/// projection family on the sole closed-set fieldless typed enum on
689/// the caixa-theme surface — and, by construction, the *final*
690/// corner on the *entire* substrate-wide closed-set fieldless typed-
691/// enum roster on the caixa surface, closing the substrate-wide
692/// 2×2-completion campaign that opened on
693/// [`caixa_core::supervisor::RestartStrategy`] (579385f, first-mover
694/// on the borrowed-input owned-[`String`] axis). Rust's standard
695/// library carries no blanket
696/// `impl<T: AsRef<str>> From<&T> for String` (nor an
697/// `impl<T: fmt::Display> From<&T> for String`), so every borrowed-
698/// input owned-string call site — a future
699/// `serde_json::Value::String(String::from(&sem))` structured-payload
700/// composer over a borrowed per-style row where the
701/// [`serde_json::Value::String`] arm typing demands an owned
702/// [`String`] and the sibling `&'static str`-returning axes force an
703/// explicit `.to_owned()` / [`String::from`] restatement, a future
704/// `Semantic::ALL.iter().map(String::from).collect::<Vec<_>>()` per-
705/// arm accept-set materializer on a future `feira lint --list-styles`
706/// operator-facing enumeration verb whose iterator yields `&Semantic`
707/// by construction (so the borrowed-input owned-[`String`] axis is
708/// what routes the pipe through the substrate-primitive
709/// [`Semantic::as_str`] accessor without a spurious `.copied()` /
710/// [`Copy`]-bound dereference), a future
711/// `HashMap::<String, usize>::from_iter(Semantic::ALL.iter().map(|sem| (String::from(sem), 0)))`
712/// per-Semantic-paint histogram seed a future `blackmatter-shell`
713/// per-arm `data-semantic="<kebab>"` DOM-attribute emit path
714/// composes off a borrowed `&Semantic` off the loaded theme-overlay
715/// table, a future `caixa-lsp` per-`SemanticTokenType` registration
716/// walk borrowing off a stored per-style row, a future `caixa.nvim`
717/// per-highlight-group re-loader borrowing off the loaded theme-
718/// overlay table where the runtime stores the owned kebab identifier
719/// as [`String`] — otherwise resolves through the detour above.
720///
721/// Closing this corner locks the caixa-theme semantic-style enum's
722/// whole 2×2 trait-idiomatic projection family onto a single
723/// [`Semantic::as_str`]-routed emit-set — any future arm addition (a
724/// `Namespace` tier between [`Self::Symbol`] and [`Self::KeywordArg`]
725/// for the M4 tatara-lisp module system's qualified-name semantic-
726/// token dispatch, a `Deleted` tier for a hard-delete-mark distinct
727/// from [`Self::Removed`] the future 3-way diff surface grows — both
728/// trajectory items the sibling [`Semantic::ALL`] doc block already
729/// names) reaches every projection path through exactly one caixa-
730/// theme edit on the [`Semantic::as_str`] `pub const fn` accessor,
731/// and the partition pin trips at test time on the first detour
732/// that drifts a corner off.
733///
734/// Sixteenth and *final* peer on the substrate-wide trait-idiomatic
735/// *borrowed-input, owned-`String` output* forward-projection family,
736/// closing the substrate-wide 2×2-completion campaign across every
737/// closed-set fieldless typed enum on the caixa surface — opened on
738/// [`caixa_core::supervisor::RestartStrategy`] (579385f), extended
739/// through [`caixa_core::supervisor::RestartPolicy`] (8465740),
740/// [`caixa_core::dep::DepList`] (e0cb617),
741/// [`caixa_core::CaixaKind`] (e76436d),
742/// [`caixa_core::CaixaDialeto`] (d3c0d1d),
743/// [`caixa_core::aplicacao::PlacementStrategy`] (d3dc000),
744/// [`caixa_core::aplicacao::WitShape`] (d638fd3),
745/// [`caixa_core::aplicacao::RateLimitUnit`] (6424e45 — closing the
746/// whole M3 mesh-primitive triple's 2×2 corner),
747/// [`caixa_core::render::PathShapeViolation`] (b90e193 — first
748/// outside-manifest-surface arm on this axis),
749/// [`caixa_arch::invariants::InvariantKind`] (3c3f66f — first
750/// outside-`caixa-core` arm),
751/// [`caixa_arch::report::ArchVerdict`] (3cfb3b5 — second outside-
752/// `caixa-core` arm), `caixa_lint::diagnostic::Severity` (9518ab9 —
753/// third outside-`caixa-core` arm),
754/// `caixa_lint::diagnostic::FixSafety` (807f67d — fourth outside-
755/// `caixa-core` arm), and `caixa_provedor::FerriteRuntime` (0caedec
756/// — fifth outside-`caixa-core` arm), and now this lift on the
757/// sixth-and-last outside-`caixa-core` closed-set enum — the caixa-
758/// theme semantic-style 16-arm axis every per-Semantic paint
759/// dispatch, every future `caixa-lsp` per-`SemanticTokenType` wire-
760/// up, every future `caixa.nvim` per-highlight-group re-loader, and
761/// every future `blackmatter-shell` per-arm `data-semantic="<kebab>"`
762/// DOM emission keys off. Every future closed-set fieldless typed
763/// enum lifted onto the caixa surface picks up the same 2×2 trait-
764/// idiomatic projection family by construction as the substrate
765/// discipline.
766///
767/// Same three-path convergence discipline as the paired owned-input
768/// impl (this borrowed-input axis, the paired owned-input
769/// [`From<Semantic> for String`], and [`Semantic::as_str`] all
770/// route through the same 16-arm inline canonical-lowercase kebab
771/// byte-strings), so a future arm addition reaches every one of the
772/// paired forward-projection paths through exactly one caixa-theme
773/// edit on the [`Semantic::as_str`] `pub const fn` accessor.
774///
775/// The [`Semantic::as_str`] emit and [`Semantic::from_wire`] parse
776/// share the same 16 inline canonical-lowercase kebab byte-strings
777/// by construction — so the borrowed-input owned-[`String`] forward
778/// axis and the reverse [`TryFrom<&str>`] axis compose directly (via
779/// the owned-[`String`]'s [`String::as_str`] borrow) without an
780/// intermediate wire-vocab hop. The round-trip witness pin below
781/// locks this direct composition on the caixa-theme semantic-style
782/// enum's borrowed-input owned-[`String`] axis pair.
783///
784/// Pinned load-bearing by
785/// [`tests::semantic_from_borrowed_into_owned_string_routes_through_as_str_accessor`]
786/// (byte-parity pin against [`Semantic::as_str`] across the 16-arm
787/// emit-set through the borrowed-input surface, plus a blanket-
788/// derived `Into<String>` shape witness) and
789/// [`tests::semantic_from_borrowed_into_owned_string_agrees_with_paired_axes_on_every_arm`]
790/// (cross-axis partition pin against every one of the four 2×2
791/// corners — the paired owned-input owned-[`String`]
792/// [`From<Semantic> for String`] impl (5ea146c), the paired
793/// borrowed-input owned-[`&'static str`]
794/// [`From<&Semantic> for &'static str`] impl (ffc0f26), and the
795/// paired owned-input owned-[`&'static str`]
796/// [`From<Semantic> for &'static str`] impl — plus a
797/// [`ToString::to_string`]-through-[`std::fmt::Display`] byte-parity
798/// witness, plus a `.iter().map(String::from)` pipe witness over
799/// [`Semantic::ALL`] (whose iterator yields `&Semantic` by
800/// construction, so the borrowed-input owned-[`String`] axis is
801/// what routes the pipe through the substrate-primitive
802/// [`Semantic::as_str`] accessor without a spurious [`Copy`] deref),
803/// plus a direct round-trip witness through [`TryFrom<&str>`] on the
804/// owned-[`String`]'s [`String::as_str`] borrow that closes the two-
805/// way `&Self → String → Self` round-trip on the trait-idiomatic
806/// borrowed-input owned-[`String`] forward + reverse axis pair).
807impl From<&Semantic> for String {
808 fn from(sem: &Semantic) -> String {
809 sem.as_str().to_owned()
810 }
811}
812
813#[cfg(test)]
814mod tests {
815 use super::*;
816
817 #[test]
818 fn semantic_all_enumerates_every_variant_in_declaration_order() {
819 // Fail-before-pass-after pin on the [`Semantic::ALL`] slice:
820 // the slice must list every one of the 15 variants in
821 // declaration order (Keyword → Symbol → KeywordArg → String →
822 // Number → Literal → Comment → Accent → Muted → Error →
823 // Warning → Info → Hint → Added → Removed → Unchanged). Peer
824 // of the sibling ALL slices on the closed-set typed-enum
825 // discriminator axes ([`caixa_core::CaixaKind::ALL`],
826 // [`caixa_core::supervisor::RestartStrategy::ALL`],
827 // [`caixa_core::supervisor::RestartPolicy::ALL`],
828 // [`caixa_core::aplicacao::PlacementStrategy::ALL`],
829 // [`caixa_core::upgrade::UpgradeInstruction::ALL`]). A future
830 // arm addition (a `Namespace` tier between `Symbol` and
831 // `KeywordArg` for the M4 tatara-lisp module system's
832 // qualified-name semantic-token dispatch, a `Deleted` tier
833 // for a hard-delete-mark distinct from `Removed` the future
834 // 3-way diff surface grows) that lands the arm on the enum
835 // but forgets to extend `ALL` must trip this pin rather than
836 // surface as a downstream consumer's silently-partial
837 // iteration.
838 assert_eq!(
839 Semantic::ALL,
840 &[
841 Semantic::Keyword,
842 Semantic::Symbol,
843 Semantic::KeywordArg,
844 Semantic::String,
845 Semantic::Number,
846 Semantic::Literal,
847 Semantic::Comment,
848 Semantic::Accent,
849 Semantic::Muted,
850 Semantic::Error,
851 Semantic::Warning,
852 Semantic::Info,
853 Semantic::Hint,
854 Semantic::Added,
855 Semantic::Removed,
856 Semantic::Unchanged,
857 ],
858 );
859 // Also pin the per-arm `IsVariant`-derived partition: every
860 // arm in `ALL` must satisfy exactly one of the 15 generated
861 // arm-discriminator predicates.
862 for variant in Semantic::ALL {
863 let row = [
864 variant.is_keyword(),
865 variant.is_symbol(),
866 variant.is_keyword_arg(),
867 variant.is_string(),
868 variant.is_number(),
869 variant.is_literal(),
870 variant.is_comment(),
871 variant.is_accent(),
872 variant.is_muted(),
873 variant.is_error(),
874 variant.is_warning(),
875 variant.is_info(),
876 variant.is_hint(),
877 variant.is_added(),
878 variant.is_removed(),
879 variant.is_unchanged(),
880 ];
881 let hits = row.iter().filter(|b| **b).count();
882 assert_eq!(
883 hits, 1,
884 "Semantic::{variant:?} must satisfy exactly one of the \
885 15 is_* arm-discriminator predicates; got {row:?}",
886 );
887 }
888 }
889
890 #[test]
891 fn semantic_is_variant_predicates_partition_the_arm_set() {
892 // Fail-before-pass-after pin on the [`gen_platform::IsVariant`]
893 // derive: for each of the 15 variants, exactly one of the
894 // generated is_* predicates returns `true` and the other 14
895 // return `false`. Pre-derive the closed 15-arm partition
896 // lived only inside the two theme overlays' 15-arm match
897 // resolvers; a future rebrand (a `#[is_variant(name = "…")]`
898 // drift, a manual hand-rolled `impl` that shadows the
899 // derive-generated method, an arm rename) trips this pin at
900 // caixa-theme build time rather than surfacing far from the
901 // derive declaration. Peer of the sibling
902 // [`caixa_core::CaixaKind`] `IsVariant` partition pin.
903 // A copy-paste flip that reroutes one arm through the wrong
904 // predicate lane trips at the identity-diagonal assertion,
905 // since each variant's row is generated live from `ALL`'s
906 // declaration order rather than transcribed by hand.
907 for (idx, variant) in Semantic::ALL.iter().enumerate() {
908 let observed: [bool; 16] = [
909 variant.is_keyword(),
910 variant.is_symbol(),
911 variant.is_keyword_arg(),
912 variant.is_string(),
913 variant.is_number(),
914 variant.is_literal(),
915 variant.is_comment(),
916 variant.is_accent(),
917 variant.is_muted(),
918 variant.is_error(),
919 variant.is_warning(),
920 variant.is_info(),
921 variant.is_hint(),
922 variant.is_added(),
923 variant.is_removed(),
924 variant.is_unchanged(),
925 ];
926 let mut expected = [false; 16];
927 expected[idx] = true;
928 assert_eq!(
929 observed, expected,
930 "Semantic::{variant:?} at ALL[{idx}] is_* predicates \
931 must fire only on their own arm lane (identity \
932 diagonal); got {observed:?}",
933 );
934 }
935 }
936
937 #[test]
938 fn semantic_as_str_returns_canonical_kebab_case_per_arm() {
939 // Fail-before-pass-after per-arm byte-string pin on
940 // [`Semantic::as_str`] — the substrate-canonical `&'static str`
941 // projection every downstream consumer of the closed 16-arm
942 // partition reaches through. A future arm rename (a `Symbol` →
943 // `Identifier` rebrand tracking a hypothetical LSP-side
944 // `SemanticTokenType` reshuffle, an `Accent` → `Highlight`
945 // rebrand tracking a `blackmatter-shell` classname rework) that
946 // touches the enum arm but forgets to update the paired
947 // `as_str` arm — or vice versa — trips this pin at caixa-theme
948 // build time rather than surfacing as a downstream
949 // `feira lint --list-styles` operator-facing enumeration verb's
950 // silently-renamed row far from the two-declaration site.
951 //
952 // Kebab-case matches the peer [`gen_platform::IsVariant`]-
953 // derived kebab discriminant convention the sibling closed-set
954 // typed enums already emit on their canonical byte-string
955 // projection axis.
956 assert_eq!(Semantic::Keyword.as_str(), "keyword");
957 assert_eq!(Semantic::Symbol.as_str(), "symbol");
958 assert_eq!(Semantic::KeywordArg.as_str(), "keyword-arg");
959 assert_eq!(Semantic::String.as_str(), "string");
960 assert_eq!(Semantic::Number.as_str(), "number");
961 assert_eq!(Semantic::Literal.as_str(), "literal");
962 assert_eq!(Semantic::Comment.as_str(), "comment");
963 assert_eq!(Semantic::Accent.as_str(), "accent");
964 assert_eq!(Semantic::Muted.as_str(), "muted");
965 assert_eq!(Semantic::Error.as_str(), "error");
966 assert_eq!(Semantic::Warning.as_str(), "warning");
967 assert_eq!(Semantic::Info.as_str(), "info");
968 assert_eq!(Semantic::Hint.as_str(), "hint");
969 assert_eq!(Semantic::Added.as_str(), "added");
970 assert_eq!(Semantic::Removed.as_str(), "removed");
971 assert_eq!(Semantic::Unchanged.as_str(), "unchanged");
972 }
973
974 #[test]
975 fn semantic_as_str_projections_are_all_distinct_across_arms() {
976 // Fail-before-pass-after pin on the injectivity of
977 // [`Semantic::as_str`]'s projection — no two arms may share
978 // their canonical kebab byte-string, since a future consumer
979 // that keys a per-arm dispatch table off the projection (a
980 // `HashMap::<&str, _>::from_iter(Semantic::ALL.iter().map(|s|
981 // (s.as_str(), …)))` style-lookup, a future `caixa-lsp`
982 // `SemanticTokenType::new(sem.as_ref())` registration table
983 // keyed by kebab identifier, a future `feira lint --list-styles`
984 // one-row-per-arm enumeration table) would silently collapse
985 // the two colliding arms onto one entry, dropping the second
986 // insertion. A future arm addition (a `Namespace` tier between
987 // `Symbol` and `KeywordArg` for the M4 tatara-lisp module
988 // system's qualified-name semantic-token dispatch, a `Deleted`
989 // tier for a hard-delete-mark distinct from `Removed` a future
990 // 3-way diff surface grows) that lands the arm on the enum and
991 // reuses a peer arm's kebab identifier (a copy-paste-derived
992 // `"removed"` on the new `Deleted` arm) trips this pin rather
993 // than surfacing far from the arm addition site.
994 let mut projections: Vec<&'static str> = Semantic::ALL.iter().map(|s| s.as_str()).collect();
995 let before = projections.len();
996 projections.sort_unstable();
997 projections.dedup();
998 assert_eq!(
999 projections.len(),
1000 before,
1001 "Semantic::as_str must be injective across ALL — collisions: \
1002 {projections:?}",
1003 );
1004 }
1005
1006 #[test]
1007 fn semantic_display_and_as_ref_str_route_through_as_str_accessor() {
1008 // Fail-before-pass-after three-path convergence pin on the
1009 // substrate-wide `(as_str, AsRef<str>, Display)` canonical-
1010 // projection triple for the caixa-theme [`Semantic`] closed-set
1011 // fieldless typed enum. For every arm in [`Semantic::ALL`], the
1012 // paired [`std::fmt::Display`] impl + [`AsRef<str>`] impl + the
1013 // substrate-canonical [`Semantic::as_str`] `pub const fn`
1014 // scalar accessor must resolve to the same `&'static str`
1015 // per arm. Peer of the sibling three-path-convergence pins the
1016 // substrate carries on the closed-set typed enums the prior
1017 // lifts converged onto
1018 // (`restart_strategy_display_routes_through_as_str_helper` /
1019 // `restart_strategy_as_ref_str_routes_through_as_str_accessor`
1020 // on [`caixa_core::supervisor::RestartStrategy`],
1021 // `ferrite_runtime_display_and_as_ref_str_route_through_variant_slug_accessor`
1022 // on `caixa_provedor::FerriteRuntime`, and the analogous pins
1023 // on `caixa_lint::Severity` / `caixa_lint::FixSafety` /
1024 // `caixa_arch::InvariantKind` / `caixa_arch::ArchVerdict`).
1025 //
1026 // A future accidental split (a hand-rolled `impl fmt::Display`
1027 // that shadows this route through a divergent per-arm match, an
1028 // `impl AsRef<str>` that returns the compiler-derived `Debug`
1029 // string via `format!("{:?}", self)` — allocating and diverging
1030 // on every arm — or a `#[serde(rename_all = "…")]` attribute
1031 // drift that quietly forks the projection) trips this pin at
1032 // caixa-theme build time rather than surfacing as a downstream
1033 // consumer's silently-forked per-Semantic dispatch far from the
1034 // trait-impl declaration site.
1035 for &sem in Semantic::ALL {
1036 let via_as_str: &str = sem.as_str();
1037 let via_display: String = format!("{sem}");
1038 let via_as_ref: &str = <Semantic as AsRef<str>>::as_ref(&sem);
1039 assert_eq!(
1040 via_display, via_as_str,
1041 "Semantic::{sem:?} — Display routes off `as_str`; got \
1042 Display={via_display:?} vs as_str={via_as_str:?}",
1043 );
1044 assert_eq!(
1045 via_as_ref, via_as_str,
1046 "Semantic::{sem:?} — AsRef<str> routes off `as_str`; got \
1047 AsRef={via_as_ref:?} vs as_str={via_as_str:?}",
1048 );
1049 }
1050 }
1051
1052 #[test]
1053 fn semantic_as_str_is_usable_in_const_context() {
1054 // The [`Semantic::as_str`] accessor is declared `pub const fn`,
1055 // matching the peer closed-set typed enums' canonical
1056 // `&'static str` projection accessors
1057 // ([`caixa_core::CaixaKind::as_str`],
1058 // [`caixa_core::supervisor::RestartStrategy::as_str`],
1059 // [`caixa_core::aplicacao::PlacementStrategy::as_str`],
1060 // `caixa_provedor::FerriteRuntime::variant_slug`). Pin the
1061 // same posture with a `const {}` assertion block so a future
1062 // accidental downgrade to non-`const` (an added runtime helper
1063 // reachable only from a non-`const` context) trips at
1064 // caixa-theme build time rather than surfacing as a downstream
1065 // `const`-context regression far from the accessor
1066 // declaration.
1067 const KEYWORD: &str = Semantic::Keyword.as_str();
1068 const ERROR: &str = Semantic::Error.as_str();
1069 const UNCHANGED: &str = Semantic::Unchanged.as_str();
1070 const { assert!(KEYWORD.as_bytes()[0] == b'k') };
1071 const { assert!(ERROR.as_bytes()[0] == b'e') };
1072 const { assert!(UNCHANGED.as_bytes()[0] == b'u') };
1073 }
1074
1075 #[test]
1076 fn semantic_from_wire_accepts_every_as_str_output() {
1077 // Fail-before-pass-after per-arm accept pin on the newly lifted
1078 // [`Semantic::from_wire`] reverse projection: every arm in
1079 // [`Semantic::ALL`] must parse back through `from_wire` when fed
1080 // its own [`Semantic::as_str`] output, landing on
1081 // `Some(same_variant)`. A regression that hand-rolled either
1082 // side's per-arm match without threading through the shared
1083 // 16-string closed set would silently disagree on any future
1084 // arm rename (a `Symbol` → `Identifier` rebrand tracking a
1085 // hypothetical LSP-side `SemanticTokenType` reshuffle, an
1086 // `Accent` → `Highlight` rebrand tracking a `blackmatter-shell`
1087 // classname rework) or new arm the theme grows (a `Namespace`
1088 // tier between `Symbol` and `KeywordArg` for the M4 tatara-lisp
1089 // module system's qualified-name semantic-token dispatch, a
1090 // `Deleted` tier for a hard-delete-mark distinct from `Removed`
1091 // the future 3-way diff surface grows) and this pin flags it at
1092 // caixa-theme build time rather than at a downstream
1093 // `feira lint --list-styles` operator-facing enumeration verb's
1094 // silent tag misclassification.
1095 //
1096 // Peer of the sibling
1097 // `caixa_lint::diagnostic::tests::severity_from_wire_accepts_every_as_str_output`
1098 // (5afff0e) /
1099 // `caixa_lint::diagnostic::tests::fix_safety_from_wire_accepts_every_as_str_output`
1100 // (bd505a1) /
1101 // `caixa_arch::report::tests::arch_verdict_from_wire_accepts_every_as_str_output`
1102 // (6afe564) /
1103 // `caixa_arch::invariants::tests::invariant_kind_from_wire_accepts_every_as_str_output`
1104 // (b9e4e61) round-trip pins on the peer caixa-lint / caixa-arch
1105 // closed-set-enum reverse-projection axes, and of the sibling
1106 // `caixa_core::kind::tests::caixa_kind_wire_round_trips_through_from_wire`
1107 // (2aa6d23) /
1108 // `caixa_core::dialeto::tests::caixa_dialeto_from_wire_accepts_every_as_str_output`
1109 // (d0e65ea) /
1110 // `caixa_core::aplicacao::tests::placement_strategy_from_wire_accepts_every_lifted_constant`
1111 // (18c7342) /
1112 // `caixa_core::dep::tests::dep_list_round_trips_through_as_str_and_from_wire`
1113 // (45ee563) /
1114 // `caixa_core::render::tests::path_shape_violation_from_wire_accepts_every_as_str_output`
1115 // (aebd9c6) round-trip pins on the sibling caixa-core closed-
1116 // set typed-enum reverse-projection axes.
1117 for &variant in Semantic::ALL {
1118 let wire = variant.as_str();
1119 let parsed = Semantic::from_wire(wire).unwrap_or_else(|| {
1120 panic!(
1121 "Semantic::from_wire({wire:?}) must accept every \
1122 Semantic::as_str output — got None for the wire \
1123 byte-string of {variant:?}"
1124 )
1125 });
1126 assert_eq!(
1127 parsed, variant,
1128 "Semantic::from_wire(Semantic::{variant:?}.as_str()) \
1129 must return Semantic::{variant:?} — the (as_str, \
1130 from_wire) pair must form a total round-trip on the \
1131 closed 16-arm Semantic arm-set",
1132 );
1133 }
1134 }
1135
1136 #[test]
1137 fn semantic_from_wire_rejects_unknown_byte_strings() {
1138 // Rejection pin on the [`Semantic::from_wire`] parser's accept-
1139 // set: any string outside the 16-arm [`Semantic::as_str`] output
1140 // set must return `None`. A future accidental widening of the
1141 // accept-set (a case-insensitive match that accepts `"KEYWORD"`
1142 // / `"Keyword"`, a silent acceptance of the pre-lift PascalCase
1143 // Debug-derived shapes `"Keyword"` / `"KeywordArg"` /
1144 // `"Unchanged"` on the wire axis, a snake_case drift accepting
1145 // `"keyword_arg"` beside the canonical kebab-case
1146 // `"keyword-arg"`, a Levenshtein-forgiving arm-lookup that
1147 // admits `"kewyord"` typos, a silent absorption of a hypothetical
1148 // future `Namespace` / `Deleted` arm before it lands on the enum
1149 // and its paired [`Semantic::as_str`] emitter arm) would
1150 // silently drift the parser's accept-set from the emitter's — a
1151 // downstream style-report re-loader that bound a prior report's
1152 // [`Self::as_str`] output back to the typed enum through this
1153 // parser would then bind a malformed byte-string to a plausibly-
1154 // wrong typed arm the caller does not route through any
1155 // fallback, silently misclassifying the reloaded row.
1156 //
1157 // Peer of the sibling
1158 // `caixa_lint::diagnostic::tests::severity_from_wire_rejects_unknown_byte_strings`
1159 // (5afff0e) /
1160 // `caixa_lint::diagnostic::tests::fix_safety_from_wire_rejects_unknown_byte_strings`
1161 // (bd505a1) /
1162 // `caixa_arch::report::tests::arch_verdict_from_wire_rejects_unknown_byte_strings`
1163 // (6afe564) /
1164 // `caixa_arch::invariants::tests::invariant_kind_from_wire_rejects_unknown_byte_strings`
1165 // (b9e4e61) rejection pins on the peer caixa-lint / caixa-arch
1166 // axes, and of the sibling
1167 // `caixa_kind_from_wire_rejects_unknown_byte_strings` (2aa6d23),
1168 // `caixa_dialeto_from_wire_rejects_unknown_byte_strings`
1169 // (d0e65ea),
1170 // `placement_strategy_from_wire_rejects_unknown_byte_strings`
1171 // (18c7342),
1172 // `dep_list_from_wire_returns_none_on_unknown_wire_scalar`
1173 // (45ee563), and
1174 // `path_shape_violation_from_wire_rejects_unknown_byte_strings`
1175 // (aebd9c6) rejection pins on the sibling caixa-core axes.
1176 //
1177 // The rejection set also covers overlapping-byte-string tags
1178 // from peer axes: caixa-lint `Severity::as_str` outputs
1179 // `"error"`/`"warning"`/`"info"`/`"hint"` and caixa-arch
1180 // `InvariantKind::as_str` outputs `"safety"`/`"compliance"`
1181 // share zero canonical byte-strings with the widened 16-arm
1182 // Semantic set here — a widened parser that admitted the peer's
1183 // arm on the sibling axis would still not admit an arm foreign
1184 // to the caixa-theme semantic-style discriminator's own accept-
1185 // set. Yet four peer-axis strings DO overlap with the
1186 // caixa-theme set here (`Severity`'s
1187 // `"error"`/`"warning"`/`"info"`/`"hint"` map identically onto
1188 // the caixa-theme diagnostic-severity sub-region
1189 // `Semantic::Error`/`Warning`/`Info`/`Hint`) — a widened parser
1190 // that admitted them under a different arm would collapse the
1191 // two axes and silently mislabel; the pin excludes those four
1192 // from the rejection set precisely because they must accept.
1193 for bad in [
1194 "",
1195 " ",
1196 "Keyword",
1197 "KEYWORD",
1198 "Symbol",
1199 "SYMBOL",
1200 "KeywordArg",
1201 "keyword_arg",
1202 "keywordarg",
1203 "String",
1204 "STRING",
1205 "Number",
1206 "Literal",
1207 "Comment",
1208 "Accent",
1209 "Muted",
1210 "Error",
1211 "ERROR",
1212 "Warning",
1213 "WARNING",
1214 "Info",
1215 "INFO",
1216 "Hint",
1217 "HINT",
1218 "Added",
1219 "ADDED",
1220 "Removed",
1221 "REMOVED",
1222 "Unchanged",
1223 "UNCHANGED",
1224 "kewyord",
1225 "sym",
1226 "kw",
1227 "str",
1228 "num",
1229 "lit",
1230 "cmt",
1231 "safe",
1232 "unsafe",
1233 "safety",
1234 "compliance",
1235 "proven",
1236 "rejected",
1237 "namespace",
1238 "deleted",
1239 "highlight",
1240 "identifier",
1241 "keyword ",
1242 " keyword",
1243 "keyword\n",
1244 "keyword\t",
1245 "keyword-arg ",
1246 " keyword-arg",
1247 "added ",
1248 " added",
1249 "unchanged ",
1250 " unchanged",
1251 ] {
1252 assert!(
1253 Semantic::from_wire(bad).is_none(),
1254 "Semantic::from_wire({bad:?}) must return None — the \
1255 parser's accept-set is exactly the 16 Semantic::as_str \
1256 outputs; a widening would silently split the parser's \
1257 accept-set from the emitter's arm-set",
1258 );
1259 }
1260 }
1261
1262 #[test]
1263 fn semantic_is_variant_predicates_are_const_fn() {
1264 // The [`gen_platform::IsVariant`] derive emits `const fn`
1265 // predicates on the peer [`caixa_core::CaixaKind`] /
1266 // [`caixa_core::upgrade::UpgradeInstruction`] /
1267 // [`caixa_core::supervisor::RestartStrategy`] /
1268 // [`caixa_core::supervisor::RestartPolicy`] closed-set typed
1269 // enums — pin the same posture on [`Semantic`] so a future
1270 // accidental downgrade to non-`const` (an added runtime helper
1271 // reachable only from a non-`const` context, a manual hand-
1272 // rolled `impl` that shadows the derive-generated method)
1273 // trips at caixa-theme build time rather than surfacing as a
1274 // downstream `const`-context regression far from the derive
1275 // declaration.
1276 const { assert!(Semantic::Keyword.is_keyword()) };
1277 const { assert!(Semantic::Error.is_error()) };
1278 const { assert!(Semantic::Added.is_added()) };
1279 const { assert!(Semantic::Unchanged.is_unchanged()) };
1280 }
1281
1282 #[test]
1283 fn semantic_try_from_str_routes_through_from_wire_accessor() {
1284 // Fail-before-pass-after byte-parity pin on the newly lifted
1285 // `impl TryFrom<&str> for Semantic` — asserts the standard-
1286 // library trait impl and the substrate-primitive
1287 // [`super::Semantic::from_wire`] `Option<Self>` accessor
1288 // resolve to the same 16-arm accept-set across every arm the
1289 // exhaustive [`super::Semantic::ALL`] slice enumerates. Any
1290 // future silent detour that routes the trait impl through a
1291 // divergent projection (a per-arm inline `match s { "keyword"
1292 // => Ok(Self::Keyword), … }` re-inlining that opens a
1293 // compile-time link to the un-lifted arm-literal, a silent
1294 // case-fold that admits `"Keyword"` / `"KEYWORD"` and would
1295 // collide the canonical-lowercase accept-set the emitter
1296 // dispatches on) trips at caixa-theme test time under
1297 // `assert_eq!` rather than at a downstream
1298 // `impl TryFrom<&str>`-bound consumer's silent split. Sweeps
1299 // every one of the 16 arms [`super::Semantic::ALL`] carries so
1300 // no arm's projection is covered only by the sibling method-
1301 // named `from_wire` path.
1302 //
1303 // Peer of the sibling
1304 // [`caixa_core::kind::tests::caixa_kind_try_from_str_routes_through_from_wire_accessor`]
1305 // (3c83606),
1306 // [`caixa_core::dialeto::tests::caixa_dialeto_try_from_str_routes_through_from_wire_accessor`]
1307 // (bf33136),
1308 // `placement_strategy_try_from_str_routes_through_from_wire_accessor`
1309 // (6fd00cd),
1310 // `rate_limit_unit_try_from_str_routes_through_from_suffix_accessor`
1311 // (bf78400),
1312 // `path_shape_violation_try_from_str_routes_through_from_wire_accessor`
1313 // (e67e48a),
1314 // `caixa_arch::invariants::tests::invariant_kind_try_from_str_routes_through_from_wire_accessor`
1315 // (e21a857),
1316 // `caixa_arch::report::tests::arch_verdict_try_from_str_routes_through_from_wire_accessor`
1317 // (0a4cc45),
1318 // `caixa_lint::diagnostic::tests::severity_try_from_str_routes_through_from_wire_accessor`
1319 // (a7bf74c), and
1320 // `caixa_lint::diagnostic::tests::fix_safety_try_from_str_routes_through_from_wire_accessor`
1321 // (df86c94) — extends the trait-idiomatic reverse-projection
1322 // axis onto the first closed-set fieldless typed enum on the
1323 // caixa-theme surface (the semantic-style axis).
1324 for &variant in Semantic::ALL {
1325 let wire = variant.as_str();
1326 assert_eq!(
1327 <Semantic as TryFrom<&str>>::try_from(wire),
1328 Ok(variant),
1329 "TryFrom<&str> impl on Semantic must round-trip \
1330 Semantic::{variant:?}.as_str() = {wire:?} back to \
1331 Ok(Semantic::{variant:?}) — divergence from \
1332 Semantic::from_wire signals a silent detour off the \
1333 substrate-primitive accessor",
1334 );
1335 assert_eq!(
1336 <Semantic as TryFrom<&str>>::try_from(wire).ok(),
1337 Semantic::from_wire(wire),
1338 "TryFrom<&str> ok()-projection on {wire:?} must \
1339 byte-equal Semantic::from_wire on the same input",
1340 );
1341 }
1342 }
1343
1344 #[test]
1345 fn semantic_try_from_str_rejects_unknown_byte_strings() {
1346 // Rejection witness on the `impl TryFrom<&str> for Semantic` —
1347 // sweeps a candidate set of byte-strings outside the 16-arm
1348 // canonical-lowercase kebab wire accept-set the sibling
1349 // [`super::Semantic::as_str`] emits and asserts every one
1350 // lands on `Err(())`, so a future accidental widening of the
1351 // trait impl's accept-set (a stray additional
1352 // `_ if s.eq_ignore_ascii_case("keyword") => Ok(…)` case-fold
1353 // path, a silent acceptance of the pre-lift PascalCase Debug-
1354 // derived shapes `"Keyword"` / `"Symbol"` / `"KeywordArg"` on
1355 // the wire axis, a Levenshtein-forgiving arm-lookup that
1356 // admits `"kwd"` / `"sym"` / `"kw"` typos — the exact form a
1357 // `format!("{:?}", …).to_lowercase()` round-trip on the paired
1358 // [`std::fmt::Debug`] derive would otherwise land on) trips at
1359 // caixa-theme test time. The candidate set includes the empty
1360 // string, whitespace-only padding, uppercase / PascalCase
1361 // rebrand candidates, Levenshtein-neighbor typos, sibling
1362 // closed-set-enum canonical tags not shared with this axis
1363 // (peer `caixa_lint::diagnostic::FixSafety::as_str` two-arm
1364 // `"safe"` / `"unsafe"`, peer `caixa_arch::InvariantKind::as_str`
1365 // three-arm `"safety"` / `"compliance"`, peer
1366 // `caixa_arch::ArchVerdict::as_str` two-arm `"proven"` /
1367 // `"rejected"`), the trajectory-item candidates
1368 // (`"namespace"`, `"deleted"`) the sibling [`Semantic::ALL`]
1369 // doc block already names, whitespace-padded canonical tags,
1370 // and CamelCase spellings of the multi-word `KeywordArg`
1371 // variant (`"KeywordArg"`, `"keywordarg"`, `"keyword_arg"`,
1372 // `"keyword.arg"`) that would silently admit
1373 // if the accept-set widened to a case-fold or separator-
1374 // normalization rule.
1375 //
1376 // Peer of the sibling
1377 // `caixa_kind_try_from_str_rejects_unknown_byte_strings`
1378 // (3c83606),
1379 // `caixa_dialeto_try_from_str_rejects_unknown_byte_strings`
1380 // (bf33136),
1381 // `rate_limit_unit_try_from_str_rejects_unknown_byte_strings`
1382 // (bf78400),
1383 // `path_shape_violation_try_from_str_rejects_unknown_byte_strings`
1384 // (e67e48a),
1385 // `invariant_kind_try_from_str_rejects_unknown_byte_strings`
1386 // (e21a857),
1387 // `arch_verdict_try_from_str_rejects_unknown_byte_strings`
1388 // (0a4cc45),
1389 // `severity_try_from_str_rejects_unknown_byte_strings`
1390 // (a7bf74c), and
1391 // `fix_safety_try_from_str_rejects_unknown_byte_strings`
1392 // (df86c94) rejection pins on the sibling closed-set typed-
1393 // enum trait-idiomatic reverse-projection axes.
1394 for bad in [
1395 "",
1396 " ",
1397 "Keyword",
1398 "KEYWORD",
1399 "Symbol",
1400 "KeywordArg",
1401 "keywordarg",
1402 "keyword_arg",
1403 "keyword.arg",
1404 "String",
1405 "Number",
1406 "Literal",
1407 "Comment",
1408 "Accent",
1409 "Muted",
1410 "Error",
1411 "ERROR",
1412 "Warning",
1413 "Info",
1414 "Hint",
1415 "Added",
1416 "Removed",
1417 "Unchanged",
1418 "kwd",
1419 "sym",
1420 "kw",
1421 "str",
1422 "num",
1423 "lit",
1424 "cmt",
1425 "safe",
1426 "unsafe",
1427 "safety",
1428 "compliance",
1429 "proven",
1430 "rejected",
1431 "namespace",
1432 "deleted",
1433 "highlight",
1434 "identifier",
1435 "keyword ",
1436 " keyword",
1437 "keyword\n",
1438 "keyword\t",
1439 "keyword-arg ",
1440 " keyword-arg",
1441 "added ",
1442 " added",
1443 "unchanged ",
1444 " unchanged",
1445 ] {
1446 assert_eq!(
1447 <Semantic as TryFrom<&str>>::try_from(bad),
1448 Err(()),
1449 "TryFrom<&str> for Semantic({bad:?}) must return \
1450 Err(()) — the trait impl's accept-set is exactly the \
1451 16 Semantic::as_str outputs; a widening would \
1452 silently split the trait impl's accept-set from the \
1453 emitter's arm-set",
1454 );
1455 }
1456 }
1457
1458 #[test]
1459 fn semantic_try_from_str_and_from_wire_partition_the_accept_set() {
1460 // Cross-axis partition pin: the trait-idiomatic
1461 // [`TryFrom<&str>`] and the method-named
1462 // [`super::Semantic::from_wire`] projections must return
1463 // equivalent decisions on every input — the trait impl's
1464 // `.ok()` project-out from `Result<Self, ()>` and the method's
1465 // `Option<Self>` return must byte-equal each other on both
1466 // accepts and rejects. A future silent bifurcation (the trait
1467 // impl gaining a case-fold path the method does not carry, the
1468 // method gaining a synonym alias the trait impl does not
1469 // honor) trips at caixa-theme test time under a single pin
1470 // rather than at a downstream generic-bound consumer that
1471 // dispatches through one axis while a peer dispatches through
1472 // the other. Sweeps both the 16-arm accept-set (via
1473 // [`super::Semantic::ALL`] threaded through
1474 // [`super::Semantic::as_str`]) and a canonical rejection
1475 // sample so both halves of the partition are covered. Peer of
1476 // the sibling
1477 // `severity_try_from_str_and_from_wire_partition_the_accept_set`
1478 // (a7bf74c) and
1479 // `fix_safety_try_from_str_and_from_wire_partition_the_accept_set`
1480 // (df86c94) partition pins.
1481 for &variant in Semantic::ALL {
1482 let wire = variant.as_str();
1483 assert_eq!(
1484 <Semantic as TryFrom<&str>>::try_from(wire).ok(),
1485 Semantic::from_wire(wire),
1486 "TryFrom<&str>::ok() and from_wire must agree on \
1487 Semantic::{variant:?}.as_str() = {wire:?}",
1488 );
1489 }
1490 for bad in [
1491 "",
1492 "Keyword",
1493 "unknown",
1494 "safety",
1495 "safe",
1496 "proven",
1497 "namespace",
1498 "keywordarg",
1499 ] {
1500 assert_eq!(
1501 <Semantic as TryFrom<&str>>::try_from(bad).ok(),
1502 Semantic::from_wire(bad),
1503 "TryFrom<&str>::ok() and from_wire must agree on the \
1504 rejection outcome for {bad:?}",
1505 );
1506 }
1507 }
1508
1509 #[test]
1510 fn semantic_from_into_static_str_routes_through_as_str_accessor() {
1511 // Fail-before-pass-after byte-parity pin on the newly lifted
1512 // `impl From<Semantic> for &'static str` — asserts the standard-
1513 // library trait impl and the substrate-primitive
1514 // [`super::Semantic::as_str`] `pub const fn` accessor resolve to
1515 // the same 16-arm canonical-lowercase kebab emit-set across every
1516 // arm the exhaustive [`super::Semantic::ALL`] slice enumerates.
1517 // Any future silent detour that routes the trait impl through a
1518 // divergent projection (a per-arm inline `match sem { Keyword =>
1519 // "keyword", … }` re-inlining that opens a compile-time link to
1520 // the un-lifted arm-literal outside the paired
1521 // [`super::Semantic::as_str`] dispatch, a swap onto a
1522 // `format!("{:?}", …).to_lowercase()` round-trip through the
1523 // `#[derive(Debug)]` output whose stability is *not* guaranteed
1524 // and would silently reroute the semantic-style tag through a
1525 // stale byte-string with no downstream signal until an operator
1526 // scrolled the theme-paint terminal, a `#[serde(rename_all = "…")]`
1527 // attribute drift that quietly forks one axis) trips at
1528 // caixa-theme test time under `assert_eq!` rather than at a
1529 // downstream `impl Into<&'static str>`-bound consumer's silent
1530 // split. Sweeps every one of the 16 arms
1531 // [`super::Semantic::ALL`] carries so no arm's projection is
1532 // covered only by the sibling method-named `as_str` /
1533 // [`std::fmt::Display`] / [`AsRef<str>`] paths. Materializes
1534 // three `<&'static str as From<Semantic>>::from` outputs in
1535 // `const`-shape bindings against the paired
1536 // [`super::Semantic::as_str`] `pub const fn` accessor to make
1537 // the `'static` lifetime promise a build-time invariant — a
1538 // future accidental downgrade of any arm's inline canonical-
1539 // lowercase kebab byte-string to a non-`&'static str` (a
1540 // `String::leak()`-produced return, a `Box::leak`-cast, an
1541 // intermediate lifetime-erasing helper) trips at caixa-theme
1542 // build time rather than at a downstream `'static`-bound
1543 // consumer.
1544 //
1545 // Peer of the sibling
1546 // [`caixa_core::supervisor::tests::restart_strategy_from_into_static_str_routes_through_as_str_accessor`]
1547 // (523157d),
1548 // [`caixa_core::supervisor::tests::restart_policy_from_into_static_str_routes_through_as_str_accessor`]
1549 // (9fb37d0),
1550 // [`caixa_core::kind::tests::caixa_kind_from_into_static_str_routes_through_as_str_accessor`]
1551 // (edb827b),
1552 // [`caixa_core::dialeto::tests::caixa_dialeto_from_into_static_str_routes_through_as_str_accessor`]
1553 // (c189a6f),
1554 // [`caixa_core::aplicacao::tests::placement_strategy_from_into_static_str_routes_through_as_str_accessor`]
1555 // (afa3562),
1556 // [`caixa_core::aplicacao::tests::wit_shape_from_into_static_str_routes_through_as_str_accessor`]
1557 // (56998ec),
1558 // [`caixa_core::aplicacao::tests::rate_limit_unit_from_into_static_str_routes_through_as_suffix_accessor`]
1559 // (7fdfbf4),
1560 // [`caixa_core::render::tests::path_shape_violation_from_into_static_str_routes_through_as_str_accessor`]
1561 // (070a6de),
1562 // `caixa_arch::invariants::tests::invariant_kind_from_into_static_str_routes_through_as_str_accessor`
1563 // (f2ca7bc),
1564 // `caixa_arch::report::tests::arch_verdict_from_into_static_str_routes_through_as_str_accessor`
1565 // (d4559cb),
1566 // `caixa_lint::diagnostic::tests::severity_from_into_static_str_routes_through_as_str_accessor`
1567 // (5cc3b8b), and
1568 // `caixa_lint::diagnostic::tests::fix_safety_from_into_static_str_routes_through_as_str_accessor`
1569 // (2a56127) pins on the sibling closed-set typed-enum forward-
1570 // projection axes — extends the trait-idiomatic forward-
1571 // projection axis onto the first closed-set fieldless typed
1572 // enum on the caixa-theme surface (the semantic-style axis),
1573 // leaving `caixa_provedor::FerriteRuntime` as the last outside-
1574 // caixa-core closed-set fieldless typed enum whose trait-
1575 // idiomatic forward axis is still open.
1576 const KEYWORD: &str = Semantic::Keyword.as_str();
1577 const KEYWORD_ARG: &str = Semantic::KeywordArg.as_str();
1578 const UNCHANGED: &str = Semantic::Unchanged.as_str();
1579 for &variant in Semantic::ALL {
1580 let via_trait: &'static str = <&'static str as From<Semantic>>::from(variant);
1581 let via_method: &'static str = variant.as_str();
1582 assert_eq!(
1583 via_trait, via_method,
1584 "From<Semantic> for &'static str impl must round-trip \
1585 Semantic::{variant:?} to the same canonical-lowercase \
1586 kebab byte-string Semantic::as_str returns — divergence \
1587 signals a silent detour off the substrate-primitive \
1588 accessor"
1589 );
1590 let via_into: &'static str = variant.into();
1591 assert_eq!(
1592 via_into, via_method,
1593 "Into<&'static str>::into on Semantic::{variant:?} must \
1594 byte-equal Semantic::as_str on the same input — the \
1595 blanket-derived Into shape must resolve to the same \
1596 as_str dispatch as the explicit From impl"
1597 );
1598 }
1599 assert_eq!(
1600 [KEYWORD, KEYWORD_ARG, UNCHANGED],
1601 ["keyword", "keyword-arg", "unchanged"],
1602 "const-context Semantic::as_str must resolve to the \
1603 canonical-lowercase kebab byte-strings — a future \
1604 accidental downgrade of any arm to a non-const or non-\
1605 static byte-string breaks the `&'static str`-lifetime \
1606 promise the paired From<Semantic> for &'static str impl \
1607 carries by construction"
1608 );
1609 }
1610
1611 #[test]
1612 fn semantic_from_into_static_str_and_as_str_partition_the_emit_set() {
1613 // Cross-axis partition pin: the paired trait-idiomatic
1614 // `From<Semantic> for &'static str` forward projection and the
1615 // method-named [`super::Semantic::as_str`] forward projection
1616 // must resolve identically on *every* arm, not just the ones
1617 // named in the primary byte-parity pin above. Sweeps every
1618 // [`super::Semantic::ALL`] arm and asserts the trait's
1619 // `From::from` output byte-equals the method-named accessor's
1620 // return-value on each, locking the two forward-projection paths
1621 // together by construction so any future detour (a stray `From`
1622 // special-case that lands on a divergent per-arm literal outside
1623 // the paired `as_str` dispatch, a hypothetical rebrand touching
1624 // one axis without the other) trips at caixa-theme test time.
1625 //
1626 // Peer of the sibling forward-projection partition pins
1627 // [`caixa_core::supervisor::tests::restart_strategy_from_into_static_str_and_as_str_partition_the_emit_set`]
1628 // (523157d),
1629 // [`caixa_core::supervisor::tests::restart_policy_from_into_static_str_and_as_str_partition_the_emit_set`]
1630 // (9fb37d0),
1631 // [`caixa_core::kind::tests::caixa_kind_from_into_static_str_and_as_str_partition_the_emit_set`]
1632 // (edb827b),
1633 // [`caixa_core::dialeto::tests::caixa_dialeto_from_into_static_str_and_as_str_partition_the_emit_set`]
1634 // (c189a6f),
1635 // [`caixa_core::aplicacao::tests::placement_strategy_from_into_static_str_and_as_str_partition_the_emit_set`]
1636 // (afa3562),
1637 // [`caixa_core::aplicacao::tests::wit_shape_from_into_static_str_and_as_str_partition_the_emit_set`]
1638 // (56998ec),
1639 // [`caixa_core::aplicacao::tests::rate_limit_unit_from_into_static_str_and_as_suffix_partition_the_emit_set`]
1640 // (7fdfbf4),
1641 // [`caixa_core::render::tests::path_shape_violation_from_into_static_str_and_as_str_partition_the_emit_set`]
1642 // (070a6de),
1643 // `caixa_arch::invariants::tests::invariant_kind_from_into_static_str_and_as_str_partition_the_emit_set`
1644 // (f2ca7bc),
1645 // `caixa_arch::report::tests::arch_verdict_from_into_static_str_and_as_str_partition_the_emit_set`
1646 // (d4559cb),
1647 // `caixa_lint::diagnostic::tests::severity_from_into_static_str_and_as_str_partition_the_emit_set`
1648 // (5cc3b8b), and
1649 // `caixa_lint::diagnostic::tests::fix_safety_from_into_static_str_and_as_str_partition_the_emit_set`
1650 // (2a56127) — extends the round-trip discipline onto the first
1651 // closed-set fieldless typed enum on the caixa-theme surface,
1652 // closing the two-way `Self ↔ &'static str` round-trip on the
1653 // trait-idiomatic pair (`From<Self> for &'static str` +
1654 // `TryFrom<&str> for Self`) as well as the pre-existing method-
1655 // named pair (`as_str` + `from_wire`).
1656 for &variant in Semantic::ALL {
1657 let via_trait: &'static str = <&'static str as From<Semantic>>::from(variant);
1658 let via_method: &'static str = variant.as_str();
1659 assert_eq!(
1660 via_trait, via_method,
1661 "From<Semantic> for &'static str and Semantic::as_str \
1662 must resolve identically on Semantic::{variant:?} — \
1663 divergence signals the two forward-projection paths \
1664 have drifted onto different emit-sets"
1665 );
1666 }
1667 // Round-trip witness: every arm's forward `From` output re-parses
1668 // through the paired trait-idiomatic `TryFrom<&str>` back to the
1669 // original variant. Closes the two-way `Semantic ↔ &'static str`
1670 // round-trip on the trait-idiomatic axis pair directly (no wire-
1671 // vocab intermediate — the emit-side [`super::Semantic::as_str`]
1672 // and the parse-side [`super::Semantic::from_wire`] dispatch on
1673 // the same 16 inline canonical-lowercase kebab byte-strings by
1674 // construction, so round-tripping through the paired
1675 // `From<Self> for &'static str` + `TryFrom<&str> for Self` trait
1676 // impls composes to the identity on `Semantic::ALL`).
1677 for &variant in Semantic::ALL {
1678 let emitted: &'static str = <&'static str as From<Semantic>>::from(variant);
1679 let reparsed = <Semantic as TryFrom<&str>>::try_from(emitted).unwrap_or_else(|()| {
1680 panic!(
1681 "TryFrom<&str> for Semantic must accept every \
1682 From<Semantic> for &'static str output — got \
1683 Err(()) for Semantic::{variant:?}'s emit \
1684 byte-string {emitted:?}"
1685 )
1686 });
1687 assert_eq!(
1688 reparsed, variant,
1689 "trait-idiomatic Semantic ↔ &'static str round-trip \
1690 must be the identity on Semantic::{variant:?} — the \
1691 From<Self> for &'static str + TryFrom<&str> for Self \
1692 pair must compose to the identity on the closed 16-arm \
1693 accept-set"
1694 );
1695 }
1696 }
1697
1698 #[test]
1699 fn semantic_from_borrowed_into_static_str_routes_through_as_str_accessor() {
1700 // Fail-before-pass-after byte-parity pin on the newly lifted
1701 // `impl From<&Semantic> for &'static str` — asserts the
1702 // borrowed-input standard-library trait impl and the substrate-
1703 // primitive [`super::Semantic::as_str`] `pub const fn` accessor
1704 // resolve to the same 16-arm canonical-lowercase kebab emit-set
1705 // across every arm the exhaustive [`super::Semantic::ALL`]
1706 // slice enumerates. Rust's `From` trait does not auto-derive
1707 // the borrowed-input sibling from a paired owned-input impl
1708 // (no `impl<T, U> From<&T> for U where T: Copy, U: From<T>`
1709 // blanket in `core`), so the borrowed-input axis is a distinct
1710 // trait-idiomatic surface that a `.iter().map(Into::into)`
1711 // shape over [`super::Semantic::ALL`] (whose iterator yields
1712 // `&Semantic`, not `Semantic`) reaches through this impl and
1713 // no other — the paired owned-input [`From<Semantic>`] impl
1714 // requires an explicit `.copied()` / dereference before the
1715 // trait fires. Materializes three
1716 // `<&'static str as From<&Semantic>>::from` outputs in
1717 // `const`-shape bindings against the paired
1718 // [`super::Semantic::as_str`] `pub const fn` accessor to make
1719 // the `'static` lifetime promise a build-time invariant — a
1720 // future accidental downgrade of any arm's inline canonical-
1721 // lowercase kebab byte-string to a non-`&'static str` (a
1722 // `String::leak()`-produced return, a `Box::leak`-cast, an
1723 // intermediate lifetime-erasing helper) trips at caixa-theme
1724 // build time rather than at a downstream `'static`-bound
1725 // consumer.
1726 //
1727 // Peer of the sibling
1728 // `caixa_provedor::ferrite::tests::ferrite_runtime_from_borrowed_into_static_str_routes_through_variant_slug_accessor`
1729 // (676d693) pin on the outside-`caixa-core` closed-set-enum
1730 // borrowed-input axis — extends the trait-idiomatic borrowed-
1731 // input forward-projection axis onto the last remaining
1732 // closed-set fieldless typed enum on the substrate surface
1733 // (the caixa-theme semantic-style 16-arm axis), closing the
1734 // substrate-wide 2×2-completion campaign's borrowed-input
1735 // `&'static str`-returning corner.
1736 const KEYWORD: &str = Semantic::Keyword.as_str();
1737 const KEYWORD_ARG: &str = Semantic::KeywordArg.as_str();
1738 const UNCHANGED: &str = Semantic::Unchanged.as_str();
1739 for variant in Semantic::ALL {
1740 let via_trait: &'static str = <&'static str as From<&Semantic>>::from(variant);
1741 let via_method: &'static str = variant.as_str();
1742 assert_eq!(
1743 via_trait, via_method,
1744 "From<&Semantic> for &'static str impl must round-trip \
1745 &Semantic::{variant:?} to the same canonical-lowercase \
1746 kebab byte-string Semantic::as_str returns — divergence \
1747 signals a silent detour off the substrate-primitive \
1748 accessor"
1749 );
1750 let via_into: &'static str = variant.into();
1751 assert_eq!(
1752 via_into, via_method,
1753 "Into<&'static str>::into on &Semantic::{variant:?} must \
1754 byte-equal Semantic::as_str on the same input — the \
1755 blanket-derived Into shape on the borrowed-input axis \
1756 must resolve to the same as_str dispatch as the \
1757 explicit From impl"
1758 );
1759 }
1760 assert_eq!(
1761 [KEYWORD, KEYWORD_ARG, UNCHANGED],
1762 ["keyword", "keyword-arg", "unchanged"],
1763 "const-context Semantic::as_str must resolve to the \
1764 canonical-lowercase kebab byte-strings — a future \
1765 accidental downgrade of any arm to a non-const or non-\
1766 static byte-string breaks the `&'static str`-lifetime \
1767 promise the paired From<&Semantic> for &'static str impl \
1768 carries by construction"
1769 );
1770 }
1771
1772 #[test]
1773 fn semantic_from_owned_and_borrowed_into_static_str_agree_on_every_arm() {
1774 // Cross-axis partition pin: the paired trait-idiomatic
1775 // `From<Semantic> for &'static str` owned-input forward
1776 // projection and the newly lifted
1777 // `From<&Semantic> for &'static str` borrowed-input forward
1778 // projection must resolve identically on *every* arm the
1779 // exhaustive [`super::Semantic::ALL`] slice enumerates. Locks
1780 // the two trait-idiomatic forward-projection paths together by
1781 // construction so any future detour (a stray borrowed-input
1782 // `From` special-case that lands on a divergent per-arm literal
1783 // outside the paired `as_str` dispatch, a hypothetical rebrand
1784 // touching one axis without the other) trips at caixa-theme
1785 // test time under `assert_eq!` rather than at a downstream
1786 // consumer split. Witnesses the borrowed-input axis with a
1787 // `.iter().map(Into::into)` pipe over `Semantic::ALL` (whose
1788 // iterator yields `&Semantic`, not `Semantic`, so the pipe
1789 // fires through the borrowed-input axis alone).
1790 //
1791 // Peer of the sibling
1792 // `caixa_provedor::ferrite::tests::ferrite_runtime_from_owned_and_borrowed_into_static_str_agree_on_every_arm`
1793 // (676d693) — extends the owned/borrowed-cross-axis partition
1794 // discipline onto the last remaining substrate-wide closed-set
1795 // fieldless typed enum whose borrowed-input axis was still
1796 // open.
1797 for &variant in Semantic::ALL {
1798 let via_owned: &'static str = <&'static str as From<Semantic>>::from(variant);
1799 let via_borrowed: &'static str = <&'static str as From<&Semantic>>::from(&variant);
1800 assert_eq!(
1801 via_owned, via_borrowed,
1802 "From<Semantic> for &'static str and From<&Semantic> \
1803 for &'static str must agree on Semantic::{variant:?} \
1804 — divergence signals the owned-input and borrowed-\
1805 input forward-projection paths have drifted onto \
1806 different emit-sets"
1807 );
1808 }
1809 let via_pipe: Vec<&'static str> = Semantic::ALL.iter().map(Into::into).collect();
1810 let via_method: Vec<&'static str> = Semantic::ALL.iter().map(|s| s.as_str()).collect();
1811 assert_eq!(
1812 via_pipe, via_method,
1813 "Semantic::ALL.iter().map(Into::into) must resolve to the \
1814 same per-arm canonical-lowercase kebab byte-string \
1815 sequence Semantic::as_str returns across every arm — the \
1816 iterator yields &Semantic, so this pipe fires through the \
1817 borrowed-input From<&Semantic> for &'static str axis and \
1818 witnesses the newly lifted impl's arm-set matches the \
1819 substrate-primitive accessor without a spurious Copy deref"
1820 );
1821 }
1822
1823 #[test]
1824 fn semantic_from_into_owned_string_routes_through_as_str_accessor() {
1825 // Fail-before-pass-after byte-parity pin on the newly lifted
1826 // `impl From<Semantic> for String` — asserts the owned-
1827 // `String`-returning standard-library trait impl and the
1828 // substrate-primitive [`super::Semantic::as_str`] `pub const
1829 // fn` accessor resolve to the same 16-arm canonical-lowercase
1830 // kebab emit-set across every arm the exhaustive
1831 // [`super::Semantic::ALL`] slice enumerates. Rust's standard
1832 // library does not carry a blanket
1833 // `impl<T: AsRef<str>> From<T> for String`, so the owned-
1834 // `String` axis is a distinct trait-idiomatic surface that a
1835 // `let key: String = sem.into();`-shaped downstream call site
1836 // reaches through this impl and no other — the sibling
1837 // `&'static str`-returning axes force an explicit
1838 // `.to_owned()` / [`String::from`] restatement whose type
1839 // bounds have no compile-time link to the substrate primitive.
1840 // Sweeps every one of the 16 arms
1841 // [`super::Semantic::ALL`] carries so no arm's projection is
1842 // covered only by the sibling method-named `as_str` /
1843 // [`std::fmt::Display`] / [`AsRef<str>`] / owned-input
1844 // `&'static str`-returning paths.
1845 //
1846 // Peer of the sibling
1847 // `caixa_provedor::ferrite::tests::ferrite_runtime_from_into_owned_string_routes_through_variant_slug_accessor`
1848 // (1e14fde) and
1849 // `caixa_arch::report::tests::arch_verdict_from_into_owned_string_routes_through_as_str_accessor`
1850 // (cc80a53) pins on the peer outside-`caixa-core` closed-set-
1851 // enum owned-`String`-returning axes — extends the trait-
1852 // idiomatic owned-`String`-returning forward-projection family
1853 // onto the sole closed-set fieldless typed enum on the caixa-
1854 // theme surface (the semantic-style 16-arm axis), extending
1855 // the substrate-wide 2×2-completion campaign onto the sixth
1856 // outside-`caixa-core` closed-set fieldless typed enum on the
1857 // caixa surface.
1858 for &variant in Semantic::ALL {
1859 let via_trait: String = <String as From<Semantic>>::from(variant);
1860 let via_method: &'static str = variant.as_str();
1861 assert_eq!(
1862 via_trait.as_str(),
1863 via_method,
1864 "From<Semantic> for String impl must round-trip \
1865 Semantic::{variant:?} to the same canonical-lowercase \
1866 kebab byte-string Semantic::as_str returns — \
1867 divergence signals a silent detour off the substrate-\
1868 primitive accessor"
1869 );
1870 let via_into: String = variant.into();
1871 assert_eq!(
1872 via_into.as_str(),
1873 via_method,
1874 "Into<String>::into on Semantic::{variant:?} must \
1875 byte-equal Semantic::as_str on the same input — the \
1876 blanket-derived Into shape must resolve to the same \
1877 as_str dispatch as the explicit From impl"
1878 );
1879 }
1880 }
1881
1882 #[test]
1883 fn semantic_from_into_owned_string_and_static_str_agree_on_every_arm() {
1884 // Cross-axis partition pin: the paired trait-idiomatic
1885 // owned-input `&'static str`-returning
1886 // `From<Semantic> for &'static str` and owned-`String`-
1887 // returning `From<Semantic> for String` (this lift) forward
1888 // projections must resolve identically on every arm, locking
1889 // the two output-shape paths together so any future detour (a
1890 // stray owned-`String` special-case that lands on a divergent
1891 // per-arm literal outside the paired `as_str` dispatch, a
1892 // hypothetical rebrand touching one axis without the other, a
1893 // silent swap onto a hand-rolled per-arm literal that shadows
1894 // the paired [`super::Semantic::as_str`] dispatch) trips at
1895 // caixa-theme test time. Then a witness that the
1896 // `ToString::to_string`-through-[`std::fmt::Display`] surface
1897 // (`variant.to_string()`) byte-equals the trait-idiomatic
1898 // owned-`String` axis (`String::from(variant)`) on every arm,
1899 // so a future consumer that reaches for `.to_string()` and
1900 // one that reaches for `.into::<String>()` land on the same
1901 // substrate-primitive vocabulary. Plus a
1902 // `.iter().copied().map(String::from)` pipe witness over
1903 // [`super::Semantic::ALL`] — the exact shape a future per-
1904 // Semantic histogram key materializer or `caixa-lsp` per-
1905 // `SemanticTokenType` registration walk reaches through —
1906 // materializes the 16-arm accept-set through the owned-
1907 // `String` axis alone. Plus a direct `Self → String → Self`
1908 // round-trip witness through the paired [`TryFrom<&str>`]
1909 // axis on the owned-`String`'s [`String::as_str`] borrow,
1910 // closing the two-way round-trip on the owned-`String` axis
1911 // directly (no wire-vocab intermediate — the emit-side
1912 // [`super::Semantic::as_str`] and the parse-side
1913 // [`super::Semantic::from_wire`] dispatch on the same 16
1914 // inline canonical-lowercase kebab byte-strings by
1915 // construction).
1916 //
1917 // Peer of the sibling
1918 // `caixa_provedor::ferrite::tests::ferrite_runtime_from_into_owned_string_and_static_str_agree_on_every_arm`
1919 // (1e14fde) partition pin on the peer outside-`caixa-core`
1920 // closed-set-enum owned-`String`-returning axis.
1921 for &variant in Semantic::ALL {
1922 let owned_string: String = <String as From<Semantic>>::from(variant);
1923 let owned_static: &'static str = <&'static str as From<Semantic>>::from(variant);
1924 assert_eq!(
1925 owned_string.as_str(),
1926 owned_static,
1927 "From<Semantic> for String and From<Semantic> for \
1928 &'static str must resolve identically on \
1929 Semantic::{variant:?} — divergence signals the two \
1930 output-shape forward-projection paths have drifted \
1931 onto different emit-sets"
1932 );
1933 let via_display: String = variant.to_string();
1934 assert_eq!(
1935 owned_string, via_display,
1936 "From<Semantic> for String and ToString::to_string \
1937 via Display must resolve identically on \
1938 Semantic::{variant:?} — divergence signals the \
1939 trait-idiomatic owned-`String` axis and the Display-\
1940 routed ToString axis have drifted onto different \
1941 vocabularies"
1942 );
1943 }
1944 let via_iter: Vec<String> = Semantic::ALL.iter().copied().map(String::from).collect();
1945 let via_method: Vec<String> = Semantic::ALL
1946 .iter()
1947 .map(|s| s.as_str().to_owned())
1948 .collect();
1949 assert_eq!(
1950 via_iter, via_method,
1951 "`.iter().copied().map(String::from)` over Semantic::ALL \
1952 must byte-equal `.iter().map(|s| s.as_str().to_owned())` \
1953 on every arm — the owned-`String` `From<Semantic> for \
1954 String` axis is what makes the `.map(String::from)` \
1955 shape route through the substrate-primitive \
1956 Semantic::as_str accessor rather than through a per-\
1957 call-site `.to_owned()` / `String::from(sem.as_str())` \
1958 detour"
1959 );
1960 for &variant in Semantic::ALL {
1961 let emitted: String = variant.into();
1962 let re_parsed: Result<Semantic, ()> =
1963 <Semantic as TryFrom<&str>>::try_from(emitted.as_str());
1964 assert_eq!(
1965 re_parsed,
1966 Ok(variant),
1967 "trait-idiomatic owned-`String` axis pair must round-\
1968 trip Semantic::{variant:?} through \
1969 `.into::<String>()` and back through `TryFrom<&str>` \
1970 on the owned-`String`'s `String::as_str` borrow — a \
1971 break signals the forward-emit owned-`String` axis \
1972 and the reverse-parse `TryFrom<&str>` axis have \
1973 drifted onto different vocabularies"
1974 );
1975 }
1976 }
1977
1978 #[test]
1979 fn semantic_from_borrowed_into_owned_string_routes_through_as_str_accessor() {
1980 // Fail-before-pass-after byte-parity pin on the newly lifted
1981 // `impl From<&Semantic> for String` — asserts the borrowed-
1982 // input owned-`String`-returning standard-library trait impl
1983 // and the substrate-primitive [`super::Semantic::as_str`]
1984 // `pub const fn` accessor resolve to the same 16-arm
1985 // canonical-lowercase kebab emit-set across every arm the
1986 // exhaustive [`super::Semantic::ALL`] slice enumerates.
1987 // Rust's standard library does not carry a blanket
1988 // `impl<T: AsRef<str>> From<&T> for String` (nor an
1989 // `impl<T: fmt::Display> From<&T> for String`), so the
1990 // borrowed-input owned-`String` forward-projection axis is a
1991 // distinct trait-idiomatic surface that a
1992 // `let key: String = (&sem).into();`-shaped call site
1993 // reaches through this impl and no other — the paired
1994 // sibling `From<Semantic> for String` impl (5ea146c) forces
1995 // every borrowed-input call site through an explicit `Copy`
1996 // deref (`String::from(*sem)`) or a `.as_str().to_owned()` /
1997 // `.to_string()` detour whose type bounds have no compile-
1998 // time link to the substrate primitive. Sweeps every one of
1999 // the 16 arms [`super::Semantic::ALL`] carries so no arm's
2000 // borrowed-input owned-`String` projection is covered only
2001 // by the sibling method-named `as_str` / [`std::fmt::Display`]
2002 // / [`AsRef<str>`] / owned-input `&'static str`-returning /
2003 // owned-input owned-`String`-returning paths.
2004 //
2005 // Peer of the sibling
2006 // `caixa_provedor::ferrite::tests::ferrite_runtime_from_borrowed_into_owned_string_routes_through_variant_slug_accessor`
2007 // (0caedec — fifth outside-`caixa-core` arm on this axis,
2008 // the paired ferrite-runtime two-arm axis on the sole caixa-
2009 // provedor closed-set enum) and
2010 // `caixa_lint::diagnostic::tests::fix_safety_from_borrowed_into_owned_string_routes_through_as_str_accessor`
2011 // (807f67d — fourth outside-`caixa-core` arm on this axis)
2012 // pins on the peer outside-`caixa-core` closed-set-enum
2013 // borrowed-input owned-`String`-returning axes — closes the
2014 // whole `{Self, &Self} × {&'static str, String}` 2×2 trait-
2015 // idiomatic projection corner on the sixth-and-last outside-
2016 // `caixa-core` closed-set fieldless typed enum on the caixa
2017 // surface (the caixa-theme semantic-style 16-arm axis every
2018 // per-Semantic paint dispatch, every future `caixa-lsp` per-
2019 // `SemanticTokenType` wire-up, every future `caixa.nvim`
2020 // per-highlight-group re-loader, and every future
2021 // `blackmatter-shell` per-arm `data-semantic="<kebab>"` DOM
2022 // emission keys off), and closes the substrate-wide 2×2-
2023 // completion campaign across every closed-set fieldless
2024 // typed enum on the caixa surface.
2025 for &variant in Semantic::ALL {
2026 let via_trait: String = <String as From<&Semantic>>::from(&variant);
2027 let via_method: &'static str = variant.as_str();
2028 assert_eq!(
2029 via_trait.as_str(),
2030 via_method,
2031 "From<&Semantic> for String impl must round-trip \
2032 &Semantic::{variant:?} to the same canonical-\
2033 lowercase kebab byte-string Semantic::as_str \
2034 returns — divergence signals a silent detour off \
2035 the substrate-primitive accessor"
2036 );
2037 let via_into: String = (&variant).into();
2038 assert_eq!(
2039 via_into.as_str(),
2040 via_method,
2041 "Into<String>::into on &Semantic::{variant:?} must \
2042 byte-equal Semantic::as_str on the same input — \
2043 the blanket-derived Into shape must resolve to the \
2044 same as_str dispatch as the explicit From impl"
2045 );
2046 }
2047 }
2048
2049 #[test]
2050 fn semantic_from_borrowed_into_owned_string_agrees_with_paired_axes_on_every_arm() {
2051 // Cross-axis partition pin: the newly lifted trait-
2052 // idiomatic borrowed-input owned-`String`
2053 // `From<&Semantic> for String` (this lift), the paired
2054 // owned-input owned-`String` `From<Semantic> for String`
2055 // (5ea146c), the paired borrowed-input owned-`&'static str`
2056 // `From<&Semantic> for &'static str` (ffc0f26), and the
2057 // paired owned-input owned-`&'static str`
2058 // `From<Semantic> for &'static str` — every corner of the
2059 // `{Self, &Self} × {&'static str, String}` 2×2 trait-
2060 // idiomatic projection family — must resolve identically on
2061 // every arm, locking the four return-shape × input-shape
2062 // paths together so any future detour trips at caixa-theme
2063 // test time. Also byte-parity witness against the sibling
2064 // [`ToString::to_string`] surface routed through
2065 // [`std::fmt::Display`] and a direct round-trip witness
2066 // through the paired trait-idiomatic reverse
2067 // [`TryFrom<&str>`] axis on the owned-`String`'s
2068 // [`String::as_str`] borrow that closes the two-way
2069 // `&Self → String → Self` round-trip on the trait-idiomatic
2070 // borrowed-input owned-`String` forward + reverse axis pair.
2071 //
2072 // The `.iter().map(String::from)` pipe witness over
2073 // [`super::Semantic::ALL`] materializes the exact shape a
2074 // future per-Semantic histogram key materializer or
2075 // `caixa-lsp` per-`SemanticTokenType` registration walk
2076 // reaches through — [`super::Semantic::ALL`]'s iterator
2077 // yields `&Semantic` by construction, so the borrowed-input
2078 // owned-`String` axis is what routes the pipe through the
2079 // substrate-primitive [`super::Semantic::as_str`] accessor
2080 // without a spurious `.copied()` / `Copy` deref (the paired
2081 // owned-input pipe witness on the sibling
2082 // `semantic_from_into_owned_string_and_static_str_agree_on_every_arm`
2083 // uses `.iter().copied().map(String::from)` for exactly this
2084 // reason — the owned-input axis alone cannot route the pipe
2085 // through the substrate primitive without the extra deref).
2086 //
2087 // Peer of the sibling
2088 // `caixa_provedor::ferrite::tests::ferrite_runtime_from_borrowed_into_owned_string_agrees_with_paired_axes_on_every_arm`
2089 // (0caedec — fifth outside-`caixa-core` arm on this axis)
2090 // partition pin on the peer outside-`caixa-core` closed-
2091 // set-enum borrowed-input owned-`String` axis — closes the
2092 // substrate-wide 2×2-completion campaign on the sixth-and-
2093 // last outside-`caixa-core` closed-set fieldless typed enum
2094 // on the caixa surface.
2095 for &variant in Semantic::ALL {
2096 let borrowed_string: String = <String as From<&Semantic>>::from(&variant);
2097 let owned_string: String = <String as From<Semantic>>::from(variant);
2098 let borrowed_static: &'static str = <&'static str as From<&Semantic>>::from(&variant);
2099 let owned_static: &'static str = <&'static str as From<Semantic>>::from(variant);
2100 assert_eq!(
2101 borrowed_string, owned_string,
2102 "From<&Semantic> for String and From<Semantic> for \
2103 String must resolve identically on \
2104 Semantic::{variant:?} — divergence signals the \
2105 owned-`String` axis pair's borrowed-input and \
2106 owned-input arms have drifted onto different emit-\
2107 sets"
2108 );
2109 assert_eq!(
2110 borrowed_string.as_str(),
2111 borrowed_static,
2112 "From<&Semantic> for String and From<&Semantic> for \
2113 &'static str must resolve identically on \
2114 Semantic::{variant:?} — divergence signals the \
2115 borrowed-input axis pair's owned-`String`-returning \
2116 and `&'static str`-returning arms have drifted \
2117 onto different emit-sets"
2118 );
2119 assert_eq!(
2120 borrowed_string.as_str(),
2121 owned_static,
2122 "From<&Semantic> for String and From<Semantic> for \
2123 &'static str must resolve identically on \
2124 Semantic::{variant:?} — the cross-diagonal corner \
2125 of the 2×2 must agree, or the four projections \
2126 have split into two vocabularies"
2127 );
2128 let via_display: String = variant.to_string();
2129 assert_eq!(
2130 borrowed_string, via_display,
2131 "From<&Semantic> for String and ToString::to_string \
2132 via Display must resolve identically on \
2133 Semantic::{variant:?} — divergence signals the \
2134 trait-idiomatic borrowed-input owned-`String` axis \
2135 and the Display-routed ToString axis have drifted \
2136 onto different vocabularies"
2137 );
2138 }
2139 let via_iter: Vec<String> = Semantic::ALL.iter().map(String::from).collect();
2140 let via_method: Vec<String> = Semantic::ALL
2141 .iter()
2142 .map(|sem| sem.as_str().to_owned())
2143 .collect();
2144 assert_eq!(
2145 via_iter, via_method,
2146 "`.iter().map(String::from)` over Semantic::ALL must \
2147 byte-equal `.iter().map(|sem| sem.as_str().to_owned())` \
2148 on every arm — the borrowed-input owned-`String` \
2149 `From<&Semantic> for String` axis is what makes the \
2150 `.map(String::from)` shape route through the substrate-\
2151 primitive Semantic::as_str accessor without a spurious \
2152 `.copied()` / `Copy` deref"
2153 );
2154 for &variant in Semantic::ALL {
2155 let emitted: String = (&variant).into();
2156 let re_parsed: Result<Semantic, ()> =
2157 <Semantic as TryFrom<&str>>::try_from(emitted.as_str());
2158 assert_eq!(
2159 re_parsed,
2160 Ok(variant),
2161 "trait-idiomatic borrowed-input owned-`String` axis \
2162 pair must round-trip Semantic::{variant:?} through \
2163 `(&variant).into::<String>()` and back through \
2164 `TryFrom<&str>` on the owned-`String`'s \
2165 `String::as_str` borrow — a break signals the \
2166 borrowed-input forward-emit owned-`String` axis \
2167 and the reverse-parse `TryFrom<&str>` axis have \
2168 drifted onto different vocabularies"
2169 );
2170 }
2171 }
2172}