# AWL workloops

Every workloop word, cadence, state, invariant, detached-start and retirement form.

A workloop declares continuing work with bounded iteration histories. It needs a wake source and an explicit retirement body. Routing to start closes one iteration and carries its typed state onward.

## Workloop words

- `workloop`: Declares perpetual work: a flow whose completion is an incident, armed by `every` or `on`, carrying invariants, retention, and a declared `retire`. Arguments: form: declaration; positions: top-level.
- `carry`: Declares a typed, defaulted value threaded iteration to iteration; `route start(name: expr)` rebinds it at the boundary. Arguments: form: header-clause; positions: workloop-header.
- `invariant`: Declares a health object with a type, tolerance and confirming route. Health samples execute; AWL cannot write its typed current-state value. Arguments: form: header-clause; positions: workloop-header.
- `tolerance`: Declares when an unconfirmed invariant alarms — `N windows` of unhealthy samples or `unconfirmed for <duration>` — and has no default. Arguments: form: header-clause; positions: workloop-header.
- `retention`: Declares the required prior-generation window. The store applies it when current-state invariant values are written; AWL currently produces no such values. Arguments: form: header-clause; positions: workloop-header.
- `hatch`: Starts a declared detached workflow that outlives the iteration and owes it nothing; every hatch carries a `key` dedupe identity. Arguments: form: statement; positions: step-body.
- `retire`: Declares the workloop's wind-down block: the recorded, non-failure way the loop stops, required on every workloop. Arguments: form: declaration; positions: top-level.
- `detached`: Declares the start contract for an independently running workflow this document may hatch. The contract supplies input only. Arguments: form: declaration; positions: top-level.
- `windows`: Completes a count-form tolerance: the number of consecutive unhealthy samples the invariant tolerates. Arguments: form: header-clause; positions: workloop-header.
- `report`: Declares a typed answer re-registered during an iteration. It is queryable only while that generation is resident; a parked loop cannot answer it. Arguments: form: header-clause; positions: workloop-header.
- `confirms`: Names the route whose firing lands as a green health sample for the invariant above it — required on every invariant, because one nothing can confirm alarms forever. Arguments: form: header-clause; positions: workloop-header.
- `start`: The iteration terminal after `route`: closes this iteration and opens the next generation, rebinding carries as the payload. Arguments: form: target-word; positions: route-target.
- `unconfirmed`: Opens a duration-form tolerance: the invariant alarms when unconfirmed for the declared window — the only form silence can trip. Arguments: form: header-clause; positions: workloop-header.
- `for`: Connects `unconfirmed` to its window in a duration-form tolerance. Arguments: form: header-clause; positions: workloop-header.
- `key`: Carries a hatch's mandatory dedupe identity: a retried or replayed iteration re-mints the same identity, so one subject hatches one workflow. Arguments: form: statement; positions: step-body.


## Complete forms

**Workloop documents — syntax 1**

```text
//! Poll a queue on cadence; hatch one detached run per task found.
workloop queue_watch
  every 25m
  input queue_dir: String
  carry seen: [String] = []
  report board: type Board
  invariant serving: type Board
    tolerance 3 windows
    confirms start
  retention 14d

type Board { swept: Int }
type Task  { id: String, kind: String, payload: String }
type Sweep { tasks: [Task], seen: [String], swept: Int }

worker sweepers
  action sweep(queue_dir: String, seen: [String]) -> Sweep

detached process_task(kind: String, payload: String)

step sweep_queue
  sweep(queue_dir: queue_dir, seen: seen) -> found
  answer board(swept: found.swept)
  outcome idle: if found.tasks is empty, route start
  outcome busy: else, route dispatch

step dispatch
  fork task in found.tasks
    hatch process_task(kind: task.kind, payload: task.payload) key task.id
  join
  route start(seen: found.seen)

retire
  sweep(queue_dir: queue_dir, seen: seen)
```


## Required structure

Declare a cadence, a received signal wake, or both. There is at most one cadence per loop. A workloop has no ordinary workflow outcome block.

Carried values have defaults. A route can rebind them for the next iteration. Invariants declare their confirming routes and tolerance; reports expose the standing typed reading. Retention names how long prior generations remain.

## Detached work and retirement

A hatch names a declared detached target and a required deduplication key. It starts independent work rather than producing an awaited child handle.

A retire body is required. The retire operation runs that body, records retirement and removes the loop from cadence processing. Use the retire operation to record successful retirement.
