056 mounted scope

✓ Passing This code compiles and runs correctly.

Code

input.k

Supporting Files

module/module.zig
module/module_abi.zig
session.kz

Actual

open ok (holds 1, bound r1)
mounted scope: spike
touch ok -> {"branch":"","value":"touched:first-note"}
seal ok (holds 2, bound r3)
unseal ok (holds 1, bound r4)
reunseal refused: 'stamp' wants a live <sealed> to spend — 'h:Stamp:5fcd62' was already spent — an obligation discharges once. Mint one through a verb whose signature ends '-> <sealed!>'
vocabulary:
pub tor open { path: string } -> *Note<opened!>
pub tor close { handle: *Note<!opened> }
pub tor touch { handle: *Note<opened> } — read a held note (borrow, mounted)
pub tor seal { label: string } — mint a sealed stamp (mounted)
pub tor unseal { stamp: *Stamp<!sealed> } — discharge a sealed stamp (mounted)
vocabulary()
grammar()
bind(name: string, value: string)
note(text: string) — speaks to the observer, not the user: reasoning, plans, and "why I'm stuck" go here
abandon(reason: string) — ends the session with your reason: what you tried, what blocked you
r1
r3
r2
r4
grammar:
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.
- `<opened>` — minted by open(...) | ok; spent by close(handle:)
On this wall: `open(path: "1") | ok v |> close(handle: v)` — a real chain from your vocabulary.

Your vocabulary:
pub tor open { path: string } -> *Note<opened!>
pub tor close { handle: *Note<!opened> }
- `<sealed>` — minted by seal(...) | ok; spent by unseal(stamp:)
pub tor touch { handle: *Note<opened> } — read a held note (borrow, mounted)
pub tor seal { label: string } — mint a sealed stamp (mounted)
pub tor unseal { stamp: *Stamp<!sealed> } — discharge a sealed stamp (mounted)
vocabulary()
grammar()
bind(name: string, value: string)
note(text: string) — speaks to the observer, not the user: reasoning, plans, and "why I'm stuck" go here
abandon(reason: string) — ends the session with your reason: what you tried, what blocked you
seal2 ok (holds 2, bound r5)
held before hang-up: 2
[BRIDGE] Invoked 'unseal' for handle 'h:Stamp:e5f666' [spike:sealed]
[BRIDGE] Invoked 'close' for handle 'h:Note:01947a' [app.session:opened]
hang-up: clean

Expected patterns

Each line is a regex that must match the program output.

^mounted scope: spike$
^open ok \(holds 1, bound r1\)$
^touch ok -> \{"branch":"","value":"touched:first-note"\}$
^seal ok \(holds 2, bound r3\)$
^unseal ok \(holds 1, bound r4\)$
^reunseal refused: 'stamp' wants a live <sealed> to spend — 'h:Stamp:[0-9a-f]+' was already spent — an obligation discharges once\. Mint one through a verb whose signature ends '-> <sealed!>'$
^pub tor touch \{ handle: \*Note<opened> \} — read a held note \(borrow, mounted\)$
^pub tor seal \{ label: string \} — mint a sealed stamp \(mounted\)$
^pub tor unseal \{ stamp: \*Stamp<!sealed> \} — discharge a sealed stamp \(mounted\)$
^- `<sealed>` — minted by seal\(\.\.\.\) \| ok; spent by unseal\(stamp:\)$
^seal2 ok \(holds 2, bound r5\)$
^held before hang-up: 2$
^\[BRIDGE\] Invoked 'unseal' for handle 'h:Stamp:[0-9a-f]+' \[spike:sealed\]$
^\[BRIDGE\] Invoked 'close' for handle 'h:Note:[0-9a-f]+' \[app.session:opened\]$
^hang-up: clean$

Flows

subflow ~step click a branch to expand · @labels scroll to their anchor
run (br, source)
subflow ~step-show click a branch to expand · @labels scroll to their anchor
run (br, source)
subflow ~mount-spike click a branch to expand · @labels scroll to their anchor
mount (br, path)
subflow ~show-vocab click a branch to expand · @labels scroll to their anchor
vocabulary (br)
subflow ~show-grammar click a branch to expand · @labels scroll to their anchor
grammar (br)
subflow ~show-held click a branch to expand · @labels scroll to their anchor
get-handles (br)
flow ~create click a branch to expand · @labels scroll to their anchor
create (id: "mounted-1", scope: "notes", introspection: true)

Test Configuration

MUST_RUN

koru.json: