angl

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 compiler

If 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.

On this page