> For the complete documentation index, see [llms.txt](https://kerno.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerno.gitbook.io/docs/core-concepts/custom-rules.md).

# Custom Rules

Every codebase has rules that are obvious to your team and invisible in the source. Custom rules put those in your repository, so Kerno applies them on every run without you restating them.&#x20;

Rules are guidance to the planner, not enforced constraints. Kerno weighs them against your source code, so a rule that contradicts verified behaviour never overrides it.

{% hint style="warning" %}
**Editing your config does not rewrite existing tests.** New rules shape the next generate for endpoints that have no tests yet. For an endpoint that already has tests, the existing tests are kept.

To apply new rules to an endpoint that already has tests, ask your agent to generate it again with guidance to apply the new rules.
{% endhint %}

### Where rules live

Rules live in two files. Kerno merges them, with your local `config.yaml` taking precedence.

| File                         | Committed      | Purpose                                                        |
| ---------------------------- | -------------- | -------------------------------------------------------------- |
| `.kerno/default.config.yaml` | yes            | Team-wide rules, reviewed in pull requests like any other code |
| `.kerno/config.yaml`         | no, gitignored | Your local overrides and credentials                           |

Put shared conventions in `default.config.yaml`. That way a teammate who clones the repository inherits them, and changing a rule is a reviewable diff.

### How rules are applied

Rules apply from broadest to most specific, and everything that matches is included, so a specific rule adds to the general ones.

```mermaid
flowchart LR
    A[Workspace context] --> B[Workspace endpoint rules]
    B --> C[Application context]
    C --> D[Application endpoint rules]
    D --> E[Merged guidance]
    F["Per-call guidance<br/>(wins on conflict)"] --> E
    E --> G[Planner]
```

For `POST /api/v1/payments` on the `payments-api` application, all four apply, in that order. For `GET /api/v1/invoices`, only the error-envelope and tenant rules apply; the payments-api rules do not.

```yaml
# .kerno/default.config.yaml

test-generation:
  context: |
    Error responses use our standard envelope. On every failure, assert the
    body matches { error: { code, message } }, not only the status code.
  endpoints:
    "/api/v1/**": |
      Every v1 endpoint is tenant-scoped. Always assert that a request
      authenticated as tenant A cannot read or modify tenant B's records.

applications:
  payments-api:
    test-generation:
      context: |
        Money amounts are integer minor units, never floats. Idempotency keys
        are required on every mutating request.
      endpoints:
        "POST /api/v1/payments": |
          Cover the duplicate-idempotency-key case explicitly: the second
          request must return the original payment, not create a second one.
```

#### Matching endpoints

| Pattern                         | Matches                                  |
| ------------------------------- | ---------------------------------------- |
| `*`                             | Every endpoint                           |
| `/api/users`                    | That exact path, any method              |
| `GET /api/users`                | That path and method only                |
| `/api/v1/*`                     | One path segment, e.g. `/api/v1/users`   |
| `/api/v1/**`                    | Any depth, e.g. `/api/v1/users/42/roles` |
| `regex:^/api/v[0-9]+/users/.+$` | Anything the expression matches          |
