# session-health-util — Two-Tier Session Health Coordinator

**Agent file:** [`agents/session-health-util.md`](../../../../agents/session-health-util.md)

**Invoked by:** `async-agent-util` (health operation) — one instance per session, in parallel batches of 10.

**Hidden:** Yes (internal infrastructure, not user-facing)

## Purpose

Coordinates health evaluation for **exactly one session** per invocation. Runs a two-tier pipeline:

1. **Tier 1 (Quick)** — fetches the last 3 text-only messages, asks `session-health-quick-util` for an obvious classification
2. **Tier 2 (Full)** — only runs if Tier 1 returns `escalate`; delegates to `session-health-full-util` for comprehensive analysis

This coordinator never evaluates content itself — it orchestrates the two specialist sub-agents and surfaces their results.

## Two-Tier Flow

```
session-health-util
  │
  ├─ Tier 1: session_messages.ts --limit 3 --text-only
  │          → session-health-quick-util
  │               │
  │               ├─ verdict: "finished" ──→ return health_state: finished
  │               ├─ verdict: "errored"  ──→ return health_state: errored
  │               └─ verdict: "escalate" ──→ proceed to Tier 2
  │
  └─ Tier 2: session-health-full-util
                  (fetches own messages, evaluates all 3 dimensions)
                  → return full health classification
```

## Input (prompt from caller)

| Field | Required | Description |
|-------|:--------:|-------------|
| `session_id` | yes | Session ID to evaluate |
| `title` | yes | Full session title |
| `tag` | yes | Extracted `[TAG]` or null |
| `status` | yes | `busy` or `idle` |
| `last_active_ms` | yes | Epoch ms of last activity |
| `collected_at_ms` | yes | Epoch ms when health snapshot was taken |
| `idle_threshold_minutes` | yes | Stuck threshold in minutes |

## Output (returned to async-agent-util)

**Quick-path result:**
```json
{
  "session_id": "ses_abc123",
  "title": "[AUTO-PRMRG-PR-42] pr-merge-worker",
  "tag": "AUTO-PRMRG-PR-42",
  "status": "idle",
  "last_active_ms": 1776700000000,
  "minutes_inactive": 2.4,
  "health_state": "finished",
  "summary": "Last message says merge was scheduled successfully.",
  "evaluation_tier": "quick",
  "signals": null
}
```

**Full-path result:** same schema with `"evaluation_tier": "full"` and populated `signals` object containing timing, tools, and content sub-verdicts.

## Health States

| State | Meaning |
|-------|---------|
| `healthy` | Busy and progressing normally, or recently active with no issues |
| `stuck` | Busy but no activity beyond the idle threshold, and last step was not awaiting tool results |
| `idle` | Not busy; paused mid-task (supervisors between cycles, workers awaiting input) |
| `finished` | Not busy; task conclusively completed |
| `unhealthy` | Operating in a degraded state (permission workarounds, retry loops, cascading failures) |
| `errored` | Explicitly cannot continue; permanent block requiring human intervention |

## Sub-agents called

| Agent | When | Purpose |
|-------|------|---------|
| `session-health-quick-util` | Always (Tier 1) | Fast obvious classification from last 3 messages |
| `session-health-full-util` | On escalate (Tier 2) | Comprehensive 3-dimension analysis |

## Skill loaded

`auto-agents-system` — provides system context for interpreting session titles and expected agent behaviours.
