# What a clean check means

> `osy validate` checks your source without a server or a database, which is what makes it fast — and what puts a handful of checks out of its reach. A clean run now says which ones those are, so a local green never has to be read as more than it is.

<!-- id: local-what-a-clean-check-means · area: local · stability: preview · html: https://osysharp.com/reference/local/what-a-clean-check-means/ -->

## Summary        {#summary}

`osy validate` runs offline: no server, no database, no account. That is what makes it quick enough to run on every
save — and it means a few checks genuinely cannot run there, because they need state that only exists when the app is
compiled. A clean run lists them rather than implying it checked everything.

## Signature      {#signature}

```console
osy validate [path] [--json]
```

## Description    {#description}

A successful run ends with the checks that did **not** happen:

```console
✓ Validated successfully (4 entities, 7 functions)
  ⓘ 10 checks run only on a server compile:
    • app.Config settings resolved against .env.development / .env.production
    • the app.Config plaintext-secret warning
    • app.Audit surfaces resolved against the audit baseline entities
    • agent `Skills` / runbook `Uses` against the committed skill catalog
    …and 6 more — osy validate --json lists them all.
```

Each line names a **kind of check**, not a count, because a count is not something you can act on. The point is to
tell you *when* a local green is not the whole answer: if you have just edited `app.Config`, added a `control`, or
wired an agent to a skill, that is the moment to run a real compile.

Everything else `osy validate` reports is held to exact agreement with the server — the same rule, from the same
code, in the same words. The list above is the residue, and it is deliberately small.

### Why these need a compile   {#why}

They all read something that does not exist until the app is built:

- **`.env` values** — a setting with no `Default` takes its value from `.env.development` / `.env.production`, and an
  `.env` key naming no declared setting is an error. Neither file is in scope for a source check. See
  [per-environment config (app.Config)](https://osysharp.com/reference/config/app-config/).
- **Committed rows** — an agent's `Skills`, a runbook's `Uses`, and `app.Audit` surfaces resolve against rows the
  compile writes. A skill catalogue holds skills your source does not declare, so checking locally would report an
  unknown skill for one that exists.
- **`osyrin.lock`** — whether a `control` has a package pinned, and whether each `chunks { }` entry has a file. An
  unpinned control fails in the browser and nowhere else.
- **Metadata the platform owns** — `[Id(...)]` directives, `[Test(...)]` fixture links, counter scopes shared across
  entities.

## Examples       {#examples}

```console
osy validate                 # the whole project, with the footer
osy validate --json          # every skipped check, with a stable id and a reason
```

For tooling, the JSON carries a `notCheckedHere` array — **on failing runs too**, because a run that is about to go
green means no more than the one that just did:

```console
osy validate --json | jq '.notCheckedHere[] | .id'
```

## See also       {#see-also}

[The inner loop](https://osysharp.com/reference/local/the-inner-loop/) — where `osy validate` sits in the edit → check → run loop.

[Compiling your app](https://osysharp.com/reference/local/compiling-your-app/) — the compile that performs the checks listed above.

[Checking your app](https://osysharp.com/reference/local/checking-your-app/) — `osy lint`, the maturity signal, beside these correctness ones.

[per-environment config (app.Config)](https://osysharp.com/reference/config/app-config/) — `app.Config` and how a setting takes its value from `.env`.
