Documentation — Architecture

# Health Check Engine

A health check isn't one query — it's 200+ of them, each scored independently, each capable of producing a finding, and each finding tracked across runs so a recurring problem shows up as one ticket getting worse, not fifty duplicate alerts.

## One check, one status

Every individual check produces a status independently of the others. The thresholds are consistent across the catalogue:

Score | Status | Meaning
--- | --- | ---
≥ 80 | Green | Healthy — no action needed.
60–79 | Amber | Worth watching, not urgent.
< 60 | Red | A finding is recorded.

Some checks use a percentage instead of a 0–100 score directly — a tablespace over 90% used is red regardless of what "score" would otherwise mean for that metric. The threshold logic is per-check, but the three-tier outcome (green / amber / red) is universal, which is what makes the dashboard's color coding consistent across completely different kinds of checks.

## The overall score is an aggregate, not a single query

The number you see on a connection's report — the circular "50/100" style score — isn't its own measurement. It's built from the category scores underneath it: storage, wait events, SQL performance, memory, active sessions, and the rest of the catalogue's categories. Each category is itself an aggregate of the individual checks inside it.

This is why the dashboard shows both the single overall number and the category tiles beneath it — the overall score tells you "how healthy, at a glance," and the category tiles tell you where to look first.

## Ranking what matters: severity × blast radius

A connection can have a dozen active findings at once. Which one do you look at first? TuneVault doesn't just rank by severity — it multiplies severity by an estimated blast radius per check, so a critical finding on something narrow doesn't automatically outrank an amber finding on something that affects the whole instance.

config/finding_weights.json — excerpt
{ "severity_score": { "red": 3, "amber": 2, "info": 1 }, "blast_radius": { "ST01_TABLESPACE_USAGE": 2.0, "WAIT_02": 1.9, "WAIT_01": 1.8, "ST02_UNDO_USAGE": 1.8 } }

Each finding's rank score is `severity_score × blast_radius`. The weights live in a config file, not code — tuning the Top 5 ranking never requires a redeploy, just a restart. This is the exact mechanism behind the "Top Findings" panel you see on first-run and on every subsequent report.

## Recurrence: why the same problem doesn't spawn a new ticket every run

An autonomous connection might run a health check every 30 minutes. Without deduplication, a single unresolved issue would generate dozens of near-identical findings a day. Instead, every finding is matched against `finding_history` on a stable key:

finding_history — the columns that matter
connection_id, check_id, finding_key -- identity: is this the SAME issue? first_seen_at -- when it first appeared last_seen_at -- bumped on every recurrence resolved_at -- set once it stops appearing

If a finding's key matches an existing open entry, `last_seen_at` is bumped — the same underlying TuneOps ticket gets an "occurrence" instead of a duplicate. This is the mechanism behind a ticket showing "confirmed 9 times": it's the same finding, reconfirmed on nine separate runs, not nine separate problems.

This is also what lets TuneVault tell you a finding is resolved — if a previously-open finding's key stops appearing on a run, `resolved_at` gets set. Nobody has to close the ticket manually for the history to reflect reality.

## Where the AI layer fits in

None of the above depends on AI. Scoring, thresholds, ranking, and recurrence tracking are deterministic — the same inputs always produce the same outputs, with or without an `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` configured. The AI summary and recommendations are a separate, optional pass layered on top of already-complete results — if no key is set, the health check still runs, still scores, still tracks recurrence; the AI fields simply show a placeholder instead of a generated summary.

See Connectivity & Agent Protocol for how a check actually reaches your Oracle server, or Architecture Overview for how this fits into the rest of the system.