# Clearing-Layer Health Verdict (/docs/operations/operational-health)



<StoryFrame label="Health contract" title="One server-owned verdict. Every client sees the same diagnosis." accent="commit">
  <StoryFact label="Scope">
    Tenant + environment + bounded observation window
  </StoryFact>

  <StoryFact label="Evidence">
    Fresh Postgres aggregates and dependency snapshots
  </StoryFact>

  <StoryFact label="Surfaces">
    REST, Connect, MCP, CLI, and dashboard
  </StoryFact>
</StoryFrame>

Ductor computes one deterministic operational diagnosis. Clients render the
versioned result; they do not reinterpret charts or ask an LLM whether production
is healthy.

## Surfaces [#surfaces]

| Client            | Operation                                                        |
| ----------------- | ---------------------------------------------------------------- |
| REST              | `GET /api/operational-health/report`                             |
| Authorized scopes | `GET /api/operational-health/scopes`                             |
| Connect           | `ductor.api.OperationalHealthService/GetOperationalHealthReport` |
| MCP               | `api_operationalhealthservice_getoperationalhealthreport`        |
| CLI               | `ductor report health`                                           |
| Dashboard         | `/workspaces/{tenant}/health`                                    |

All surfaces consume the same `v1` report id, scope, bounded time window, source
freshness, verdict, confidence, stable reason codes, safe numeric evidence, and fixed
runbook-backed next steps.

## Verdicts [#verdicts]

<StateGrid label="Operational health verdicts">
  <StateCard code="healthy" title="Evidence is fresh" tone="commit">
    Every required source is available and no warning threshold is crossed.
  </StateCard>

  <StateCard code="degraded" title="Flowing under pressure" tone="gold">
    Work continues, but at least one warning threshold is crossed.
  </StateCard>

  <StateCard code="unhealthy" title="Action required" tone="halt">
    Failure, backlog, incompatibility, or stall evidence crosses a hard threshold.
  </StateCard>

  <StateCard code="unknown" title="Evidence path failed" tone="muted">
    Required data is missing, stale, unavailable, skewed, or unclassified.
  </StateCard>
</StateGrid>

`unknown` is fail-closed. Missing telemetry never becomes healthy inactivity.

## Current ruleset [#current-ruleset]

| Signal                                       |   Degraded |       Unhealthy / unknown |
| -------------------------------------------- | ---------: | ------------------------: |
| Telemetry age                                |          — |   unknown after 5 minutes |
| Source clock skew                            |          — | unknown beyond 30 seconds |
| Dependency snapshot age                      |          — |  unknown after 30 seconds |
| Workflow failure ratio (minimum 5 terminals) |        10% |                       25% |
| Recoverable running runs idle for 5 minutes  |          1 |                         5 |
| Ready queue depth                            |        100 |                     1,000 |
| Oldest ready item                            | 15 minutes |                    1 hour |
| Incompatible active attempts                 |          1 |                        10 |
| Unreplayed workflow DLQ entries              |          1 |                       100 |

The successful bounded Postgres observation is itself the workflow telemetry
heartbeat, so a genuinely idle environment can remain fresh without inventing
business activity.

## Authority and privacy [#authority-and-privacy]

The request principal supplies tenant authority. Environment filtering is checked
against that principal before the tenant-bounded aggregate query runs. Reports cache
for 15 seconds by tenant, environment, and period. The report id hashes the pinned
ruleset plus sanitized aggregates.

Output and audit contain ids, scope, verdict, confidence, reason codes, and safe
numbers. Workflow payloads, prompts, raw dependency errors, and credentials are never
report fields.

## CLI example [#cli-example]

```bash
ductor report health --environment production --period 1h
```

Treat `unknown` first as an evidence-path incident: restore the stale or unavailable
source before interpreting downstream workflow ratios.

## Change policy [#change-policy]

Threshold or classification changes require a new ruleset version and frozen
fixtures for flowing, idle, stalled, failing, backlogged, incompatible, and stale
scenarios. A client-specific threshold override is intentionally unsupported.
