Skip to main content

Mountain/ProcessManagement/
ExtractDevTag.rs

1#![allow(non_snake_case)]
2
3//! Cocoon stdout-line inspector. Detects the `[DEV:<TAG>]` prefix written by
4//! `Cocoon/Source/Services/DevLog.ts::CocoonDevLog` and returns the lower-
5//! cased tag for dispatch into Mountain's per-tag `dev_log!` sinks. Returns
6//! `None` for bare stdout so the caller falls back to the catch-all `cocoon`
7//! tag.
8
9pub fn Fn(Line:&str) -> Option<String> {
10	let Stripped = Line.strip_prefix("[DEV:")?;
11	let (TagUpper, _Rest) = Stripped.split_once(']')?;
12	if TagUpper.is_empty() {
13		return None;
14	}
15	// Reject anything that isn't a simple tag ident - prevents stray
16	// `[DEV: something with space]` headers from being treated as tags.
17	if !TagUpper.chars().all(|C| C.is_ascii_uppercase() || C == '-' || C == '_') {
18		return None;
19	}
20	Some(TagUpper.to_ascii_lowercase())
21}
22
23#[cfg(test)]
24mod Tests {
25	use super::Fn;
26
27	#[test]
28	fn StripsKnownTag() {
29		assert_eq!(
30			Fn("[DEV:BOOTSTRAP-STAGE] [Bootstrap] stage=Environment event=start"),
31			Some("bootstrap-stage".to_string())
32		);
33	}
34
35	#[test]
36	fn RejectsPlainText() {
37		assert_eq!(Fn("plain stdout line"), None);
38	}
39
40	#[test]
41	fn RejectsMalformed() {
42		assert_eq!(Fn("[DEV: BOOT] x"), None);
43		assert_eq!(Fn("[DEV:]"), None);
44		assert_eq!(Fn("[DEV:BOOT"), None);
45	}
46}