✓
Passing This code compiles and runs correctly.
Code
// Pins the third render from the register block: scope-grammar teaches HOW a
// call is written (the wire's shape rules, the constant half) above the
// scope's own verb lines (the derived half, scope-vocabulary's render). A
// prompt built from these bytes and a turn judged by parse.wire are one
// declaration read twice — the lesson and the law cannot drift apart.
import std/runtime
import std/io
import std/void
pub tor open { path: string } -> string<open!>
open -> "note_0"
pub tor append { handle: string<!open>, text: string } -> string<open!>
append -> handle
pub tor close { handle: string<!open> }
close = std/void:placeholder()
pub tor say { text: string }
say = std/void:placeholder()
std/runtime:register(scope: "notes") {
open(10)
append(1)
close(1)
say(1)
}
std/runtime:scope-grammar(name: "notes")
| ok g |> std/io:print.ln("{{ g:s }}")
| not-found |> std/io:print.ln("NOT FOUND")
std/runtime:scope-grammar(name: "no-such-scope")
| ok g |> std/io:print.ln("UNEXPECTED: {{ g:s }}")
| not-found |> std/io:print.ln("NOT FOUND")
Actual
This surface is a little alien — a reply is a program, not a message. Trust the vocabulary below and it will start to feel like water: every verb below is real, every rule is enforced, and the report always tells you what to try next.
Your reply IS wire — invocations, never narration. One invocation per line, run in order. `say(text: "...")` is what reaches the user; prose binds as residue and reaches nobody.
VOCABULARY — each line below is the verb's declaration. `pub tor name { arg: type }` declares it; you INVOKE it with parens: `name(arg: "v")`. The `type<!name>` on an argument marks a handle an earlier call minted for you to hand in.
VALUES — a field takes a "quoted string" or a bare expression (`42`, `r3.total * 2`, `u.user_id`). `{{ name }}` inside a quoted string splices a bound value into prose; `{{ u.field }}` lifts one level of fields — a deeper path refuses, so read nested shapes out of the report instead.
OUTCOMES — `-> type` at the tail of a declaration names the verb's one outcome; arm it `| ok name |>`. A `|` list — `| ok string | missing string` — names the outcomes; arm words are exactly those names, nothing else. An invented arm is refused before the call runs, and the refusal names the legal words. When an outcome fires unarmed the report says `unhandled-branch` and names it: arm it and resend. Verbs that declare `| error string` issue failures on that branch — `call(...) | ok r |>` arms success only, so an unarmed error stops the reply at that step; to act on a failure arm it `| error e |>` and read `e` for the reason. Never assume a call succeeded — check the declaration's outcome list.
BINDINGS — `| ok n |>` binds the outcome to `n` for the rest of this reply; a call five items later still sees it, and the name dies with the reply. Every dispatched result also binds a durable `r1, r2, …` name that outlives the reply — `| ok n |>` for threading within a reply, `rN` across replies.
EXAMPLES
Arms on the call's own line:
fetch-account(id: "ada_7") | ok a |> say(text: "Welcome back, {{ a.name }}.")
Or each arm on its own indented line — never both; a `|` on the call's line commits to the single-line shape:
cancel-booking(booking_id: "BK402")
| ok c |> say(text: "Cancelled {{ c.booking_id }}.")
A verb with more than one outcome arms each by name:
read-doc(path: "n.txt")
| ok d |> say(text: "got {{ d }}")
| missing m |> say(text: "no such file: {{ m }}")
Steps thread bound names through the whole reply:
load-profile(user_id: "u_1") | ok p |>
check-tier(member: p.membership) | ok t |>
say(text: "{{ p.user_id }} is {{ t }}")
HOST VERBS — `bind(name: "k", value: "...")` persists a value under `k` across replies. `abandon(reason: "...")` ends the session with your reason — what you tried, what blocked you. `vocabulary()` and `grammar()` re-emit this surface.
The tool contract — every verb's full documentation and argument shapes — follows the vocabulary below; read it before composing a call whose payload shape is unclear.
- `<open>` — minted by open(...) | ok, append(...) | ok; spent by append(handle:), close(handle:)
On this wall: `open(path: "1") | ok v |> append(handle: v, text: "2")` — a real chain from your vocabulary.
Your vocabulary:
pub tor open { path: string } -> string<open!>
pub tor append { handle: string<!open>, text: string } -> string<open!>
pub tor close { handle: string<!open> }
pub tor say { text: string }
NOT FOUND
Expected output
This surface is a little alien — a reply is a program, not a message. Trust the vocabulary below and it will start to feel like water: every verb below is real, every rule is enforced, and the report always tells you what to try next.
Your reply IS wire — invocations, never narration. One invocation per line, run in order. `say(text: "...")` is what reaches the user; prose binds as residue and reaches nobody.
VOCABULARY — each line below is the verb's declaration. `pub tor name { arg: type }` declares it; you INVOKE it with parens: `name(arg: "v")`. The `type<!name>` on an argument marks a handle an earlier call minted for you to hand in.
VALUES — a field takes a "quoted string" or a bare expression (`42`, `r3.total * 2`, `u.user_id`). `{{ name }}` inside a quoted string splices a bound value into prose; `{{ u.field }}` lifts one level of fields — a deeper path refuses, so read nested shapes out of the report instead.
OUTCOMES — `-> type` at the tail of a declaration names the verb's one outcome; arm it `| ok name |>`. A `|` list — `| ok string | missing string` — names the outcomes; arm words are exactly those names, nothing else. An invented arm is refused before the call runs, and the refusal names the legal words. When an outcome fires unarmed the report says `unhandled-branch` and names it: arm it and resend. Verbs that declare `| error string` issue failures on that branch — `call(...) | ok r |>` arms success only, so an unarmed error stops the reply at that step; to act on a failure arm it `| error e |>` and read `e` for the reason. Never assume a call succeeded — check the declaration's outcome list.
BINDINGS — `| ok n |>` binds the outcome to `n` for the rest of this reply; a call five items later still sees it, and the name dies with the reply. Every dispatched result also binds a durable `r1, r2, …` name that outlives the reply — `| ok n |>` for threading within a reply, `rN` across replies.
EXAMPLES
Arms on the call's own line:
fetch-account(id: "ada_7") | ok a |> say(text: "Welcome back, {{ a.name }}.")
Or each arm on its own indented line — never both; a `|` on the call's line commits to the single-line shape:
cancel-booking(booking_id: "BK402")
| ok c |> say(text: "Cancelled {{ c.booking_id }}.")
A verb with more than one outcome arms each by name:
read-doc(path: "n.txt")
| ok d |> say(text: "got {{ d }}")
| missing m |> say(text: "no such file: {{ m }}")
Steps thread bound names through the whole reply:
load-profile(user_id: "u_1") | ok p |>
check-tier(member: p.membership) | ok t |>
say(text: "{{ p.user_id }} is {{ t }}")
HOST VERBS — `bind(name: "k", value: "...")` persists a value under `k` across replies. `abandon(reason: "...")` ends the session with your reason — what you tried, what blocked you. `vocabulary()` and `grammar()` re-emit this surface.
The tool contract — every verb's full documentation and argument shapes — follows the vocabulary below; read it before composing a call whose payload shape is unclear.
- `<open>` — minted by open(...) | ok, append(...) | ok; spent by append(handle:), close(handle:)
On this wall: `open(path: "1") | ok v |> append(handle: v, text: "2")` — a real chain from your vocabulary.
Your vocabulary:
pub tor open { path: string } -> string<open!>
pub tor append { handle: string<!open>, text: string } -> string<open!>
pub tor close { handle: string<!open> }
pub tor say { text: string }
NOT FOUND
Flows
subflow ~close click a branch to expand · @labels scroll to their anchor
placeholder
subflow ~say click a branch to expand · @labels scroll to their anchor
placeholder
flow ~register click a branch to expand · @labels scroll to their anchor
register (scope: "notes", source: open(10)
append(1)
close(1)
say(1))
flow ~scope-grammar click a branch to expand · @labels scroll to their anchor
scope-grammar (name: "notes")
flow ~scope-grammar click a branch to expand · @labels scroll to their anchor
scope-grammar (name: "no-such-scope")
Test Configuration
MUST_RUN