Skip to main content

Mountain/ProcessManagement/
ExtractDevTag.rs

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