> ## Documentation Index
> Fetch the complete documentation index at: https://docs.energy.nlead.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# Cases (Inbox)

> The bridge's exceptions as units of work, each with an outcome - opened by code, closed by a person or by the condition going away

A warning in the event log says that something is wrong. A **case** says
who is dealing with it, what it is about, and how it ended. Cases are the
first piece of the [agentic process support
design](/setup/agentic-process-support.md) (PR 1): the ledger, the inbox views
and the outcome taxonomy exist before any agent does, so the figures an
agent will later be measured against have a baseline. No model is involved
anywhere on this page.

## Where cases come from

Every case is opened by code, from what the bridge already knows.

| Source | Opens | Closes by itself |
| - | - | - |
| `gate_closure_warning` | One case per delivery day: not submitted and accepted inside the gate-closure window. Category *deadline*, risk high. The watchdog's repeat every 15 minutes touches the case, it does not open another. | never - an operator closes it |
| `forecast_backup_at_trader_deadline` | One per delivery day: the customer's forecast missing as the trader's order falls due. *deadline*, medium. | never |
| `vertragsbefund` | One per finding key: a contract breach (high) or difference (medium). *needs\_investigation*. | never |
| `fahrplan_vom_uenb_geaendert` | One per delivery day and Regelzone: the TSO confirmed a trade series at other values than sent. *needs\_investigation*, high. | `fahrplan_aenderung_aufgehoben` for the same day and Regelzone closes it as *resolved by counterpart* |
| `marktdaten_unbekannt` | One per forwarded file with a Prüfidentifikator the bridge does not evaluate. *data\_missing*, low. | never |
| `aperak_needs_review` | One per set of received messages that could not be parsed (keyed by sender and type, so the loop's repeat finds the same case). *needs\_investigation*, high: the APERAK clock is running. | never |
| **Standing rejection** (partner overview) | One per partner and stream whose latest word is a rejection: `partin` (low), `transport` (medium), `zuordnung` (high). Reconciled on every orchestrator run from `market-partners/overview`, so it needs MakoFlow. | when the overview no longer shows the rejection: *resolved by counterpart* |
| **Open Wiedervorlage** | One per entry, opened straight into *For a person*: a partner's reply that a human has to deal with. Reconciled on every run. | when the Wiedervorlage is closed - in the Wiedervorlagen tab or otherwise: *fixed by a human with the agent* |

A case carries its `key` (one open case per key), `source`, `category`,
`risk`, `title`, `subject` (the partner, Regelzone, delivery day, message
reference the finding is about), `evidence` (references into what the
bridge holds already: event ids, ledger entries - never copies),
`explanation` (the warning's own words), an empty `proposals` list (an
agent's, from PR 4 on), a `timeline`, and once closed its `outcome`.

## The outcome taxonomy

Every case closes as exactly one of five outcomes (design rule D7). The
operator picks one in the inbox; code picks one when it closes a case.

| Outcome | Meaning |
| - | - |
| `fixed_by_agent` | The agent's own action resolved it (none yet) |
| `fixed_by_human_with_agent` | A person resolved it, in the bridge |
| `resolved_by_counterpart` | The other side moved: a later positive acknowledgment, the TSO confirming as sent again |
| `no_action_needed` | Looked at; nothing to do |
| `dismissed` | Not a case |

A case open for more than **7 days** is *stale*; the inbox and the summary
count them.

## The inbox

The console tab **Fälle** shows the cases in six views, with a count per
view on each button: *Offen* (everything not done), *Freigabe* (an agent's
proposal waits for a person - empty until PR 4), *Für eine Person*,
*Verbesserungen* (proposed rules and corrections - empty until PR 5),
*Fehlgeschlagen*, *Erledigt*. Open views sort by risk, then age; every row
shows the age and marks a stale case. Per case: a note, a move to or from
*Für eine Person*, and *Erledigt* with the outcome.

The same over the API (scope: **process**):

| Endpoint | Purpose |
| - | - |
| `GET /v1/process/cases?view=&limit=` | The cases of one view, the counts of every view, the stale count |
| `GET /v1/process/cases/{id}` | One case with its timeline |
| `POST /v1/process/cases/{id}/close` | `{"outcome", "note"}` - close with one of the five outcomes (409 when closed already) |
| `POST /v1/process/cases/{id}/note` | `{"text"}` - a timeline entry |
| `POST /v1/process/cases/{id}/status` | `{"status": "open" \| "for_person", "note"}` |
| `POST /v1/process/cases/sync` | What the orchestrator does every run, by hand; `dry_run` (default) reports without writing |
| `GET /v1/process/cases/summary` | Open, stale, by status, category and source, outcomes all-time and over the last 7 days, median hours to resolution |

The caller's key name is recorded as `who` on every timeline entry; cases
opened or closed by code say `bridge`.

## Events and storage

`case_opened`, `case_updated` and `case_closed` go to the event log like
everything else, so the console stream shows them; they stay out of the
Slack interaction log, which already carries the warning or interaction
behind each. `case_sync_failed` (warning) says the partner overview could
not be read for the reconciliation; the next run tries again.

The ledger is `cases.json` on the audit share, next to the ledgers it
references (`wiedervorlage`, `vertragsbefunde_gemeldet`, ...). It is never
pruned: closed cases are the measurement.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.