ablative docs
↑↓ move↵ openesc close
Stack Notebook ablative.com.au

AWL steps and decisions

Step dependencies, expressions, guards, terminal routes and list pipelines.

Open .md

Steps and list expressions

step awl 6

Declares one node of the step graph; the statements inside it run in written order.

  • form declaration
  • positions top-level, recipe-body
//! Statements inside a step run in written order; steps chain the graph.
workflow compose_greeting
  input name: String
  outcome done: type String, route success

step compose
  "hello " + name -> greeting

step deliver
  route done(greeting)
after awl 6

Names the steps a step waits for, so the dependency is written rather than inferred from position.

  • form statement
  • positions step-body, recipe-step
//! `verify` waits for `build`: the dependency is written, not inferred.
workflow gated_build
  input tag: String
  outcome done: type Checked, route success

type Built   { artifact: String }
type Checked { ok: Bool }

worker ci
  action build(tag: String) -> Built
  action verify(artifact: String) -> Checked

step build
  build(tag: tag) -> built

step verify after build
  verify(artifact: built.artifact) -> checked
  route done(checked)
filter awl 6

Keeps the elements of a collection its predicate accepts.

  • form pipeline-stage
  • positions pipe-stage
//! Keep only the findings the predicate accepts.
workflow keep_blockers
  input findings: [Finding]
  outcome done: type [Finding], route success

type Finding { title: String, blocking: Bool }

step sift
  findings |> filter(.blocking) -> blockers
  route done(blockers)
map awl 6

Rewrites each element of a collection through a deterministic value expression.

  • form pipeline-stage
  • positions pipe-stage
//! Rewrite each element through a deterministic expression.
workflow list_titles
  input findings: [Finding]
  outcome done: type [String], route success

type Finding { title: String, blocking: Bool }

step rename
  findings |> map(.title) -> titles
  route done(titles)
sort awl 6

Orders a collection by a key, which the compile refuses unless it is `Int`, `Float`, or `String`.

  • form pipeline-stage
  • positions pipe-stage
//! Order a collection by a comparable key.
workflow rank_findings
  input findings: [Finding]
  outcome done: type [Finding], route success

type Finding { title: String, severity: Int }

step rank
  findings |> sort(.severity) -> ranked
  route done(ranked)
count awl 6

Counts a collection's elements.

  • form pipeline-stage
  • positions pipe-stage, condition
//! Count a collection's elements.
workflow tally_findings
  input findings: [Finding]
  outcome done: type Int, route success

type Finding { title: String }

step tally
  findings |> count -> total
  route done(total)
any awl 6

True when at least one element of a collection satisfies its predicate.

  • form pipeline-stage
  • positions pipe-stage, condition
//! True when at least one element satisfies the predicate.
workflow spot_blocker
  input findings: [Finding]
  outcome done: type String, route success

type Finding { blocking: Bool }

step look
  findings |> any(.blocking) -> has_blocker
  outcome blocked: if has_blocker, route done("blocked")
  outcome clear: else, route done("clear")
all awl 6

True when every element of a collection satisfies its predicate.

  • form pipeline-stage
  • positions pipe-stage, condition
//! True when every element satisfies the predicate.
workflow verify_receipts
  input receipts: [Receipt]
  outcome done: type String, route success

type Receipt { ok: Bool }

step verify
  receipts |> all(.ok) -> all_ok
  outcome good: if all_ok, route done("every receipt landed")
  outcome partial: else, route done("at least one failed")
is awl 6

Opens a predicate: `is empty`, `is present`, or `is absent`.

  • form condition-word
  • positions condition
//! `is` opens a predicate: `is empty`, `is present`, or `is absent`.
workflow check_queue
  input items: [String]
  outcome done: type String, route success

step look
  outcome idle: if items is empty, route done("idle")
  outcome busy: else, route done("busy")
empty awl 6

The predicate for a collection with nothing in it.

  • form condition-word
  • positions condition
//! The predicate for a collection with nothing in it.
workflow judge_review
  input findings: [String]
  outcome clean:   type String, route success
  outcome blocked: type String, route failure

step judge
  outcome pass: if findings is empty, route clean("no findings")
  outcome fail: else, route blocked("findings remain")
present awl 6

Proves an optional access path present, narrowing it from `T?` to `T` wherever that proof holds.

  • form condition-word
  • positions condition
//! Prove the optional present; the proof narrows `T?` to `T` in the arm.
workflow read_note
  input finding: Finding
  outcome done: type String, route success

type Finding { title: String, note: String? }

step read
  outcome noted: if finding.note is present, route done(finding.note)
  outcome bare: else, route done(finding.title)
absent awl 6

Proves an optional access path absent, which is what an `or` chain narrows on its false edge.

  • form condition-word
  • positions condition
//! Prove the optional absent, which is what omission looks like.
workflow chase_signoff
  input review: Review
  outcome done: type String, route success

type Review { change: String, verdict: String? }

step chase
  outcome pending: if review.verdict is absent, route done("chase " + review.change)
  outcome settled: else, route done(review.change)
not awl 6

Negates a boolean expression.

  • form condition-word
  • positions condition
//! Negate a boolean expression.
workflow gate_ship
  input checks_passed: Bool
  outcome held:    type String, route failure
  outcome shipped: type String, route success

step decide
  outcome hold: if not checks_passed, route held("checks failed")
  outcome go: else, route shipped("shipped")
and awl 6

Boolean conjunction, where each conjunct's presence proof holds for the operands after it.

  • form condition-word
  • positions condition
//! Both conjuncts must hold; each proof carries to the operands after it.
workflow admit_report
  input report: Report
  outcome done: type String, route success

type Report { blocking: Bool, detail: String? }

step admit
  outcome real: if report.blocking and report.detail is present, route done(report.detail)
  outcome noise: else, route done("nothing blocking")
or awl 6

Boolean disjunction, where each disjunct's absence proof holds on its false edge.

  • form condition-word
  • positions condition
//! Either disjunct admits; absence proofs hold on the false edge.
workflow accept_change
  input change: Change
  outcome done: type String, route success

type Change { approved: Bool, urgent: Bool, title: String }

step judge
  outcome go: if change.approved or change.urgent, route done(change.title)
  outcome no: else, route done("declined: " + change.title)

A dependency must name a step. The checker rejects unknown targets and invalid binding flow. Read a binding only on paths that establish it.

Boolean aliases are accepted, then formatted to the word spellings. Parentheses preserve the grouping the expression needs.

Decisions and outcomes

outcome awl 7

Declares a terminal payload in the workflow header, and a guarded arm inside a step body.

  • form statement
  • positions workflow-header, step-body
//! `outcome` declares terminals in the header and guarded arms in a step.
workflow triage_alert
  input urgent: Bool
  outcome paged:  type String, route success
  outcome logged: type String, route success

step decide
  outcome page: if urgent, route paged("paged the operator")
  outcome log: else, route logged("logged for morning")
if awl 7

Guards an outcome arm; the first true guard wins, and its proofs narrow optionals through that arm.

  • form statement
  • positions step-body
//! The first true `if` wins; its proofs hold through the arm.
workflow admit_finding
  input finding: Finding
  outcome done: type String, route success

type Finding { blocking: Bool, detail: String? }

step judge
  outcome real: if finding.detail is present, route done(finding.detail)
  outcome noise: else, route done("no detail recorded")
else awl 7

The complement arm of a guarded outcome set, which must come last.

  • form condition-word
  • positions condition
//! `else` is the complement arm, and must come last.
workflow rate_change
  input risky: Bool
  outcome done: type String, route success

step rate
  outcome careful: if risky, route done("hold for review")
  outcome fine: else, route done("ship it")
when awl 7

Accepted spelling of the `if` guard; `aion awl fmt` rewrites it to the canon.

  • form condition-word
  • positions condition
//! `when` still parses as the `if` guard; `aion awl fmt` rewrites it.
workflow admit_legacy
  input urgent: Bool
  outcome done: type String, route success

step judge
  outcome page: when urgent, route done("page")
  outcome log: else, route done("log")
otherwise awl 7

Accepted spelling of the `else` complement arm; `aion awl fmt` rewrites it to the canon.

  • form condition-word
  • positions condition
//! `otherwise` still parses as the `else` arm; `aion awl fmt` rewrites it.
workflow rate_legacy
  input risky: Bool
  outcome done: type String, route success

step rate
  outcome careful: if risky, route done("hold for review")
  outcome fine: otherwise, route done("ship it")
route awl 7

Sends flow to another step or to a declared outcome, supplying that outcome's payload.

  • form statement
  • positions workflow-header, step-body, pipe-stage
//! `route` sends flow to another step or to a declared outcome.
workflow escalate_alert
  input urgent: Bool
  outcome done: type String, route success

step assess
  outcome page: if urgent, route page_operator
  outcome log: else, route done("logged")

step page_operator
  route done("paged")

An outcome arm combines a named guard and a route. A complement arm covers the remaining case. The checker verifies exhaustiveness where the construct requires it.

A route can carry named record fields or an already-bound value. A successful terminal route records the outcome envelope. A failure-routed outcome records failure rather than a successful result.

Pipeline behavior

Filter keeps matching items. Map selects values. Sort orders by a comparable key. Count, any and all return aggregate values. Each stage’s types are checked; the compiler additionally requires sortable keys to be numbers or strings.

Concurrent dependency layers

Independent eligible steps compile into one parallel dispatch only when every member is exactly one ordinary action call, with no outcome clauses, failure block or visit bound. Other layers run in written order. Child and advisory calls do not qualify for this layer form.