Files
tracer-cloud--opensre/tests/synthetic/rds_postgres
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00
..

Synthetic RDS PostgreSQL Suite

This suite benchmarks RDS PostgreSQL root-cause analysis against bundled telemetry fixtures instead of live AWS infrastructure. Each scenario is a static evidence snapshot served through a FixtureGrafanaBackend, which drives the same agentic pipeline (plan → investigate → diagnose) used in production.

Scenario table

Axis 1 — Efficiency (marker: synthetic)

ID Name Difficulty True root cause Adversarial element Forbidden
000 healthy 1 healthy none resource_exhaustion
001 replication-lag 1 replication_lag none
002 connection-exhaustion 1 connection_exhaustion none
003 storage-full 1 storage_exhaustion none
004 cpu-saturation-bad-query 1 cpu_saturation none
005 failover 1 multi_az_failover_health_check none
006 replication-lag-cpu-redherring 2 replication_lag CPUUtilization elevated (analytics job) category: cpu_saturation
007 connection-pressure-noisy-healthy 2 healthy CPU/connections oscillating near-threshold category: connection_exhaustion
008 storage-full-missing-metric 3 storage_exhaustion FreeStorageSpace absent from fixture
009 dual-fault-connection-cpu 4 connection_exhaustion connections + CPU both failing, causally linked keywords: storage, replication
010 replication-lag-missing-metric 3 replication_lag ReplicaLag metric absent from fixture

Axis 2 — Reasoning (marker: axis2)

Axis 2 scenarios use SelectiveGrafanaBackend. The agent must ask for the right metrics and explicitly rule out alternative hypotheses. Each scenario has ruling_out_keywords that must appear in the agent's output.

ID Name Difficulty True root cause Red herring / adversarial element Must rule out
011 cpu-storage-compositional 4 dual_resource_exhaustion ReplicaLag elevation and connection spike as side effects connection_exhaustion, replication
012 replication-lag-misleading-events 3 replication_lag Three historical infra events in event stream (none are root cause) infrastructure (failover as root cause)
013 storage-recovery-false-alert 3 healthy FreeStorageSpace spike + WriteLatency brief elevation resource_exhaustion (already recovered)
014 checkpoint-storm-cpu-saturation 4 checkpoint_io_storm CPU at 92% — alert fires on CPU but cause is VACUUM checkpoint storm cpu_saturation (CPU is symptom, not root)

Difficulty levels

Level Description
1 Single dominant signal — all evidence consistent, root cause identifiable in one step
2 One confounder present — second evidence source needed to rule it out
3 Absent or indirect evidence — key metric missing, or misleading signals require timeline reasoning
4 Compositional fault — two failure modes active; agent must identify both and correctly characterise causally-linked side effects

MECE basis

Uniqueness is on (primary_signal × rate × corroborating_presence × event_presence), not on primary signal alone.

003 and 008 both map to storage_full but have distinct fingerprints:

  • 003: FreeStorageSpace present and trending to 0 with elevated WriteIOPS
  • 008: FreeStorageSpace absent from the fixture entirely — agent must infer from events + PI write latency

Scoring

Axis 1 (all scenarios — test_suite.py)

Each scenario passes when all of the following are true:

  1. The model returns a non-empty root cause
  2. The predicted ROOT_CAUSE_CATEGORY matches answer.yml
  3. Every required keyword from answer.yml:required_keywords appears in the output
  4. The actual category is not in answer.yml:forbidden_categories (level 2+ scenarios)
  5. No forbidden keyword from answer.yml:forbidden_keywords appears in the output (level 4 scenario)
  6. Every source listed in answer.yml:required_evidence_sources is non-empty in final_state["evidence"] — proves the agent consulted the right evidence, not just keyword-matched the alert title

Additionally, a TrajectoryScore is computed for each scenario with an optimal_trajectory:

  • sequencing_ok: all expected action types appear in the agent's executed action log (set membership; parallel execution order is non-deterministic)
  • calibration_ok: number of investigation loops ≤ max_investigation_loops
  • efficiency_score: mean(sequencing_ok, calibration_ok); 1.0 = full pass

Axis 2 (adversarial scenarios — test_suite_axis2.py, marker: axis2)

Axis 2 runs through SelectiveGrafanaBackend, which:

  • Returns only the metric series matching the agent's metric_name query (case-insensitive substring)
  • Records every metric name the agent requested in queried_metrics (audit log)

On top of all Axis 1 checks, Axis 2 asserts a ReasoningScore:

  • ruling_out_ok: every token in answer.yml:ruling_out_keywords appears in agent output (proves the agent addressed and dismissed alternative hypotheses)
  • queries_ok: every entry in answer.yml:required_queries was requested by the agent via query_timeseriesnot yet testable: the current action registry hardcodes metric_name="pipeline_runs_total" for all query_grafana_metrics calls; required_queries is reserved for when the agent supports per-metric querying
  • reasoning_score: mean(ruling_out_ok, queries_ok); 1.0 = full pass

Gap metric

The gap between Axis 1 and Axis 2 pass rates is the primary health indicator for adversarial robustness. A large gap means the agent can find answers when handed all data but cannot reason when it must choose what to look at. Track it per difficulty level:

python -m tests.synthetic.rds_postgres.run_suite --mock-grafana --axis2

Each scenario folder contains

  • scenario.yml: scenario metadata (engine, difficulty, adversarial_signals, depends_on)
  • alert.json: synthetic alert payload
  • aws_cloudwatch_metrics.json: CloudWatch metric evidence (may omit metrics to simulate collection gaps)
  • aws_rds_events.json: RDS event stream for the incident window
  • aws_performance_insights.json: top SQL and wait-event evidence
  • answer.yml: expected category, required keywords, optional forbidden constraints, required evidence sources

Running

Via the interactive CLI (recommended):

opensre tests synthetic

Run the whole Axis 1 suite directly:

python -m tests.synthetic.rds_postgres.run_suite --mock-grafana

Run Axis 2 adversarial scenarios via pytest:

pytest -m axis2 tests/synthetic/rds_postgres/test_suite_axis2.py -v

Run a single scenario:

python -m tests.synthetic.rds_postgres.run_suite --scenario 006-replication-lag-cpu-redherring --mock-grafana

Print JSON results:

python -m tests.synthetic.rds_postgres.run_suite --mock-grafana --json

CI tier strategy

  • Axis 1, Levels 12 (scenarios 000007): run on every commit (@synthetic)
  • Axis 1, Levels 34 (scenarios 008010): deferred to nightly — require indirect inference
  • Axis 2 (scenarios 011013, @axis2): run nightly alongside Axis 1 levels 34; gap is reported each run

Known gaps

  • Temporal ordering: all scenarios deliver evidence as a static snapshot. Production delivers evidence incrementally (alert fires → query metrics → query events → …). Testing temporal ordering requires architectural changes to the fixture backend and is out of scope.
  • Level 4 coverage: two compositional fault scenarios (009, 011). A fuller curriculum would include 34 dual-fault combinations across different failure mode pairs.
  • Slack/markdown renderer for multi-fault: the renderer displays a single root_cause string. Compositional faults may eventually need a root_causes: list field in the schema.
  • Axis 2 required_queries not yet enforced: The agent action registry hardcodes metric_name="pipeline_runs_total" for all query_grafana_metrics calls. SelectiveGrafanaBackend records all queried metric names as an audit log but does not filter results. When the agent is updated to pass dynamic CloudWatch metric names (e.g. metric_name="CPUUtilization"), re-enable filtering in SelectiveGrafanaBackend.query_timeseries and set required_queries in answer.yml.

Dependency: healthy_rca_state

Scenario 007 depends on HEALTHY_SHORT_CIRCUIT=true (the default) and the healthy category being wired into the LLM prompt. If you run with HEALTHY_SHORT_CIRCUIT=false, scenario 007 will fall through to the LLM path, which should still classify as healthy — but the test is most deterministic with the short-circuit enabled.