Lemonade Splunk OpenTelemetry
Prerequisites
| Tool or access |
Purpose |
Verify |
| Bash and Python 3 |
Run bundled setup and validation helpers |
bash --version && python3 --version |
| Required product/platform access |
Inspect or configure the selected target |
Complete the documented preflight |
| Credential files for live modes |
Keep secrets out of chat |
Verify paths only |
Workflow Overview
┌───────────┐ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐
│ Preflight │ → │ Render/review │ → │ Apply/handoff │ → │ Validate evidence │
└───────────┘ └───────────────┘ └───────────────┘ └─────────────────┘
When to Activate
- Installing or upgrading Lemonade, checking its telemetry, configuring a loopback OTLP receiver, or preparing
Lemonade telemetry for Splunk or Galileo fan-out.
- Preview and review the lemonade splunk otel workflow before any live apply phase.
- Diagnose failed prerequisites, generated assets, configuration, or validation evidence.
Scope
Follow the documented read-only or render-first path whenever it is available.
This skill does not imply permission to mutate live systems. Require explicit
apply flags, protected credentials, and operator review for state changes.
Examples
Inspect the supported setup modes before selecting one:
bash skills/lemonade-splunk-otel/scripts/setup.sh --help
Expected output: usage, supported modes, and required arguments are displayed
without changing the target environment.
Inspect validation modes before running completion checks:
bash skills/lemonade-splunk-otel/scripts/validate.sh --help
Expected output: offline, live, and completion options are displayed when the
skill supports them; help exits without mutation.
Troubleshooting
| Issue |
Cause |
Resolution |
| Preflight fails |
A required tool or access path is missing |
Resolve it before rendering or applying |
| Rendered assets are incomplete |
Required non-secret inputs are absent |
Complete intake and render again |
| Apply is blocked |
Review, credentials, or explicit acceptance is missing |
Use the documented handoff |
| Validation is incomplete |
Live evidence is unavailable |
Record the gap and keep completion open |
Purpose
Use this skill as the host and collector foundation for a Lemonade Server on
Debian or an AMD Ryzen AI developer box. It owns discovery, upgrade safety,
native telemetry, a single rendered collector configuration, validation, and
rollback. For Galileo routing and application-side agent traces, compose it
with $galileo-lemonade-instrumentation-setup.
The tested baseline is Lemonade v10.10 with Splunk OTel Collector v0.156 on
Linux; preserve the exact installed distro's component IDs.
Run the render/review tools with Python 3 plus PyYAML. On Debian install
python3-yaml; in this repository use the isolated requirements-dev.txt
environment (for example, .venv/bin/python) rather than the macOS system
interpreter. The shell entrypoints use the first python3 on PATH.
Lemonade v10.10 emits OTLP traces for inference requests. It does not emit
OTLP logs or metrics. Journald collection is a separate, opt-in logs path.
Safety Contract
- Discover the live service, package source, config path, collector binary,
collector config, and bound ports before changing anything.
- Render to a staging path. Never layer a second YAML file containing pipeline
lists over the live collector config.
- Back up the Lemonade and collector configs and record service state before
apply. Validate with the exact installed collector binary before restart.
- Keep OTLP receivers on loopback unless an explicit network threat model and
firewall policy authorize remote ingestion.
- Keep
telemetry.hide_inputs, hide_outputs, and hide_thinking enabled by
default. Disabling them is content-export approval, not a debugging toggle.
- Lemonade v10.10 can place a raw upstream/model error in span
status.message even while hide flags are on. Keep the rendered conditional
privacy transform and validate a failed non-sensitive request.
- Never place a Splunk token or Galileo key on argv, in chat, or in generated
YAML. Source each secret into a dedicated
0600 runtime file owned by the
service identity that reads it; use root ownership only for a root service.
Rendering and validation reject literal credential-bearing YAML fields,
including inherited exporter tokens and sensitive headers; use only exact
uppercase environment placeholders.
- Use separate least-privilege Splunk organization tokens: an Ingest-scoped
token for the Collector and an API-scoped
read_only token for backend
validation. Never deploy a user API session token to the Collector. Follow
the fail-closed creation, rotation, and cutover transaction in
references/keychain.md; a disclosed or combined
API-and-Ingest token is not production-ready until it is replaced and the
old token or secret is no longer accepted.
- Do not infer success from a service restart alone. Require source, collector,
exporter, and backend evidence.
Workflow
Read reference.md, then load only the detailed reference
needed for the task.
Inventory the host using the commands in
references/debian-runbook.md. Confirm the
health URL and OpenAI-compatible base URL from the live server; do not
assume a port.
If upgrading, record the installed version, package candidate, APT origin,
held packages, config checksum, and service state. Back up first and keep a
downgrade path.
Configure Lemonade through telemetry.otlp.*; Lemonade does not consume the
standard per-signal OTLP endpoint/protocol environment variables. Set both
openinference and otel_genai semantics. On v10.10, after backing up the
discovered config.json, the concrete CLI operation is:
lemonade config set telemetry.enabled=true \
telemetry.hide_inputs=true \
telemetry.hide_outputs=true \
telemetry.hide_thinking=true \
telemetry.otlp.endpoint=http://127.0.0.1:4318/v1/traces \
telemetry.otlp.protocol=http/protobuf \
telemetry.otlp.semantics='["openinference","otel_genai"]'
Verify the live snapshot through lemonade config or the loopback-only
/internal/config endpoint without printing telemetry.otlp.headers.
Render one full collector config from the live base:
bash skills/lemonade-splunk-otel/scripts/setup.sh \
--base /etc/otel/collector/agent_config.yaml \
--output /tmp/lemonade-agent_config.yaml \
--deployment-environment lemonade-dev
If a config produced by the earlier personal skill contains the known
shared resource/lemonade component, the renderer fails closed. Review the
detected shape, keep the backup, and rerun with
--migrate-legacy-lemonade-renderer; unknown/conflicting shapes are never
removed automatically. The explicit migration accepts only the exact legacy
topology: one final processor entry in the selected traces[/name] pipeline
and one final processor entry in the selected logs[/name] pipeline.
Duplicate, reordered, wrong-field, metrics, foreign-pipeline, missing, or
additional references fail closed.
Preserve the installed distro's resource-detection component ID and
detector configuration.
Repeated renders recognize only this skill's exact current privacy and
optional journald component shapes, references, and ordering. A foreign,
partial, dangling, duplicated, reordered, or tampered managed ID fails
closed; reconcile it from the retained source backup instead of forcing an
overwrite. The existing privacy processor must remain referenced by the
same selected --traces-pipeline; changing that selector is not an implicit
move operation. To move it, start from the retained clean source or
deliberately remove the previously reviewed exact managed component and
reference, then render and validate the complete diff again.
Review the diff. Validate the staged file with both this skill and the exact
installed collector binary:
PyYAML normalizes formatting and does not preserve vendor comments. Keep the
original backup and use the value-free semantic summary to make review
tractable before inspecting the full diff:
python3 skills/lemonade-splunk-otel/scripts/config_change_summary.py \
--before /etc/otel/collector/agent_config.yaml \
--after /tmp/lemonade-agent_config.yaml
bash skills/lemonade-splunk-otel/scripts/validate.sh \
--collector-config /tmp/lemonade-agent_config.yaml \
--collector-binary /usr/bin/otelcol \
--production
Use --production for an apply candidate; it refuses to pass without an
explicit absolute path to the exact installed collector binary. Omit it
only for offline static inspection.
Apply the already-validated staged bytes with the packaged Linux/root-only
transaction helper. Derive every path, service name, and loopback collector
health URL from the live unit; the values below are examples:
STAGED_SHA256="$(sha256sum /tmp/lemonade-agent_config.yaml | cut -d ' ' -f 1)"
COLLECTOR_SHA256="$(sha256sum /usr/bin/otelcol | cut -d ' ' -f 1)"
sudo python3 skills/lemonade-splunk-otel/scripts/transactional_apply.py apply \
--staged /tmp/lemonade-agent_config.yaml \
--live /etc/otel/collector/agent_config.yaml \
--service splunk-otel-collector.service \
--health-url http://127.0.0.1:13133/ \
--expected-sha256 "$STAGED_SHA256" \
--collector-binary /usr/bin/otelcol \
--collector-binary-sha256 "$COLLECTOR_SHA256" \
--state-root /var/lib/lemonade-otel-config-transactions
Retain the returned root-only schema-v2 manifest. Before taking a snapshot,
the helper requires systemctl show to resolve the exact requested service
ID with LoadState=loaded, ActiveState exactly active or inactive, and
UnitFileState exactly enabled or disabled; it rejects transitional,
failed, runtime-only, static, alias, linked, indirect, and masked states.
The exact ActiveState must agree with systemctl is-active. It binds the
transaction to a hashed machine ID, exact package versions, the supplied
collector binary path, device/inode, and hash, and a hash-only systemd
unit/drop-in fingerprint. It snapshots exact live bytes, ownership, mode,
ACL/SELinux/extended attributes, and exact service state before atomically
installing and restarting. An explicit later rollback is:
sudo python3 skills/lemonade-splunk-otel/scripts/transactional_apply.py \
restore --manifest /absolute/root-only/transaction/manifest.json
Explicit restore is resumable and accepts only the exact staged hash or the
exact backup hash for the current transaction generation. It fails closed
for unknown config drift, a stale/copied manifest, host/package/binary/unit
drift, or a missing exact loaded service. A root-only current-generation
pointer and phase journal survive abrupt termination; retry the same restore
after an interrupted rollback. A new apply refuses to supersede an
incomplete generation. Do not bypass these gates—restore the recorded
runtime provenance or investigate the drift. Automatic in-process recovery
may overwrite an indeterminate partial install with the verified backup.
The helper rechecks packages, collector binary identity/hash, unit
fingerprint, and exact service state before install, before and after
restart, before and after health, and immediately before the terminal
applied checkpoint. If one of those checks drifts after config replacement,
it restores only the verified prior config bytes, performs no rollback
service actions, records recovery_required, and exits with sanitized
evidence. Restore the recorded package/binary/unit provenance and retry the
same manifest; do not start another apply.
Require the live config, state root, collector binary, systemd unit, and
their ancestors to be root-owned and not group/other-writable. The staged
input may be operator-owned, but it must remain the same inode and hash
through the mutation boundary. If ACL, SELinux, or extended attributes
cannot be read and restored exactly, the helper stops before replacement.
This transaction covers the collector config and collector service state;
snapshot and restore any package, systemd drop-in, or environment-file
change separately.
Send the privacy-safe canary, run a real non-sensitive Lemonade completion,
flush /internal/telemetry/flush, then perform the validation ladder and
organization-bound, all-segment Splunk APM readback in
references/validation.md. Use a separate
protected API-scoped read token; the Collector ingest token is not a
backend-read credential.
Native Telemetry Settings
Use the live Lemonade configuration mechanism discovered on the host. The
equivalent settings are:
telemetry:
enabled: true
hide_inputs: true
hide_outputs: true
hide_thinking: true
otlp:
endpoint: http://127.0.0.1:4318/v1/traces
protocol: http/protobuf
semantics: [openinference, otel_genai]
Lemonade has one native OTLP endpoint and creates a new root trace for every
request. It does not extract W3C traceparent, so its spans cannot join a
caller's agent trace without source changes.
Delegations
- Fresh or fleet collector installation: use
$splunk-observability-otel-collector-setup.
- Galileo project/Log stream lifecycle and tenant readiness: use
$galileo-platform-setup.
- Galileo fan-out, source-selection, agent instrumentation, and readback: use
$galileo-lemonade-instrumentation-setup.
Completion Gate
Report the Lemonade version and health, privacy flags, receiver bind address,
collector validation, exact accepted/failed/refused and
sent/send-failed/enqueue-failed deltas, queue/in-flight state, Splunk readback,
and the retained transaction manifest or tested restore artifact. Never report
backend delivery from collector counters alone.
1---2name: lemonade-splunk-otel3description: Use when installing or upgrading Lemonade, checking its telemetry, configuring a loopback OTLP receiver, or preparing Lemonade telemetry for Splunk or Galileo fan-out. Upgrade and operate Lemonade Server on Debian or AMD Ryzen AI hosts, enable its native OpenTelemetry traces, and route them through the Splunk Distribution of the OpenTelemetry Collector with secure credentials, privacy controls, rollback, and backend validation.4---56# Lemonade Splunk OpenTelemetry78## Prerequisites910| Tool or access | Purpose | Verify |11|---|---|---|12| Bash and Python 3 | Run bundled setup and validation helpers | `bash --version && python3 --version` |13| Required product/platform access | Inspect or configure the selected target | Complete the documented preflight |14| Credential files for live modes | Keep secrets out of chat | Verify paths only |1516## Workflow Overview1718```text19┌───────────┐ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐20│ Preflight │ → │ Render/review │ → │ Apply/handoff │ → │ Validate evidence │21└───────────┘ └───────────────┘ └───────────────┘ └─────────────────┘22```2324## When to Activate2526- Installing or upgrading Lemonade, checking its telemetry, configuring a loopback OTLP receiver, or preparing27 Lemonade telemetry for Splunk or Galileo fan-out.28- Preview and review the lemonade splunk otel workflow before any live apply phase.29- Diagnose failed prerequisites, generated assets, configuration, or validation evidence.3031## Scope3233Follow the documented read-only or render-first path whenever it is available.34This skill does not imply permission to mutate live systems. Require explicit35apply flags, protected credentials, and operator review for state changes.3637## Examples3839Inspect the supported setup modes before selecting one:4041```bash42bash skills/lemonade-splunk-otel/scripts/setup.sh --help43```4445Expected output: usage, supported modes, and required arguments are displayed46without changing the target environment.4748Inspect validation modes before running completion checks:4950```bash51bash skills/lemonade-splunk-otel/scripts/validate.sh --help52```5354Expected output: offline, live, and completion options are displayed when the55skill supports them; help exits without mutation.5657## Troubleshooting5859| Issue | Cause | Resolution |60|---|---|---|61| Preflight fails | A required tool or access path is missing | Resolve it before rendering or applying |62| Rendered assets are incomplete | Required non-secret inputs are absent | Complete intake and render again |63| Apply is blocked | Review, credentials, or explicit acceptance is missing | Use the documented handoff |64| Validation is incomplete | Live evidence is unavailable | Record the gap and keep completion open |6566## Purpose6768Use this skill as the host and collector foundation for a Lemonade Server on69Debian or an AMD Ryzen AI developer box. It owns discovery, upgrade safety,70native telemetry, a single rendered collector configuration, validation, and71rollback. For Galileo routing and application-side agent traces, compose it72with `$galileo-lemonade-instrumentation-setup`.7374The tested baseline is Lemonade v10.10 with Splunk OTel Collector v0.156 on75Linux; preserve the exact installed distro's component IDs.7677Run the render/review tools with Python 3 plus PyYAML. On Debian install78`python3-yaml`; in this repository use the isolated `requirements-dev.txt`79environment (for example, `.venv/bin/python`) rather than the macOS system80interpreter. The shell entrypoints use the first `python3` on `PATH`.8182Lemonade v10.10 emits OTLP **traces** for inference requests. It does not emit83OTLP logs or metrics. Journald collection is a separate, opt-in logs path.8485## Safety Contract8687- Discover the live service, package source, config path, collector binary,88 collector config, and bound ports before changing anything.89- Render to a staging path. Never layer a second YAML file containing pipeline90 lists over the live collector config.91- Back up the Lemonade and collector configs and record service state before92 apply. Validate with the exact installed collector binary before restart.93- Keep OTLP receivers on loopback unless an explicit network threat model and94 firewall policy authorize remote ingestion.95- Keep `telemetry.hide_inputs`, `hide_outputs`, and `hide_thinking` enabled by96 default. Disabling them is content-export approval, not a debugging toggle.97- Lemonade v10.10 can place a raw upstream/model error in span98 `status.message` even while hide flags are on. Keep the rendered conditional99 privacy transform and validate a failed non-sensitive request.100- Never place a Splunk token or Galileo key on argv, in chat, or in generated101 YAML. Source each secret into a dedicated `0600` runtime file owned by the102 service identity that reads it; use root ownership only for a root service.103 Rendering and validation reject literal credential-bearing YAML fields,104 including inherited exporter tokens and sensitive headers; use only exact105 uppercase environment placeholders.106- Use separate least-privilege Splunk organization tokens: an Ingest-scoped107 token for the Collector and an API-scoped `read_only` token for backend108 validation. Never deploy a user API session token to the Collector. Follow109 the fail-closed creation, rotation, and cutover transaction in110 [references/keychain.md](references/keychain.md); a disclosed or combined111 API-and-Ingest token is not production-ready until it is replaced and the112 old token or secret is no longer accepted.113- Do not infer success from a service restart alone. Require source, collector,114 exporter, and backend evidence.115116## Workflow1171181. Read [reference.md](reference.md), then load only the detailed reference119 needed for the task.1202. Inventory the host using the commands in121 [references/debian-runbook.md](references/debian-runbook.md). Confirm the122 health URL and OpenAI-compatible base URL from the live server; do not123 assume a port.1243. If upgrading, record the installed version, package candidate, APT origin,125 held packages, config checksum, and service state. Back up first and keep a126 downgrade path.1274. Configure Lemonade through `telemetry.otlp.*`; Lemonade does not consume the128 standard per-signal OTLP endpoint/protocol environment variables. Set both129 `openinference` and `otel_genai` semantics. On v10.10, after backing up the130 discovered `config.json`, the concrete CLI operation is:131132 ```bash133 lemonade config set telemetry.enabled=true \134 telemetry.hide_inputs=true \135 telemetry.hide_outputs=true \136 telemetry.hide_thinking=true \137 telemetry.otlp.endpoint=http://127.0.0.1:4318/v1/traces \138 telemetry.otlp.protocol=http/protobuf \139 telemetry.otlp.semantics='["openinference","otel_genai"]'140 ```141142 Verify the live snapshot through `lemonade config` or the loopback-only143 `/internal/config` endpoint without printing `telemetry.otlp.headers`.1445. Render one full collector config from the live base:145146 ```bash147 bash skills/lemonade-splunk-otel/scripts/setup.sh \148 --base /etc/otel/collector/agent_config.yaml \149 --output /tmp/lemonade-agent_config.yaml \150 --deployment-environment lemonade-dev151 ```152153 If a config produced by the earlier personal skill contains the known154 shared `resource/lemonade` component, the renderer fails closed. Review the155 detected shape, keep the backup, and rerun with156 `--migrate-legacy-lemonade-renderer`; unknown/conflicting shapes are never157 removed automatically. The explicit migration accepts only the exact legacy158 topology: one final processor entry in the selected `traces[/name]` pipeline159 and one final processor entry in the selected `logs[/name]` pipeline.160 Duplicate, reordered, wrong-field, metrics, foreign-pipeline, missing, or161 additional references fail closed.162 Preserve the installed distro's resource-detection component ID and163 detector configuration.164165 Repeated renders recognize only this skill's exact current privacy and166 optional journald component shapes, references, and ordering. A foreign,167 partial, dangling, duplicated, reordered, or tampered managed ID fails168 closed; reconcile it from the retained source backup instead of forcing an169 overwrite. The existing privacy processor must remain referenced by the170 same selected `--traces-pipeline`; changing that selector is not an implicit171 move operation. To move it, start from the retained clean source or172 deliberately remove the previously reviewed exact managed component and173 reference, then render and validate the complete diff again.1741756. Review the diff. Validate the staged file with both this skill and the exact176 installed collector binary:177178 PyYAML normalizes formatting and does not preserve vendor comments. Keep the179 original backup and use the value-free semantic summary to make review180 tractable before inspecting the full diff:181182 ```bash183 python3 skills/lemonade-splunk-otel/scripts/config_change_summary.py \184 --before /etc/otel/collector/agent_config.yaml \185 --after /tmp/lemonade-agent_config.yaml186 ```187188 ```bash189 bash skills/lemonade-splunk-otel/scripts/validate.sh \190 --collector-config /tmp/lemonade-agent_config.yaml \191 --collector-binary /usr/bin/otelcol \192 --production193 ```194195 Use `--production` for an apply candidate; it refuses to pass without an196 explicit absolute path to the exact installed collector binary. Omit it197 only for offline static inspection.1981997. Apply the already-validated staged bytes with the packaged Linux/root-only200 transaction helper. Derive every path, service name, and loopback collector201 health URL from the live unit; the values below are examples:202203 ```bash204 STAGED_SHA256="$(sha256sum /tmp/lemonade-agent_config.yaml | cut -d ' ' -f 1)"205 COLLECTOR_SHA256="$(sha256sum /usr/bin/otelcol | cut -d ' ' -f 1)"206 sudo python3 skills/lemonade-splunk-otel/scripts/transactional_apply.py apply \207 --staged /tmp/lemonade-agent_config.yaml \208 --live /etc/otel/collector/agent_config.yaml \209 --service splunk-otel-collector.service \210 --health-url http://127.0.0.1:13133/ \211 --expected-sha256 "$STAGED_SHA256" \212 --collector-binary /usr/bin/otelcol \213 --collector-binary-sha256 "$COLLECTOR_SHA256" \214 --state-root /var/lib/lemonade-otel-config-transactions215 ```216217 Retain the returned root-only schema-v2 manifest. Before taking a snapshot,218 the helper requires `systemctl show` to resolve the exact requested service219 ID with `LoadState=loaded`, `ActiveState` exactly `active` or `inactive`, and220 `UnitFileState` exactly `enabled` or `disabled`; it rejects transitional,221 failed, runtime-only, static, alias, linked, indirect, and masked states.222 The exact `ActiveState` must agree with `systemctl is-active`. It binds the223 transaction to a hashed machine ID, exact package versions, the supplied224 collector binary path, device/inode, and hash, and a hash-only systemd225 unit/drop-in fingerprint. It snapshots exact live bytes, ownership, mode,226 ACL/SELinux/extended attributes, and exact service state before atomically227 installing and restarting. An explicit later rollback is:228229 ```bash230 sudo python3 skills/lemonade-splunk-otel/scripts/transactional_apply.py \231 restore --manifest /absolute/root-only/transaction/manifest.json232 ```233234 Explicit restore is resumable and accepts only the exact staged hash or the235 exact backup hash for the current transaction generation. It fails closed236 for unknown config drift, a stale/copied manifest, host/package/binary/unit237 drift, or a missing exact loaded service. A root-only current-generation238 pointer and phase journal survive abrupt termination; retry the same restore239 after an interrupted rollback. A new apply refuses to supersede an240 incomplete generation. Do not bypass these gates—restore the recorded241 runtime provenance or investigate the drift. Automatic in-process recovery242 may overwrite an indeterminate partial install with the verified backup.243244 The helper rechecks packages, collector binary identity/hash, unit245 fingerprint, and exact service state before install, before and after246 restart, before and after health, and immediately before the terminal247 `applied` checkpoint. If one of those checks drifts after config replacement,248 it restores only the verified prior config bytes, performs no rollback249 service actions, records `recovery_required`, and exits with sanitized250 evidence. Restore the recorded package/binary/unit provenance and retry the251 same manifest; do not start another apply.252253 Require the live config, state root, collector binary, systemd unit, and254 their ancestors to be root-owned and not group/other-writable. The staged255 input may be operator-owned, but it must remain the same inode and hash256 through the mutation boundary. If ACL, SELinux, or extended attributes257 cannot be read and restored exactly, the helper stops before replacement.258259 This transaction covers the collector config and collector service state;260 snapshot and restore any package, systemd drop-in, or environment-file261 change separately.2628. Send the privacy-safe canary, run a real non-sensitive Lemonade completion,263 flush `/internal/telemetry/flush`, then perform the validation ladder and264 organization-bound, all-segment Splunk APM readback in265 [references/validation.md](references/validation.md). Use a separate266 protected API-scoped read token; the Collector ingest token is not a267 backend-read credential.268269## Native Telemetry Settings270271Use the live Lemonade configuration mechanism discovered on the host. The272equivalent settings are:273274```yaml275telemetry:276 enabled: true277 hide_inputs: true278 hide_outputs: true279 hide_thinking: true280 otlp:281 endpoint: http://127.0.0.1:4318/v1/traces282 protocol: http/protobuf283 semantics: [openinference, otel_genai]284```285286Lemonade has one native OTLP endpoint and creates a new root trace for every287request. It does not extract W3C `traceparent`, so its spans cannot join a288caller's agent trace without source changes.289290## Delegations291292- Fresh or fleet collector installation: use293 `$splunk-observability-otel-collector-setup`.294- Galileo project/Log stream lifecycle and tenant readiness: use295 `$galileo-platform-setup`.296- Galileo fan-out, source-selection, agent instrumentation, and readback: use297 `$galileo-lemonade-instrumentation-setup`.298299## Completion Gate300301Report the Lemonade version and health, privacy flags, receiver bind address,302collector validation, exact accepted/failed/refused and303sent/send-failed/enqueue-failed deltas, queue/in-flight state, Splunk readback,304and the retained transaction manifest or tested restore artifact. Never report305backend delivery from collector counters alone.