summon
:summon threads a value through a list of action names in sequence. Each action receives the output of the previous one.
Overview
:summon is :invoke applied repeatedly down a list. It takes a starting value and a list of action name strings, and passes the value through each action in order — the output of one becomes the input of the next.
:summon(value, ["action_one", "action_two", "action_three"])
:summon(value, ["action_one", "action_two", "action_three"])
This is equivalent to:
value |= :invoke("action_one", value) value |= :invoke("action_two", value) value |= :invoke("action_three", value)
value |= :invoke("action_one", value) value |= :invoke("action_two", value) value |= :invoke("action_three", value)
Basic Usage
act add_one(n) => return n + 1 act double(n) => return n * 2 result | :summon(3, ["add_one", "double"]) /// add_one(3) → 4 /// double(4) → 8 /// result → 8
act add_one(n) => return n + 1 act double(n) => return n * 2 result | :summon(3, ["add_one", "double"]) /// add_one(3) → 4 /// double(4) → 8 /// result → 8
Sheriff Build Pipeline
:summon is how the Sheriff build pipeline works. Each portal defines a schedule in its config — an ordered list of action names — and summon threads the page context through all of them:
schedule | cfg["schedule"] ctx |= :summon(ctx, schedule)
schedule | cfg["schedule"] ctx |= :summon(ctx, schedule)
A schedule might look like:
schedule: - "frontier::strip_frontmatter" - "markdown_core::render" - "trailboss::rewrite_wiki_links" - "brindle::apply_layout" - "brindle::apply_tokens"
schedule: - "frontier::strip_frontmatter" - "markdown_core::render" - "trailboss::rewrite_wiki_links" - "brindle::apply_layout" - "brindle::apply_tokens"
Each action receives ctx and returns a modified ctx. The final result is the fully built page. Because the schedule lives in config rather than code, you can add, remove, or reorder build steps without touching any Goblin files.
Pre-Build Actions
Pre-build actions run once before any files are processed. :summon works the same way — you can pass a single-item list to run just one action:
ret | :summon(pre_ctx, [act_name]) if !ret.nix? pre_ctx |= ret xx
ret | :summon(pre_ctx, [act_name]) if !ret.nix? pre_ctx |= ret xx
Signature
:summon(value, [action_names])
:summon(value, [action_names])
| Argument | Type | Description |
|---|---|---|
value |
any | The starting value to thread through the pipeline. |
action_names |
array of strings | Ordered list of action names to call. Namespaced names ("ns::action") are supported. |
Errors
Passing a non-array as the second argument raises a type error:
:summon(ctx, "markdown_core::render") /// error: T0205 type-mismatch: second argument must be an array of strings
:summon(ctx, "markdown_core::render") /// error: T0205 type-mismatch: second argument must be an array of strings
Passing a non-string inside the array raises a type error:
:summon(ctx, [42]) /// error: T0205 type-mismatch: each event must be a string action name
:summon(ctx, [42]) /// error: T0205 type-mismatch: each event must be a string action name
Wrong argument count raises a wrong-arity error:
:summon(ctx) /// error: R0301 wrong-arity: expected 2, got 1
:summon(ctx) /// error: R0301 wrong-arity: expected 2, got 1