Writing chapters
One .angl file is one chapter, a public capability with pinned behavior.
Angl source should read like Markdown, but it is not arbitrary Markdown. The format is a controlled document schema: readable prose in known sections, machine facts in stable anchors, and executable examples in clean data blocks.
The core rule:
If a line changes compilation structure, it must be a schema rail or an
example data block. Everything else is prose.Chapter shape
# Chapter Title
> Boundary: `chapter_name(input: object) -> object`
> Runs as: `python`
> Uses: `other_chapter`, `another_chapter`
## Purpose
One or two paragraphs explaining why this chapter exists.
## Behavior
Readable behavior rules.
## Examples
### Example name
When the input has this situation, the chapter does this outcome.
Input `input`:
```json
{ "field": "value" }
```
Returns:
```json
{ "result": "value" }
```The required surface is small: a title, a typed boundary, behavior prose, and
at least one executable example. Purpose, Runs as, and Uses are optional.
Each part has a distinct job:
- The boundary is the typed interface, the only thing other chapters see. Think of a protobuf service signature.
- Behavior is natural-language product behavior. It is fed to the compiler and guides generation. It is never checked.
- Examples are data-only expectations. They pin the meaning. The judge enforces these and nothing else.
- Purpose is human documentation only. It is not parsed as compiler intent.
The prose rule
Behavior may describe domain rules, invariants, vocabulary, required fields, defaults, and user-visible errors. It must not describe target-language structure, runtime APIs, internal control flow, or an implementation algorithm, unless that algorithm is itself the product requirement.
Good prose:
Reject a request when guests, budget, or hours are not positive.Bad prose:
Import pydantic, define a class, loop over fields, and catch exceptions.If a generation fails, prefer one of two fixes: add a data case that pins the
missing behavior, or improve the compiler prompt. Do not turn Behavior into
pseudocode just to make the current model comply. The linter warns when prose
looks like hidden schema.
File delegation
Source should not normally name generated implementation files.
Bad:
Create checkout.py, discount_helpers.py, and schema.py.Good:
> Boundary: `checkout(cart: object) -> object`
> Uses: `price_quote`, `tax_quote`, `reserve_inventory`The division of labor:
chapter = public capability
implementation = compiled output the app can execute
host adapter = generated glue for the app's language, if needed
judge adapter = generated glue for black-box verification
manifest = compiled file layout, reported by the compilerIf a boundary matters to humans, make it a chapter. If it is implementation plumbing, let the compiler generate it and report it in the manifest.
What deserves a chapter
Angl is meant for contract boundaries, not every private helper function. Write cases for public behavior you care about preserving. Generated code can have whatever internal helpers it wants; untested behavior is unspecified.
If a behavior changes, examples must change. If a chapter grows too broad, split it. If a generated file boundary matters, promote it to a chapter.