# Diagnostics

> Hookable, dedup-aware runtime diagnostics — replaces TODO/FIXME and console.warn.

Source: https://utils.n.yatsyk.com/docs/core

# Diagnostics

The `diagnostics` module is the canonical sink for "something is off but the
process keeps going" — code paths that would otherwise carry a `// TODO`,
`// FIXME`, an inline `console.warn`, or a try/catch that silently swallows
errors. Six functions, grouped by what they signal:

| Function                                  | Kind                                                                      | Dedup'd?           |
| ----------------------------------------- | ------------------------------------------------------------------------- | ------------------ |
| `warnNotImplemented(category, detail)`    | feature exists upstream, port has nothing                                 | yes (per category) |
| `warnDegraded(category, detail)`          | fallback running; usable but not faithful                                 | yes (per category) |
| `warnUnexpected(category, detail, data?)` | should-be-impossible state — Zod fail, non-exhaustive `match`, type guard | no                 |
| `logInfo(category, detail, data?)`        | lifecycle / boot / ops — visible but no "wrong" signal                    | no                 |
| `logError(category, err, detail?)`        | something threw; serializes `Error`                                       | no                 |
| `tryCatchWarn(category, fn)`              | wrap throws into a `{ ok, value } \| { ok, error }` union                 | no                 |

Every emission flows through an optional hook (`setDiagnosticHook`) so a TUI
or web debug panel can render the stream live. Dedup'd kinds use a shared
in-memory `Set<string>` keyed by `kind:category` — call `resetDiagnostics()`
between tests.

* **Stability:** stable
* **Platforms:** node, browser

## Install

```bash
npm i @dev-bench/utils
```

## At the call site

```ts
import {
  warnDegraded,
  warnNotImplemented,
  warnUnexpected,
  logError,
  tryCatchWarn,
} from "@dev-bench/utils";

warnDegraded(
  "polling.getPaneCurrentPath",
  'Falling back to "/" — tmux display-message failed',
);

warnNotImplemented("client.reconnect", "Exponential backoff not yet tuned");

const parsed = SseSchema.safeParse(line);
if (!parsed.success) {
  warnUnexpected("connection.handleSseBlock", "SSE message failed schema validation", {
    issues: parsed.error.issues,
  });
}

const r = await tryCatchWarn("git.diff", () => runGitDiff(ref));
// r is { ok: true; value: T } | { ok: false; error: unknown } — caller .exhaustive()s.
```

See [Getting Started](./getting-started.mdx) for hook setup and test patterns,
[API](./api.mdx) for the full export list.
