kestrel.markets
Version:
A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.
107 lines (86 loc) • 4.86 kB
Markdown
# 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
```