This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.

Supervisor

import std/supervisor

Koru Standard Library: Supervision

supervisor.kz · 2 tors

Koru Standard Library: Supervision · 64 more lines
Koru Standard Library: Supervision Failure-handling as a compile-time fact, in the `stored`/`captured` family: the arm declares that its producing call is supervised, the transform elaborates the declaration into an ordinary bounded retry loop — the language's own `#`/`@` fold. There is no supervisor object, no registry, no runtime service: the policy is a datablock read at compile time and the mechanism is a generated step tor plus a labeled fold loop. worker(n) | ok v |> … | boom f |> std/supervisor:supervised | retry t when t < 3 or, with an explicit re-entry call and terminal produce: | boom f |> std/supervisor:supervised | retry t when t < 3 |> worker(n: f + 4) | exhausted => boom f The datablock `{ restart: N [, args: { f: expr }] }` is the terse spelling of the same guarantee — `restart: N` is `| retry t when t < N`, and `args:` is the implicit re-entry call's argument map. Under `[with]std/supervisor` the qualifier drops, but the bare name collides with produce-branch spelling — write `supervised()` there. SEMANTICS (pinned by 320_151's hand-written twin): - `restart: N` means N retries after the initial call — the producing call runs at most N+1 times. - Re-entry targets the producing call; unmapped arguments keep the LAST attempt's values (the step's ambient inputs), not the site's. - Every non-supervised branch proceeds exactly as written at the site: the sibling arms dispatch on the generated step's vocabulary, so a retried `ok` flows through the same arm set as a first-call `ok`. - Exhaustion forwards the LAST child outcome upward in kind — a `| err` stays `| err`, a `?!boom` stays a panic. The supervisor absorbs and defers; it never rewrites an outcome's kind. - The retry counter rides as a step input named after the retry arm's own binding (`| retry t` → field `t`) — `when` conditions and re-entry args resolve verbatim, no shadowing, no `__fail` plumbing. ELABORATION — the language's own `#`/`@` fold, no generated proc: connect = dial(port) tor __sup_step_L<n> { port, t } | ok => ok | ok | refused | refused |> supervised | __more { port, t } | retry t when t < 5 |> dial(port: port + 1) ==> __sup_step_L<n> = dial(port) | exhausted => refused | ok => ok | refused when t < 5 => __more { port: port+1, t: t+1 } | refused => refused connect = #__sup_L<n> __sup_step_L<n>(port, t: 0) | __more s |> @__sup_L<n>(s.port, s.t) | ok => ok | refused => refused The step's `port` IS the failing attempt's argument — ambient reader semantics, not threading — so `port + 1` reads the failed port. Branch shapes pass through verbatim: a void branch stays void inside the fold, so `| ok p` on a `| ok` declaration refuses at the site exactly as it would without `supervised`.

~part h koru_std/supervisor.h.kz

Koru Standard Library: the `h` part of supervisor.kz — the shared emission helpers. Joined via `~part h` in supervisor.kz; merged into the supervisor module at load. `std`/`ast` arrive at module scope from the other parts — a local import here would shadow them.

~part decl koru_std/supervisor.decl.kz

Koru Standard Library: the `decl` part of supervisor.kz — policy declaration parsing. Joined via `~part decl` in supervisor.kz; merged into the supervisor module at load. Declarations are DATA — they live in the supervised block, not in arm position (`| [key: value]` refuses pointing here). `within: N unit` is the wall-clock min-spacing throttle; `policy: Name` delegates the decision rules to a named same-module tor. `ticks` is pinned vocabulary awaiting its supplier — an enclosing signal model's steppable clock.

~part policy koru_std/supervisor.policy.kz

Koru Standard Library: the `policy` part of supervisor.kz — delegated policy resolution and emission. Joined via `~part policy` in supervisor.kz; merged into the supervisor module at load. `std`, `ast`, `errors`, and `H` arrive at module scope from the sibling parts. ---- `policy: Name` — delegated policy ------------------------------------ The block delegates the decision to a named same-module tor consuming the failure stream under the arm vocabulary — `{ f: <payload>, t: i64 }`, `f` optional, `t` required (the bound channel) — and producing the SAME vocabulary the arms spell: `| retry { <child input fields> }` re-enters with adapted args, `| exhausted` is terminal (payload → same-branch produce, bare → forward the last failure in kind). `within` composes — a declined retry fails the keep-alive contract and the pending failure proceeds upward.

~part fold koru_std/supervisor.fold.kz

Koru Standard Library: the `fold` part of supervisor.kz — the elaboration itself: the `supervised` transform decl+proc and the generated-AST constructors it builds the step tor and `#`/`@` fold from. Joined via `~part fold` in supervisor.kz; merged into the supervisor module at load. `std`/`ast`/`H`/`functional` arrive at module scope from the other parts — local imports here would shadow them.

supervised

keywordcomptimetransform koru_std/supervisor.fold.kz:162

~part home koru_std/supervisor.home.kz

Koru Standard Library: the `home` part of supervisor.kz — the home-branch lookup the fold runs when a site sits inside a module_decl. Joined via `~part home` in supervisor.kz; merged into the supervisor module at load. `H`, `std`, and `ast` arrive at module scope from the other parts. The enclosing tor's declared `| <site.branch>` for a site inside a module_decl — the same lookup the main body runs at program top level.

~part explain koru_std/supervisor.explain.kz

Koru Standard Library: the `explain` part of supervisor.kz — joined via `~part explain`; members land in koru_supervisor. `supervised` is the most elaborating surface in std: the arm you write retargets the call that produced its branch (retarget_producer), the outcome dispatch moves to a generated step tor, and every name inside a re-entry expression resolves in the STEP's scope — the attempt's inputs and the retry counter, not the caller's. The explainer lifts exactly that: per site it reports the producer, the child's declared vocabulary (a void branch stays void), the step tor and `#`/`@` fold the site becomes, the policy it read, and which names the re-entry expressions actually rebind. Then it shows the work: the program is cloned, the real transform pass runs over the clone, and the generated step decl + the retargeted home flow print through the canonical AST printer (src/ast_printer.zig). The elaborated view cannot drift from the transform — it IS the transform's output.

explain-supervised

comptimeexplainer koru_std/supervisor.explain.kz:190