angl

Source schema

The exact machine anchors an .angl file may use. Everything else is prose.

An .angl file is a structured Markdown document. Markdown is the carrier format; Angl only treats a few lines as schema. Only these anchors are machine schema:

> Boundary:
> Runs as:
> Uses:
## Behavior
## Examples
Input ...:
Fixture ...:
Returns:
Fails with error containing:

Normal Markdown prose is not schema.

Required

  1. A chapter title: # Normalize Event
  2. A typed boundary: > Boundary: `normalize_event(raw: object) -> object`
  3. Behavior prose under ## Behavior. Guides generation, never decides correctness.
  4. At least one executable example under ## Examples. These decide correctness.

Optional

  1. Purpose under ## Purpose. Human documentation only.
  2. Target: > Runs as: `go`. Defaults to python. See Targets.
  3. Dependencies: > Uses: `normalize_event`, `classify_severity`. See Composition.

Rail rules

  • Schema rails must appear before the first section.
  • The boundary function name must be a valid identifier.
  • Dependencies must refer to existing chapter names.
  • Unknown > rails are parse errors. These are not valid:
> Function: `checkout`
> Files: `checkout.py`, `helpers.py`
> Algorithm: `dijkstra`

Use natural language in Behavior for product semantics, and generated manifests for generated files.

Example rules

Inputs are positional. Two Input blocks produce two function arguments in order:

Input `event`:
```json
{"fingerprint": "pay-500"}
```

Input `open_incidents`:
```json
[]
```

Return examples define exact expected values and must contain JSON that parses:

Returns:
```json
{"ok": true}
```

Error examples use substring matching:

Fails with error containing: service

Rules:

  • Every JSON block must parse.
  • Input block names should match boundary argument names.
  • Return blocks define exact expected values.
  • Error examples define exact required error substrings.
  • One-line JSON is allowed by the parser but is expanded by the formatter.

The type boundary

Values that cross the judge shim are JSON: number, string, bool, null, array, object, plus the error channel {"ok": false, "error": msg}. The expressiveness ceiling of Angl is what can cross this boundary plus what fixtures exist. Extending either extends the language.

Generated manifest

Every compiled chapter emits a manifest reporting what the compiler actually made:

{
  "chapter": "checkout",
  "boundary": "checkout(cart: object) -> object",
  "target": "typescript",
  "implementation": "checkout.ts",
  "host_adapter": "checkout.py",
  "judge_adapter": "checkout_shim.py",
  "generated_files": ["checkout.ts", "checkout.py", "checkout_shim.py"],
  "public_files": ["checkout.ts", "checkout.py"],
  "private_files": ["checkout_shim.py"]
}

The manifest is evidence. It is not source truth. Adapters are build plumbing and should stay hidden unless you ask to inspect generated output.

Legacy forms

Older specs using name, interface, target, uses, INTENT, and CONTRACT are still accepted, for migration only. The compact case form also still parses:

name add
interface add(a: number, b: number) -> number

INTENT
Add two numbers.

CONTRACT
case: 1, 2 -> 3
case: 1, "x" -> !error contains "number"

The formatter rewrites accepted aliases into canonical v0.2 form.

On this page