# Kestrel fences in the docs are executable

Every Kestrel code fence in this repository's public docs is a **product assertion**, not
decoration. Prose that contains syntax is a claim about what the runtime accepts, and a claim
that no longer parses is a lie the docs tell their readers. So CI extracts each fence from the
source Markdown and runs it through the **real** parser and printer (`src/lang`). This page
documents the fence taxonomy and doubles as the corpus that proves every branch of it.

Each governed fence carries metadata on its info string: a stable `id`, an optional `check`,
and — for anything that must not parse — an explicit `role`. The checker
(`tests/docs.fences.test.ts`) fails closed if any accepted fence lacks an `id`, if two ids
collide, or if a role/check is unknown.

## Accepted examples — parse, and print stably

An accepted fence uses the `kestrel` language and needs only an `id`. It must parse and its
`print ∘ parse` must be a fixed point. When the source text is already byte-canonical —
canonical spacing, and any `#` comments written in their canonical position — tag it
`check=roundtrip` to pin the ADR-0004 round-trip invariant against the source bytes
themselves:

```kestrel id=doc-breakout-ladder check=roundtrip
PLAN breakout-ladder budget 0.3R ttl +45m regime {intraday: trend}
  USING signal SPX exec SPY 0dte
  WHEN spot crosses above hod AND velocity(1m) >= p95
  DO buy 2 +1 C @ min(fair, mid) peg cap fair
  RELOAD WHEN spot crosses above hod buy 1 +1 C @ min(fair, mid) peg cap fair
  TP 2x frac 0.5 @ fair
  EXIT spot < vwap held 60s @ fair
```

Comments are **preserved byte-stably** (ADR-0004 / ADR-0033): the author's reasoning travels
_with_ the action and survives `print ∘ parse` verbatim. An own-line `#` comment prints on its
own line at the statement's indentation; a trailing `#` comment rides its line with a single
canonical space before `#`. A comment-bearing fence already written in canonical form is a
`check=roundtrip` fence like any other:

```kestrel id=doc-comments-roundtrip check=roundtrip
# reversion: buy the flush, bank the snapback — worse price is a better entry
PLAN buy-the-dip budget 0.3R ttl +30m regime {intraday: range}
  WHEN spot crosses below vwap # fade the flush, not the trend
  DO buy 1 -1 P @ lean(bid, fair, 0.5) peg # rest between bid and worth
  TP 2x frac 0.5 @ fair
```

Only **non-canonical** spacing or comment position is normalized (comment padding collapses to
one space, a stray blank line is dropped) — never dropped, only moved to canonical position. A
fence written that way still parses and stays idempotent under `print ∘ parse`, so it is checked
with `check=parse` (the default): parse must succeed and `print ∘ parse` must be idempotent, but
the source need not equal the canonical form.

```kestrel id=doc-buy-the-flush
# reversion: buy the flush, bank the snapback
PLAN buy-the-flush budget 0.3R ttl +30m regime {intraday: range}
  WHEN spot crosses below vwap
  DO buy 1 -1 P @ lean(bid, fair, 0.5) peg   # rest between bid and worth
  TP 2x frac 0.5 @ fair
```

## Proposed / reference notation — visibly excluded, must not parse

Grammar skeletons and other aspirational notation are **not** executable: they carry
`<placeholders>`, `|` alternations, and `[optional]` brackets. They use a non-`kestrel` fence
language (so the runtime's own `parseMarkdown` never trips over them) plus `role=proposed`,
and the checker asserts they fail closed — the docs can never quietly imply the parser accepts
sugar it does not:

```text id=doc-clause-skeleton role=proposed
PLAN <name> budget <n>R ttl <HH:MM|+45m> [regime {scope: value}]
  WHEN <trigger>
  DO buy <qty> <strike|ATM|+1> <C|P> @ <price>
```

## Diagnostics — "this should fail", and it must

A diagnostic fence demonstrates a fail-closed doctrine. It uses `role=reject` and an
`expect="…"` fragment that must appear in the raised `KestrelParseError` message. If the
example ever starts parsing — or fails for the wrong reason — CI catches it.

A quote is a health signal, never a value: an active exit may not condition on the mark
(ADR-0005).

```text id=doc-reject-exit-on-mark role=reject expect="marks lie"
PLAN bad-exit
  WHEN spot crosses above hod
  DO buy 1 atm C @ fair-2c
  EXIT mid < fair
```

Bounded risk is a type: a budget must be a positive risk fraction, so the position is always
defined-risk.

```text id=doc-reject-budget role=reject expect="positive risk fraction"
PLAN overcommit budget -0.5R
  WHEN phase open
  DO buy 1 atm C @ fair
```

The `atomic` keyword is reserved and refused in v1 — a multi-leg ticket may not claim
all-or-none fills the runtime cannot guarantee.

```text id=doc-reject-atomic role=reject expect="reserved and refused"
PLAN condor
  WHEN phase open
  DO atomic buy 1 +1 C, sell 1 +2 C @ fair
```
