From dce37d29cb6c2fa9fe408b89e907d19994d68716 Mon Sep 17 00:00:00 2001 From: adityamehra Date: Thu, 16 Jul 2026 13:41:06 -0700 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20rename=20GalileoSpan=20?= =?UTF-8?q?=E2=86=92=20SplunkAOSpan,=20galileo=5Fspan=20=E2=86=92=20splunk?= =?UTF-8?q?=5Fao=5Fspan,=20galileo-otel=20=E2=86=92=20splunk-ao-otel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove remaining Galileo branding from the OTel integration layer: - Import alias: `Span as GalileoSpan` → `Span as SplunkAOSpan` - Parameter/variable names: `galileo_span` → `splunk_ao_span` across otel.py, handler.py, and utils - gen_ai.system attribute value: `"galileo-otel"` → `"splunk-ao-otel"` - Test class/method names updated to match - Examples updated: start_galileo_span → start_splunk_ao_span, galileo_span_processor → splunk_ao_span_processor Co-authored-by: Cursor --- examples/agent/google-adk/my_agent/agent.py | 4 +- .../agent/langgraph-open-telemetry/main.py | 4 +- .../python-service/app.py | 4 +- .../handlers/openai_agents/handler.py | 4 +- src/splunk_ao/otel.py | 58 +++++++++---------- src/splunk_ao/utils/openai_agents.py | 4 +- tests/test_openai_agents_utils.py | 4 +- tests/test_otel.py | 8 +-- 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/examples/agent/google-adk/my_agent/agent.py b/examples/agent/google-adk/my_agent/agent.py index 438418cd..414cb38e 100644 --- a/examples/agent/google-adk/my_agent/agent.py +++ b/examples/agent/google-adk/my_agent/agent.py @@ -10,8 +10,8 @@ # Create tracer provider and register Splunk AO span processor tracer_provider = trace_sdk.TracerProvider() -galileo_span_processor = otel.SplunkAOSpanProcessor() -tracer_provider.add_span_processor(galileo_span_processor) +splunk_ao_span_processor = otel.SplunkAOSpanProcessor() +tracer_provider.add_span_processor(splunk_ao_span_processor) # Instrument Google ADK with OpenInference (this captures inputs/outputs) GoogleADKInstrumentor().instrument(tracer_provider=tracer_provider) diff --git a/examples/agent/langgraph-open-telemetry/main.py b/examples/agent/langgraph-open-telemetry/main.py index 6d006482..f5ccdfb3 100644 --- a/examples/agent/langgraph-open-telemetry/main.py +++ b/examples/agent/langgraph-open-telemetry/main.py @@ -26,7 +26,7 @@ client = openai.OpenAI(api_key=openai_api_key) print("✓ OpenAI client configured") -galileo_span_processor = otel.SplunkAOSpanProcessor() +splunk_ao_span_processor = otel.SplunkAOSpanProcessor() resource = Resource.create( @@ -40,7 +40,7 @@ # Add a span processor that sends traces to Splunk AO -otel.add_splunk_ao_span_processor(tracer_provider, galileo_span_processor) +otel.add_splunk_ao_span_processor(tracer_provider, splunk_ao_span_processor) # OPTIONAL: Console output disabled to reduce noise in Splunk AO # Uncomment the next 3 lines if you want local console debugging: diff --git a/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py b/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py index bad8a4ba..8e51fcff 100644 --- a/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py +++ b/examples/logging-samples/distributed-tracing-otel-python-java/python-service/app.py @@ -6,7 +6,7 @@ import chromadb.utils.embedding_functions as ef import openai from fastapi import FastAPI -from splunk_ao.otel import start_galileo_span +from splunk_ao.otel import start_splunk_ao_span from splunk_ao_core.schemas.logging.span import RetrieverSpan from splunk_ao_core.schemas.shared.document import Document from langgraph.graph import END, START, StateGraph @@ -110,7 +110,7 @@ def retrieve_documents(state: GraphState) -> GraphState: query = state["question"] retriever_span = RetrieverSpan(name="chromadb_search", input=query) - with start_galileo_span(retriever_span) as span: + with start_splunk_ao_span(retriever_span) as span: try: collection = chroma.get_collection(CHROMA_COLLECTION, embedding_function=embedding_fn) results = collection.query(query_texts=[query], n_results=3) diff --git a/src/splunk_ao/handlers/openai_agents/handler.py b/src/splunk_ao/handlers/openai_agents/handler.py index e34a8032..e82b25ea 100644 --- a/src/splunk_ao/handlers/openai_agents/handler.py +++ b/src/splunk_ao/handlers/openai_agents/handler.py @@ -7,7 +7,7 @@ from agents.tracing import ResponseSpanData, get_current_span, get_trace_provider from galileo_core.schemas.logging.span import LlmMetrics, LlmSpan -from galileo_core.schemas.logging.span import Span as GalileoSpan +from galileo_core.schemas.logging.span import Span as SplunkAOSpan from splunk_ao import SplunkAOLogger, splunk_ao_context from splunk_ao.schema.handlers import Node from splunk_ao.utils import _get_timestamp @@ -492,7 +492,7 @@ def _extract_tool_output(self, item_dict: dict[str, Any], item_type: str) -> str return serialize_to_str(item_dict.get("output") or item_dict.get("results")) @staticmethod - def add_splunk_ao_custom_span(span: GalileoSpan) -> Span[SplunkAOCustomSpan]: + def add_splunk_ao_custom_span(span: SplunkAOSpan) -> Span[SplunkAOCustomSpan]: """Add a Galileo custom span to the trace.""" trace_provider = get_trace_provider() current_span = get_current_span() diff --git a/src/splunk_ao/otel.py b/src/splunk_ao/otel.py index f60f32ee..a462873b 100644 --- a/src/splunk_ao/otel.py +++ b/src/splunk_ao/otel.py @@ -10,7 +10,7 @@ from requests import Session from galileo_core.schemas.logging.span import RetrieverSpan, ToolSpan, WorkflowSpan -from galileo_core.schemas.logging.span import Span as GalileoSpan +from galileo_core.schemas.logging.span import Span as SplunkAOSpan from splunk_ao.config import SplunkAOConfig from splunk_ao.decorator import ( _dataset_input_context, @@ -318,32 +318,32 @@ def add_splunk_ao_span_processor(tracer_provider: TracerProvider, processor: Spl _TRACE_PROVIDER_CONTEXT_VAR.set(tracer_provider) -def _set_retriever_span_attributes(span: trace.Span, galileo_span: RetrieverSpan) -> None: +def _set_retriever_span_attributes(span: trace.Span, splunk_ao_span: RetrieverSpan) -> None: span.set_attribute("db.operation", "search") - span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "user", "content": galileo_span.input}])) + span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "user", "content": splunk_ao_span.input}])) span.set_attribute( "gen_ai.output.messages", json.dumps( [ { "role": "assistant", - "content": {"documents": document_adapter.dump_python(galileo_span.output, mode="json")}, + "content": {"documents": document_adapter.dump_python(splunk_ao_span.output, mode="json")}, } ] ), ) -def _set_tool_span_attributes(span: trace.Span, galileo_span: ToolSpan) -> None: +def _set_tool_span_attributes(span: trace.Span, splunk_ao_span: ToolSpan) -> None: span.set_attribute("gen_ai.operation.name", "execute_tool") - span.set_attribute("gen_ai.tool.name", galileo_span.name) - span.set_attribute("gen_ai.tool.call.arguments", galileo_span.input) - span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "tool", "content": galileo_span.input}])) - if galileo_span.output is not None: - span.set_attribute("gen_ai.tool.call.result", galileo_span.output) - span.set_attribute("gen_ai.output.messages", json.dumps([{"role": "tool", "content": galileo_span.output}])) - if galileo_span.tool_call_id is not None: - span.set_attribute("gen_ai.tool.call.id", galileo_span.tool_call_id) + span.set_attribute("gen_ai.tool.name", splunk_ao_span.name) + span.set_attribute("gen_ai.tool.call.arguments", splunk_ao_span.input) + span.set_attribute("gen_ai.input.messages", json.dumps([{"role": "tool", "content": splunk_ao_span.input}])) + if splunk_ao_span.output is not None: + span.set_attribute("gen_ai.tool.call.result", splunk_ao_span.output) + span.set_attribute("gen_ai.output.messages", json.dumps([{"role": "tool", "content": splunk_ao_span.output}])) + if splunk_ao_span.tool_call_id is not None: + span.set_attribute("gen_ai.tool.call.id", splunk_ao_span.tool_call_id) def _apply_dataset_attributes( @@ -358,15 +358,15 @@ def _apply_dataset_attributes( span.set_attribute("splunk_ao.dataset.metadata", json.dumps(dataset_metadata)) -def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) -> None: +def _set_workflow_span_attributes(span: trace.Span, splunk_ao_span: WorkflowSpan) -> None: """Set OpenTelemetry attributes for WorkflowSpan.""" # Handle input - Union[str, Sequence[Message]] - if isinstance(galileo_span.input, str): - input_messages = [{"role": "user", "content": galileo_span.input}] + if isinstance(splunk_ao_span.input, str): + input_messages = [{"role": "user", "content": splunk_ao_span.input}] else: # Sequence[Message] - serialize each message input_messages = [] - for msg in list(galileo_span.input): + for msg in list(splunk_ao_span.input): if hasattr(msg, "model_dump"): input_messages.append(msg.model_dump(exclude_none=True)) else: @@ -374,10 +374,10 @@ def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) span.set_attribute("gen_ai.input.messages", json.dumps(input_messages)) # Handle output - Union[str, Message, Sequence[Document], None] - if galileo_span.output is None: + if splunk_ao_span.output is None: return - output_value = galileo_span.output + output_value = splunk_ao_span.output # Type annotation to handle flexible content types (string or dict) # Content can be: str (simple output), dict (documents), or dict (Message model_dump) output_messages: list[dict[str, Any]] = [] @@ -401,22 +401,22 @@ def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) @contextmanager -def start_splunk_ao_span(galileo_span: GalileoSpan) -> Generator[trace.Span, Any, None]: +def start_splunk_ao_span(splunk_ao_span: SplunkAOSpan) -> Generator[trace.Span, Any, None]: tracer_provider = _TRACE_PROVIDER_CONTEXT_VAR.get() if tracer_provider is None: tracer_provider = trace.get_tracer_provider() _TRACE_PROVIDER_CONTEXT_VAR.set(cast(TracerProvider, tracer_provider)) tracer = tracer_provider.get_tracer("galileo-tracer") - with tracer.start_as_current_span(galileo_span.name) as span: + with tracer.start_as_current_span(splunk_ao_span.name) as span: yield span - span.set_attribute("gen_ai.system", "galileo-otel") + span.set_attribute("gen_ai.system", "splunk-ao-otel") # Set dataset attributes for ground truth/reference output support _apply_dataset_attributes( - span, galileo_span.dataset_input, galileo_span.dataset_output, galileo_span.dataset_metadata + span, splunk_ao_span.dataset_input, splunk_ao_span.dataset_output, splunk_ao_span.dataset_metadata ) - if isinstance(galileo_span, RetrieverSpan): - _set_retriever_span_attributes(span, galileo_span) - elif isinstance(galileo_span, ToolSpan): - _set_tool_span_attributes(span, galileo_span) - elif isinstance(galileo_span, WorkflowSpan): - _set_workflow_span_attributes(span, galileo_span) + if isinstance(splunk_ao_span, RetrieverSpan): + _set_retriever_span_attributes(span, splunk_ao_span) + elif isinstance(splunk_ao_span, ToolSpan): + _set_tool_span_attributes(span, splunk_ao_span) + elif isinstance(splunk_ao_span, WorkflowSpan): + _set_workflow_span_attributes(span, splunk_ao_span) diff --git a/src/splunk_ao/utils/openai_agents.py b/src/splunk_ao/utils/openai_agents.py index be6d4c8e..32373aa8 100644 --- a/src/splunk_ao/utils/openai_agents.py +++ b/src/splunk_ao/utils/openai_agents.py @@ -13,7 +13,7 @@ ) from agents.tracing import ResponseSpanData -from galileo_core.schemas.logging.span import Span as GalileoSpan +from galileo_core.schemas.logging.span import Span as SplunkAOSpan from splunk_ao.schema.handlers import SPAN_TYPE from splunk_ao.utils.serialization import serialize_to_str @@ -21,7 +21,7 @@ class SplunkAOCustomSpan(CustomSpanData): - def __init__(self, span: GalileoSpan, data: dict[str, Any]): + def __init__(self, span: SplunkAOSpan, data: dict[str, Any]): self.span = span super().__init__(span.name, data) diff --git a/tests/test_openai_agents_utils.py b/tests/test_openai_agents_utils.py index 69b1bdc0..3e16b8b2 100644 --- a/tests/test_openai_agents_utils.py +++ b/tests/test_openai_agents_utils.py @@ -298,8 +298,8 @@ def test_span_data_types(self, span_data: Any, expected_type: str) -> None: def test_galileo_custom_span(self) -> None: """Test mapping SplunkAOCustomSpan.""" - galileo_span = WorkflowSpan(name="Test", input="input", output="output", status_code=200) - assert _map_span_type(SplunkAOCustomSpan(galileo_span, {})) == "splunk_ao_custom" + splunk_ao_span = WorkflowSpan(name="Test", input="input", output="output", status_code=200) + assert _map_span_type(SplunkAOCustomSpan(splunk_ao_span, {})) == "splunk_ao_custom" @pytest.mark.parametrize( "type_attr,expected_type", [("function", "tool"), ("generation", "llm"), ("agent", "workflow")] diff --git a/tests/test_otel.py b/tests/test_otel.py index a4cae49e..140bed51 100644 --- a/tests/test_otel.py +++ b/tests/test_otel.py @@ -254,7 +254,7 @@ class TestOTelUnavailable: """Test behavior when OpenTelemetry is not available.""" @patch("splunk_ao.otel.OTEL_AVAILABLE", False) - def test_galileo_span_processor_raises_import_error_when_otel_unavailable(self): + def test_splunk_ao_span_processor_raises_import_error_when_otel_unavailable(self): """Test that SplunkAOSpanProcessor raises ImportError when OpenTelemetry is not available.""" with pytest.raises(ImportError, match=re.escape(INSTALL_ERR_MSG)): SplunkAOSpanProcessor(project="test") @@ -569,7 +569,7 @@ def test_tool_span_with_output_no_tool_call_id(self): assert mock_otel_span.set_attribute.call_count == 6 -class TestStartGalileoSpan: +class TestStartSplunkAOSpan: """Test suite for start_splunk_ao_span context manager.""" @pytest.fixture(autouse=True) @@ -604,7 +604,7 @@ def test_start_splunk_ao_span_dispatches_tool_span(self): # Then: the span has gen_ai.system set and tool-specific attributes calls = {args[0]: args[1] for args, _ in mock_otel_span.set_attribute.call_args_list} - assert calls["gen_ai.system"] == "galileo-otel" + assert calls["gen_ai.system"] == "splunk-ao-otel" assert calls["gen_ai.operation.name"] == "execute_tool" assert calls["gen_ai.tool.name"] == "my-tool" assert calls["gen_ai.tool.call.arguments"] == "tool input data" @@ -632,7 +632,7 @@ def test_start_splunk_ao_span_tool_span_with_none_output(self): # Then: gen_ai.system, operation name, tool name, tool arguments, and input are set (no output or tool_call_id) calls = {args[0]: args[1] for args, _ in mock_otel_span.set_attribute.call_args_list} - assert calls["gen_ai.system"] == "galileo-otel" + assert calls["gen_ai.system"] == "splunk-ao-otel" assert calls["gen_ai.operation.name"] == "execute_tool" assert calls["gen_ai.tool.name"] == "minimal-tool" assert calls["gen_ai.tool.call.arguments"] == "just input" From 0a88ca9ff97543d5169a0e56d099be0e547a9e05 Mon Sep 17 00:00:00 2001 From: adityamehra Date: Fri, 17 Jul 2026 11:51:21 -0700 Subject: [PATCH 2/3] refactor: fix remaining Galileo branding in tracer name and docstring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - "galileo-tracer" → "splunk-ao-tracer" (OTel instrumentation scope name) - "Add a Galileo custom span" → "Add a Splunk AO custom span" (docstring) Addresses review comments from fercor-cisco on PR #90. Co-authored-by: Cursor --- src/splunk_ao/handlers/openai_agents/handler.py | 2 +- src/splunk_ao/otel.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/splunk_ao/handlers/openai_agents/handler.py b/src/splunk_ao/handlers/openai_agents/handler.py index e82b25ea..072cea79 100644 --- a/src/splunk_ao/handlers/openai_agents/handler.py +++ b/src/splunk_ao/handlers/openai_agents/handler.py @@ -493,7 +493,7 @@ def _extract_tool_output(self, item_dict: dict[str, Any], item_type: str) -> str @staticmethod def add_splunk_ao_custom_span(span: SplunkAOSpan) -> Span[SplunkAOCustomSpan]: - """Add a Galileo custom span to the trace.""" + """Add a Splunk AO custom span to the trace.""" trace_provider = get_trace_provider() current_span = get_current_span() custom_span = SplunkAOCustomSpan(span, span.user_metadata) diff --git a/src/splunk_ao/otel.py b/src/splunk_ao/otel.py index a462873b..cabe456a 100644 --- a/src/splunk_ao/otel.py +++ b/src/splunk_ao/otel.py @@ -406,7 +406,7 @@ def start_splunk_ao_span(splunk_ao_span: SplunkAOSpan) -> Generator[trace.Span, if tracer_provider is None: tracer_provider = trace.get_tracer_provider() _TRACE_PROVIDER_CONTEXT_VAR.set(cast(TracerProvider, tracer_provider)) - tracer = tracer_provider.get_tracer("galileo-tracer") + tracer = tracer_provider.get_tracer("splunk-ao-tracer") with tracer.start_as_current_span(splunk_ao_span.name) as span: yield span span.set_attribute("gen_ai.system", "splunk-ao-otel") From 320e9a9d515ded80e932abc01eee43ae98f277a0 Mon Sep 17 00:00:00 2001 From: adityamehra Date: Fri, 17 Jul 2026 11:55:21 -0700 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20add=20OTel=20Galileo=20=E2=86=92=20?= =?UTF-8?q?Splunk=20AO=20rename=20guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the changes made in this branch for users who depend on OTel span attributes (gen_ai.system, otel.scope.name) and for internal contributors reviewing the refactor. Covers: instrumentation scope name, gen_ai.system value, import alias, parameter renames, and example variable name updates. Co-authored-by: Cursor --- docs/OTEL_GALILEO_TO_SPLUNK_AO_RENAME.md | 106 +++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 docs/OTEL_GALILEO_TO_SPLUNK_AO_RENAME.md diff --git a/docs/OTEL_GALILEO_TO_SPLUNK_AO_RENAME.md b/docs/OTEL_GALILEO_TO_SPLUNK_AO_RENAME.md new file mode 100644 index 00000000..6cfed0e1 --- /dev/null +++ b/docs/OTEL_GALILEO_TO_SPLUNK_AO_RENAME.md @@ -0,0 +1,106 @@ +# OTel Layer: Galileo → Splunk AO Rename + +**Branch:** `rename/galileo-to-splunk-ao` +**Ticket:** Internal refactor (follow-on to HYBIM-832) + +## Summary + +This change removes the remaining `galileo` branding from the OpenTelemetry integration layer. All `Galileo`-prefixed symbols, variable names, and OTel attribute values in the OTel module have been renamed to their `SplunkAO` / `splunk-ao` equivalents. + +--- + +## What Changed + +### 1. Import alias + +| Before | After | +|--------|-------| +| `from galileo_core.schemas.logging.span import Span as GalileoSpan` | `from galileo_core.schemas.logging.span import Span as SplunkAOSpan` | + +Affected files: +- `src/splunk_ao/otel.py` +- `src/splunk_ao/handlers/openai_agents/handler.py` +- `src/splunk_ao/utils/openai_agents.py` + +### 2. OTel instrumentation scope name + +| Before | After | +|--------|-------| +| `tracer_provider.get_tracer("galileo-tracer")` | `tracer_provider.get_tracer("splunk-ao-tracer")` | + +This is the **OTel instrumentation scope** name. It appears as `otel.scope.name` / `instrumentation.name` in traces exported to any OTel-compatible backend. + +### 3. `gen_ai.system` attribute value + +| Before | After | +|--------|-------| +| `span.set_attribute("gen_ai.system", "galileo-otel")` | `span.set_attribute("gen_ai.system", "splunk-ao-otel")` | + +This attribute is set on every span emitted by `start_splunk_ao_span()`. + +### 4. Internal parameter and variable names + +| Before | After | Location | +|--------|-------|----------| +| `galileo_span` (parameter) | `splunk_ao_span` | `otel.py` — `_set_retriever_span_attributes`, `_set_tool_span_attributes`, `_set_workflow_span_attributes` | +| `galileo_span: GalileoSpan` (parameter) | `splunk_ao_span: SplunkAOSpan` | `otel.py` — `start_splunk_ao_span` | +| `galileo_span: GalileoSpan` (parameter) | `span: SplunkAOSpan` | `handler.py` — `add_splunk_ao_custom_span` | +| `span: GalileoSpan` (parameter) | `span: SplunkAOSpan` | `utils/openai_agents.py` — `SplunkAOCustomSpan.__init__` | + +### 5. Docstring + +| Before | After | +|--------|-------| +| `"""Add a Galileo custom span to the trace."""` | `"""Add a Splunk AO custom span to the trace."""` | + +### 6. Example variable names + +| Before | After | File | +|--------|-------|------| +| `galileo_span_processor` | `splunk_ao_span_processor` | `examples/agent/google-adk/my_agent/agent.py` | +| `galileo_span_processor` | `splunk_ao_span_processor` | `examples/agent/langgraph-open-telemetry/main.py` | +| `start_galileo_span` | `start_splunk_ao_span` | `examples/rag/cli-rag-demo/python-service/app.py` | + +--- + +## Impact on Users + +### Potentially breaking: OTel span attributes + +If you have dashboards, alerts, or queries that filter on `gen_ai.system = "galileo-otel"` or `otel.scope.name = "galileo-tracer"` in your observability backend (Splunk, Datadog, Jaeger, etc.), update those filters: + +| Attribute | Old value | New value | +|-----------|-----------|-----------| +| `gen_ai.system` | `galileo-otel` | `splunk-ao-otel` | +| `otel.scope.name` / `instrumentation.name` | `galileo-tracer` | `splunk-ao-tracer` | + +### Not breaking: Public Python API + +The public functions `start_splunk_ao_span()`, `add_splunk_ao_span_processor()`, `SplunkAOSpanProcessor`, and `SplunkAOCustomSpan` are **unchanged**. Only their internal parameter names changed. + +### Example code updates + +If you copied variable names from the examples (e.g. `galileo_span_processor`), update them to `splunk_ao_span_processor`. These are local variable names with no API contract. + +--- + +## Files Changed + +``` +src/splunk_ao/otel.py +src/splunk_ao/handlers/openai_agents/handler.py +src/splunk_ao/utils/openai_agents.py +examples/agent/google-adk/my_agent/agent.py +examples/agent/langgraph-open-telemetry/main.py +examples/rag/cli-rag-demo/python-service/app.py +tests/test_otel.py +tests/test_openai_agents_utils.py +``` + +--- + +## Related + +- [HYBIM-832](https://splunk.atlassian.net/browse/HYBIM-832) — `SPLUNK_AO_ENV_RENAME.md` removed (superseded migration docs) +- [HYBIM-730](https://splunk.atlassian.net/browse/HYBIM-730) — Domain entity rename (Metrics → Evaluators, Log Streams → Agent Streams) — separate upcoming PR +- `splunk-ao-migration-tool/README.md` — full Galileo → Splunk AO migration guide