---
title: "A tour of Hew 0.6: files, concurrent work and services"
description: "Start with a small file tool, then follow the language features that let it grow into a service with owned resources, workers and typed protocols."
source: "https://hew.sh/blog/2026/10/hew-06-language-tour"
---

A file tool starts simply: read an input, calculate something, print a result. Then there are several inputs. One read fails. A job takes too long. Eventually the tool becomes a service, and now it has a queue, connections to close and workers to restart.

That is a useful way to look at the additions and expanded forms since Hew 0.5.6. Actors and machines already existed; this tour also shows how existing features compose as a program grows. An ordinary function can become concurrent work, a value can become a message, and cleanup follows the work through both.

This tour covers three points in that progression:

| Version | What the examples describe |
| --- | --- |
| **0.6.0, released** | The file tool and the main language tour below. The [release notes](https://github.com/hew-lang/hew/releases/tag/v0.6.0) and [migration guide](https://github.com/hew-lang/hew/blob/v0.6.0/docs/migrations/v0.6.0.md) describe the published SDK. |
| **0.6.1, released** | Generic closures, compile-time inputs, macros, confinement and the other additions in the 0.6.1 section. See the [0.6.1 release notes](https://github.com/hew-lang/hew/releases/tag/v0.6.1) and the examples below. |
| **Development preview** | The final section follows the [development source](https://github.com/hew-lang/hew/tree/a340281056). Those examples are part of the 0.6.2 preview and require that development toolchain. |

Jump to [data](#make-the-data-easy-to-work-with), [failures](#keep-the-successful-path-in-view), [ownership](#put-ownership-in-the-interface), [tasks](#choose-where-work-runs-concurrently), [actors](#give-a-service-its-own-state), [streams](#process-a-flow-without-collecting-everything-first), [machines](#write-the-protocol-as-a-machine), [0.6.1 additions](#what-061-adds), or [development previews](#development-preview-compose-the-same-operations-further).

Run the file and service examples with the native SDK. The [sandbox capability matrix](https://github.com/hew-lang/hew/blob/v0.6.0/docs/wasm-capability-matrix.md) lists the separate browser and WASI target coverage.

## Start with two files

Save this complete 0.6.0 program as `sizes.hew`:

```hew
import std.fs;

fn byte_count(path: string) -> i64 fails fs.IoError {
    let contents = fs.read_bytes(path)?;
    contents.len()
}

fn main() fails fs.IoError {
    let results = await fork [
        byte_count("first.txt"),
        byte_count("second.txt"),
    ];
    for result in results { println(result?); }
}
```

Create the inputs and run it:

```bash
printf 'Hew\n' > first.txt
printf 'hello\n' > second.txt
hew run sizes.hew
```

It prints `4` and `6`. The calls run concurrently, and the results stay in input order. Each call keeps its own typed read error, which the loop can propagate with `?`. This version reads each whole file into memory; a streaming version makes more sense for large inputs.

There is quite a bit of language in that small program. The rest of the tour pulls it apart, then adds the pieces a longer-lived service needs. Later snippets are excerpts: names such as `load`, `fetch` and `save` stand for application functions where their implementation is beside the point.

## Make the data easy to work with

### Modules, records and the names between them

An import follows the module path with dots. `import std.fs` makes `fs` available; `import std.encoding.json` makes `json` available. Selective imports name the items in braces, and generic application uses the same `<T>` spelling on types and calls:

```hew
import std.encoding.json;

type Summary {
    path: string;
    bytes: i64;
}

enum JobState {
    Waiting;
    Finished { summary: Summary; }
}

package fn empty_summary(path: string) -> Summary {
    Summary { path, bytes: 0 }
}
```

`type` declares a record. Fields and enum variants end with semicolons; a value's field list uses commas. `Summary { path, bytes: 0 }` uses the local `path` binding directly. A known expected type lets a variant be written as `.Waiting` or `.Finished { summary }`; `JobState.Waiting` supplies the type explicitly.

The `package` modifier makes the helper available within its package. An unmarked declaration stays private to its module, while `pub` exposes it to importing packages. The [package guide](/docs/packages) covers how those modules become a reusable dependency.

### Change a value while keeping the earlier snapshot

A report often needs a few variations of the same input. Record updates and vector spreads keep that code close to the data:

```hew
let first = Summary { path: "first.txt", bytes: 4 };
let renamed = Summary { ..first, path: "archive/first.txt" };

let earlier = [first];
let reports = [..earlier, renamed];
var revised = reports;
revised.push(Summary { path: "second.txt", bytes: 6 });
```

The earlier values remain usable. `var` permits changes to that binding; it does not turn every copy into an alias of shared mutable storage. Ordinary values have snapshot semantics, and `clone value` makes duplication explicit where that is useful. Resource ownership has a different rule, which becomes important when the data contains an open file or connection.

Definite assignment also lets a binding receive its initial value along different control-flow paths. The checker requires every path reaching a read to have initialized it, so there is no need to invent a placeholder value just to satisfy a declaration.

```hew
fn choose(primary: bool) -> string {
    let path: string;
    if primary { path = "first.txt"; }
    else { path = "second.txt"; }
    path
}
```

The [type guide](/docs/types) introduces the declarations, and the [0.6.0 language guide](https://github.com/hew-lang/hew/blob/v0.6.0/docs/hew-language-guide.md) has the complete record, spread and snapshot examples.

## Keep the successful path in view

A missing setting, a failed read and a programming fault need different handling. Hew gives ordinary absence an `Option`, returned application errors a `Result`, and a declared failure path the `fails` clause used by `byte_count`.

```hew
fn positive_limit(value: i64) -> i64 fails string {
    if value <= 0 {
        return error "the limit must be positive";
    }
    value
}

let limit = positive_limit(configured_limit) handle message {
    println(message);
    10
};
```

The function body returns its success value normally. `return error` takes the declared failure path, while `handle` supplies local recovery. A caller that also declares `fails` can use `?` to propagate the error instead. When accessing a successful result immediately, grouping makes the operation clear: `(load()?).len()`.

Conditions can combine a successful pattern with tests on what it bound:

```hew
if let .Some(limit) = requested_limit && limit > 0 {
    println(limit);
}

let .Some(path) = requested_path else {
    return;
};
```

The first form avoids nested `if` blocks. The second keeps the binding available after the check because its `else` path leaves the current flow. For a chain of optional data, `user?.address?.city` carries absence through the member accesses, and `??` provides a default at the end.

Cleanup belongs beside the operation that needs it. A regular `defer` runs on scope exit; `defer err` runs when the scope exits through failure, a fault or cancellation. In an application that creates a temporary output, the shape is:

```hew
defer err { remove_temporary_output(); }
write_output()?;
publish_output()?;
```

Returning `.Err(...)` as ordinary data from a `-> Result<...>` function is still an ordinary return. Use `fails` and its failure operations when that is the control flow the function means to express.

## Put ownership in the interface

An open connection has a lifetime that a string does not. A `#[resource]` type names its cleanup operation, and `consume` says when an operation takes the owner:

```hew
#[resource]
type Connection {
    descriptor: i64;
}

impl Connection {
    fn close(consume self) {
        release_descriptor(self.descriptor);
    }
}
```

Here `release_descriptor` is the application's descriptor-release function. A live resource closes when its scope exits, including cleanup after failure or cancellation. An explicit close consumes it earlier.

For a transaction that must be committed or rolled back, `#[linear]` requires an explicit consuming operation on every exit path. It has no automatic close. That distinction makes an unfinished transaction a compile error rather than an implicit choice of outcome.

Function values can state ownership and invocation requirements too. `fn(...) -> T` is repeatedly callable through a read-only value, `fn[var](...) -> T` needs a mutable callable place, and `fn[once](...) -> T` consumes the callable when invoked. Adding `clone` promises independent duplication, while `suspends` permits the call to wait. These distinctions matter when a callback keeps a resource or mutable state.

```hew
fn apply_twice(f: fn[clone](i64) -> i64, value: i64) -> i64 {
    f(f(value))
}

fn read_with(load: fn[suspends](string) -> string, path: string) -> string {
    load(path)
}
```

A private mutable capture is written where the closure is created:

```hew
let count = 0;
var next: fn[var, clone]() -> i64 = capture(var count) || {
    count += 1;
    count
};
```

The counter belongs to this closure; it does not mutate the original binding. With an owned `connection`, a one-use callback can transfer and eventually close it:

```hew
let finish: fn[once]() -> i64 = move || {
    connection.close();
    0
};
```

`move` transfers captured ownership. Consuming that capture makes this callback call-once. The [ownership examples in the language guide](https://github.com/hew-lang/hew/blob/v0.6.0/docs/hew-language-guide.md) show resources, linear values and consuming methods together.

## Choose where work runs concurrently

The file tool used `await fork [...]` because all its jobs had the same shape. The smaller building blocks are useful as soon as preparation and reporting take time too:

```hew
let first = fork byte_count("first.txt");
let prepared = fork {
    let text = load_template();
    prepare_report(text)
};

let bytes = await first;
let report = await prepared;
```

`fork call(...)` and `fork { ... }` produce tasks. An ordinary call waits for its result; `await` joins a task that was started separately. Task results keep their declared types, including an ordinary `Result` when a job can fail.

There are several useful ways to collect work:

| Work to collect | Form |
| --- | --- |
| Calls with one result type | `await fork [first(), second()]` |
| Calls with different result types | `await fork (read_header(), count_rows())` |
| A vector of task handles already built by the program | `await tasks` |

Vector results stay in vector order. A task belongs to its enclosing lifetime even if the program discards its handle, so discarding a handle is not a way to detach work.

### Race a result, or select something ready

A first-response operation can join immediately or keep the race task for later:

```hew
let response = await race [primary.fetch(key), replica.fetch(key)];

let pending = race [primary.fetch(other_key), replica.fetch(other_key)];
prepare_display();
let other_response = await pending;
```

The inputs can also be task handles that the program has already created:

```hew
let primary_task = fork primary.fetch(key);
let replica_task = fork replica.fetch(key);
let response = await race [primary_task, replica_task];
```

`race` chooses the first normal completion, including an ordinary error value. It cancels and drains the losers before making the winning result available. That cleanup does not undo an external effect or retract a handler that another actor has already started.

A `scope` groups child work. Add `within` to place a deadline over the group and attach `handle` to recover after its work has drained:

```hew
let report = scope within 2s {
    let work = fork build_report();
    await work
} handle failure {
    cached_report()
};
```

`select` is useful when a task, an incoming stream item or a timer could determine the next step. With an existing task `job` and stream `input`, a selection can look like this:

```hew
select {
    value from job => show_result(value),
    item from input.recv() => show_item(item),
    after 100ms => show_progress(),
};
```

The selection does the waiting, so arm sources do not contain `await`. An existing task that loses this selection remains part of its scope and can still be joined. That is a useful difference from handing work to a race. The [selection comparison](/docs/compare/select-join) and [fan-out/fan-in example](/docs/compare/fan-out-fan-in) put these choices side by side.

## Give a service its own state

An actor is useful when requests need to share a history: counters, a cache, a connection or the current stage of a job. Its handlers see that state one turn at a time.

```hew
actor Totals {
    var bytes: i64;

    receive fn add(amount: i64) {
        bytes += amount;
    }

    receive fn read() -> i64 {
        bytes
    }
}

let totals = spawn Totals { bytes: 0 };
totals.add(4).expect("record bytes");
println(totals.read().expect("read total"));
```

The keyed spawn `spawn Totals { bytes: 0 }` supplies the named state field; construction keys can also supply `init` parameters. A call on the resulting handle waits for that handler's completion and returns its actor result. `fork totals.read()` starts that completion call concurrently. The actor type is also the type of its handle, so it can appear directly in a field or parameter.

### Separate submission from completion

Some callers only need to submit work. `mailbox(target)` gives them a one-way view; `policy(target)` keeps completion semantics while choosing what to do when admission is full:

```hew
let inbox = mailbox(totals, on_full: .DropNewest);
let delivery = inbox.add(4);

let completion = policy(totals, on_full: .Reject).add(6);
```

Submission reports delivery, while a completion call reports what happened to the handler. A `.Wait` policy can suspend while waiting for capacity. A `.Reject` policy returns the unaccepted request, and a `.DropNewest` submission can discard the incoming message. The actor's own mailbox declaration also controls admission and any replacement of queued submissions.

A rejected completion request keeps its owned payload. Its `failure.message.retry()` consumes that request and tries the original destination; `failure.message.to(other)` consumes it and redirects to a compatible handler. A request whose handler already ran has no equivalent safe retry guarantee.

The default matters: an ordinary handle waits for completion and capacity. A mailbox view inherits `.Reject` from an actor declared with `overflow fail`; otherwise it defaults to `.Wait`. The [backpressure guide](/docs/compare/backpressure) explains the delivery outcomes and queue policies.

### Start, stop and restart deliberately

An actor's `init` body initializes state before normal delivery. `#[on(start)]` and `#[on(stop)]` place lifecycle work beside its handlers, `#[on(crash)]` handles the fault lifecycle, and `#[every(1s)]` schedules a parameterless receive handler periodically.

Stopping has a request and a join, just as starting concurrent work does:

```hew
stop(totals);
stopped(totals);
```

`stop` requests graceful shutdown; `terminate` requests cancellation. Both return after the request, and `stopped` waits for terminal cleanup. A handler call finishing and the actor finishing are separate events.

For a small actor with one operation, an anonymous actor can be enough:

```hew
let factor = 3;
let scale = actor |n: i64| -> i64 { n * factor };
println(scale(7).expect("scale"));
stop(scale);
stopped(scale);
```

Its handle has an `actor(i64) -> i64` shape and can be stored or passed like other values. The [actor guide](/docs/actors) covers named and anonymous actors, initialization and lifecycle operations.

### Keep worker roles stable across restarts

Once a service owns several workers, a supervisor can declare their construction and restart policy. This fragment assumes the application has a `Worker` actor:

```hew
supervisor Farm {
    strategy: simple_one_for_one;
    intensity: 5 within 60s;

    pool workers: Worker { id: 0 } count: 4;
}
```

A named `child` gives a stable supervised role; a `pool` gives indexed roles for a group. Code can keep the role while the supervisor replaces its actor incarnation, and `restarted(role)` waits for a replacement where the application needs that handoff. Pool members can restart independently. Stopping the supervisor requests shutdown of its children, and `stopped` joins their cleanup too.

For a `Worker` with an `id_of` handler, the same helper accepts a named child or a pool member. Call it when waiting for a known restart:

```hew
fn read_after_restart(worker: ChildRef<Worker>) -> i64 {
    restarted(worker);
    worker.id_of().expect("replacement worker")
}

let farm = spawn Farm;
let role: ChildRef<Worker> = farm.workers[0];
```

The [supervision comparison](/docs/compare/supervision) shows the corresponding actor declarations and calls.

## Process a flow without collecting everything first

The whole-file example is convenient, but a pipeline needs a way to read and write incrementally. Hew's `Sink<T>` and `Stream<T>` provide the two ends of a pipe:

```hew
import std.stream;

let (output, input) = stream.pipe<string>(4).expect("create pipe");
output.send("first row").expect("send row");
output.finish();

for row in input {
    println(row);
}
```

`send` waits for capacity; `try_send` can report a full pipe immediately. `recv` returns an `Option`, where `None` means the stream has ended. An empty string or empty byte chunk is still an item. File and socket adapters use the same stream operations, so the processing loop need not know where its input began.

A generator is the local, lazy way to produce a sequence:

```hew
gen fn labels(prefix: string, count: i64) -> string {
    for index in 0 .. count {
        yield f"{prefix}:{index}";
    }
}

let short = gen { yield "first"; yield "second"; };
for label in labels("row", 3) {
    println(label);
}
```

Calling a generator constructs its state; iteration drives its body. Both generator functions and `gen { ... }` blocks can hold local state across yields. A generator declared with `fails E` yields `Result` items for the consumer to handle, and stopping early releases the generator's owned state. The [pipeline example](/docs/compare/actor-pipeline) and [language guide](https://github.com/hew-lang/hew/blob/v0.6.0/docs/hew-language-guide.md) cover streaming and generator composition.

## Write the protocol as a machine

A service often has states that permit different inputs. Keeping that logic in a machine makes the protocol visible in one place, with typed outputs for the application to act on:

```hew
machine Meter {
    events {
        Reading { value: i64; }
    }
    emits {
        Alarm { value: i64; }
    }
    state Watching { peak: i64; }

    on Reading: Watching => Watching when event.value > state.peak {
        emit Alarm { value: event.value };
        Watching { peak: event.value }
    }
    on Reading: Watching => Watching { state }
}

var meter: Meter = .Watching { peak: 0 };
let report = meter.step(.Reading { value: 7 });
```

`step` updates the machine and returns a report containing the transition disposition and emitted outputs. The surrounding actor or function can inspect `report.outputs` and perform the actual I/O; the transition describes the state change.

Machines can take type parameters for their payloads and const parameters for fixed values such as a capacity. Composite states group related states, and entry/exit hooks keep shared transition behaviour with the state it belongs to. The [machine guide](/docs/machines) introduces those forms. More deeply nested transitions and explicit re-entry appear in the 0.6.1 section below.

## Share behaviour and exchange typed data

### Traits can describe what a producer yields

An associated type lets a trait name a result that varies with the implementation. For example, a producer can define `type Output` and use `Self.Output` in its methods. Generic code keeps the concrete type, while a `dyn Trait` value carries a runtime choice of implementation.

```hew
trait Producer {
    type Output;
    fn output(self) -> Self.Output;
}

type Number {}
impl Producer for Number {
    type Output = i64;
    fn output(self) -> i64 { 1 }
}
```

That dynamic value can be returned from a function or stored in a collection, which is useful for a set of renderers, commands or handlers selected from configuration. The caller uses the trait's methods without building a manual enum for every implementation. The [type guide](/docs/types) covers traits; the [language guide's associated-type examples](https://github.com/hew-lang/hew/blob/v0.6.0/docs/hew-language-guide.md) show the declarations and implementations.

For example, a common naming interface can hide the returned implementation:

```hew
trait Named { fn name(self) -> string; }
type Person { label: string; }
impl Named for Person {
    fn name(self) -> string { self.label }
}
fn make_named(label: string) -> dyn Named { Person { label } }

let entries: Vec<dyn Named> = [make_named("ada"), make_named("lin")];
for entry in entries.into_iter() { println(entry.name()); }
```

### Give serialized fields a stable identity

A typed protocol starts with the fields that must survive being stored or sent:

```hew
#[wire]
type JobSummary {
    id: u64 @1;
    path: string @2;
    note: Option<string> @3 optional;
}
```

The numeric tags are stable field identities. `optional` permits the key to be absent. A required `Option<string>` instead requires the key while allowing its value to be null, which is a different contract when another program sends the data.

JSON, CBOR, YAML, TOML and MessagePack expose typed `encode` and `decode<T>` operations. For example, `json.decode<JobSummary>(text)` reports a typed decoding error when the document does not fit. Format limits still apply: TOML has no null value, so a nullable schema needs a representation that TOML can express. The [wire-type comparison](/docs/compare/wire-types) explains field identity, compatibility and presence.

### Keep blocking foreign work off scheduler workers

Native integrations sometimes need a C function that blocks. Put `#[offload]` on its extern declaration to run that call on the blocking pool while the Hew caller suspends:

```hew
extern "C" {
    #[offload]
    fn render_report(template: string, rows: Vec<string>) -> string;
}
```

The caller still makes an ordinary `unsafe` call. Offloaded arguments and results must satisfy the supported copyable boundary; consuming resource handles and raw pointers are refused. If the caller's deadline expires, the foreign call may continue on the pool and discard its eventual result. That matters for a function that writes files or performs another external action.

## Test the program at the level it is used

`#[test]` marks an ordinary test. Give the test concrete data parameters and the runner generates cases, shrinks failures and reports a reproducible counterexample:

```hew
#[test]
fn a_snapshot_keeps_its_values(values: Vec<i64>) {
    let before = values;
    var after = values;
    after.push(7);
    assert(after.len() == before.len() + 1);
}
```

`#[should_panic]` checks an expected fault, `#[ignore]` leaves a test out of normal runs, and `#[serial]` coordinates tests that need exclusive access to shared state. A benchmark uses `#[bench]` and a `std.bench.Bencher` parameter, with `b.iter(...)` describing the operation to measure.

```hew
import std.bench;

#[bench]
fn concatenate(b: bench.Bencher) {
    b.iter(|| "hello" + " world");
}
```

Run tests with `hew test` and measurements with `hew bench`. The [testing guide](/docs/testing) explains case counts, seeds, filtering and benchmark baselines.

## What 0.6.1 adds

The following examples use the [released 0.6.1 SDK](https://github.com/hew-lang/hew/releases/tag/v0.6.1).

### Keep a function generic after putting it in a value

A generic closure can keep its type parameters until each call, including when the closure is returned by another function:

```hew
fn make_identity() -> fn<T>(T) -> T {
    |<T> value: T| -> T { value }
}

let identity = make_identity();
let number = identity(41);
let greeting = identity<string>("hello");
```

Hew 0.6.1 also lets generic code constrain an associated type directly. `where I.Item: Display` says that an iterator's item can be displayed, while `I: Iterator<Item = T>` ties that associated type to another type parameter. These constraints let an iterator helper state what it needs without forcing callers to change their container. The [0.6.1 specification](https://github.com/hew-lang/hew/blob/v0.6.1/docs/specs/HEW-SPEC-2026.md) includes quantified function values and projection bounds.

```hew
fn first_label<I: Iterator>(var items: I) -> string where I.Item: Display {
    match items.next() {
        .Some(item) => f"{item}",
        .None => "empty",
    }
}

fn equal_label<I: Iterator<Item = T>, T>(var items: I) -> string
    where <I as Iterator>.Item: Display {
    first_label(items)
}
```

### Bring assets and configuration into the build

A schema, template or small default configuration can be compiled into the executable. Paths are relative to the source file and must stay inside the package:

```hew
const SCHEMA: string = include_str!("sql/schema.sql");
const LOGO: bytes = include_bytes!("assets/logo.png");

type Config {
    host: string;
    port: u16;
}

const DEFAULTS: Config = embed!("config/defaults.toml");
```

Those files must exist when the program is built. `embed!` decodes JSON, YAML or TOML into the expected type during compilation, including `#[serial]` names and skipped fields. Aggregate constants can also contain records, enums, tuples, arrays and collections built from constant values, so a default need not be flattened into separate scalar constants.

For diagnostics, `stringify!(expression)` gives the expression's source form without evaluating it, and `location!()` produces a `SourceLocation` with file, line and column. The [compile-time input guide](https://github.com/hew-lang/hew/blob/v0.6.1/docs/guides/compile-time-inputs.md) covers input tracking, package boundaries and typed embedding.

```hew
let expression = stringify!(price + tax);
let here = location!();
println(f"{here.file}:{here.line}: {expression}");
```

### Generate ordinary source where repetition earns it

A declarative macro can expand to an expression or to items. Repetition makes patterns such as a small sum concise:

```hew
macro sum {
    ($($value:expr),*) => expr {
        { var total = 0; $(total += $value;)* total }
    }
}

let count = sum!(1, 2, 3);
```

An `items { ... }` rule can produce declarations, and attribute macros can wrap a function while forwarding its parameters, return type and body. Expansion preserves the normal type and ownership checks. A macro that duplicates an expression also duplicates its evaluation, so use a template local when an argument should run once.

```hew
macro logged {
    #[($label:literal)] $f:fn => items {
        $f.vis fn $f.name $f.generics ($f.params) $f.ret $f.where {
            println($label);
            $f.body
        }
    }
}

#[logged("answer")]
fn answer() -> i64 { 42 }
```

For a schema that generates whole modules, declare a generation step in the manifest:

```toml
[[generate]]
name = "schema"
run = "tools/schema.hew"
args = ["schema.json", "models"]
inputs = ["schema.json"]
outputs = "models"
```

`hew generate` updates the step's source output. `hew generate --check` compares regenerated output without replacing the checked-in tree, which makes it useful in CI. Dependency packages ship their generated source; importing one does not execute its generator. The [macro guide](https://github.com/hew-lang/hew/blob/v0.6.1/docs/guides/macros.md) and [source-generation guide](https://github.com/hew-lang/hew/blob/v0.6.1/docs/guides/source-generation.md) cover the two scales of reuse.

### Wrap deliveries and supply the authority a component needs

An actor interceptor puts common per-delivery behaviour around its handler. This store refuses an erase and inspects a successful read:

```hew
actor Store {
    #[intercept]
    fn guard(call: Call<Self>) -> Outcome<Self> {
        if call.handler_name() == "erase" {
            call.refuse("read-only store")
        } else {
            let outcome = call.proceed();
            match outcome.response {
                .Some(.read(value)) => println(value),
                _ => {}
            }
            outcome
        }
    }
    receive fn read() -> string { "stored value" }
    receive fn erase() {}
}
```

The interceptor consumes its `Call<Self>` and returns the delivery's `Outcome<Self>`. Its `response` is an `Option<Self.Response>`: refusal produces `None`, while a completed unit handler still has a response variant without a payload. Declared handler failures remain distinguishable from a handler that successfully returns an ordinary error-valued `Result`.

`#[confined]` addresses a different service concern: which outside operations a component can acquire. Supply the file, directory or application service it should use when constructing it. Its ordinary calls can then use that supplied service, while ambient acquisition is checked. A directory service can grant a subtree instead of passing a global filesystem path as authority. The [confinement guide](/docs/confinement) explains the construction model and its supported service boundaries.

For an existing `input/orders` directory, the launcher can narrow a read root before supplying it:

```hew
import std.fs;

#[confined]
actor OrderReader {
    let input: fs.ReadDir;
    receive fn read() -> Result<bytes, fs.IoError> {
        input.read("orders.csv")
    }
}

let root = fs.open_read_dir("input").expect("read root");
let orders = root.subdir("orders").expect("narrow to orders");
root.close();
let reader = spawn OrderReader { input: orders };
let data = reader.read().expect("actor reply").expect("read orders");
stop(reader);
stopped(reader);
```

The narrowed resource keeps its own open directory handle. Its relative paths stay beneath that directory, and it cannot write or acquire an unrelated path. Supplying a `ReadFile` or `WriteFile` narrows authority further to one opened file and one direction.

### Describe a deeper protocol without flattening its states

Hew 0.6.1 extends machine composition with deeper nested states, named targets and computed targets. A transition to a composite state follows its declared initial child; a computed target can choose the next state from its input. `reenter` requests exit and entry behaviour even for an explicit transition back into the same state.

For a connection with a handshake and several handshake phases, those rules let shared connection hooks stay on the parent while each phase handles its own inputs. The [0.6.1 machine specification](https://github.com/hew-lang/hew/blob/v0.6.1/docs/specs/MACHINE-SPEC.md) describes target selection and hook order.

Here are the state and rule excerpts from such a machine; its input declarations include `Open`, `Retry` and `Check { valid: bool; }`:

```hew
state Idle;
state Connection {
    initial state Handshake {
        initial state Waiting;
        state Verified;
    }
    state Live;
}

on Open: Idle => Connection;
on Retry: Verified => Handshake reenter;
on Check: Waiting => _ {
    if event.valid { Verified } else { state }
}
```

A named sibling transition keeps the shared parent entered. A computed `_` target exits the active branch before running its body, then enters the chosen branch, even when the body chooses the same leaf.

## Development preview: compose the same operations further

This section requires the [development toolchain at `a340281056`](https://github.com/hew-lang/hew/tree/a340281056). It describes work after the 0.6.1 release, for the 0.6.2 preview.

### Select ordinary calls and observe machine changes

Development `select` can prepare ordinary calls, including mutable callable values and dynamic dispatch, alongside the existing task, stream and timer forms:

```hew
select {
    notice from subscription.recv() => show_notice(notice),
    after 1s => show_progress(),
};
```

Here `subscription.recv()` is an ordinary checked call. This is useful with the machine observation feed: a machine owner applies inputs, while subscribers receive ordered revisions and transition reports. Readers can follow state changes without owning the machine's mutation interface. The [machine-feed example](https://github.com/hew-lang/hew/blob/a340281056/tests/core-acceptance/cases/machine-observed-feed.hew) shows subscription, cancellation and selection together.

Using the `Meter` machine from earlier, an owner and subscriber can be created together:

```hew
import std.machine.watch;

let (owner, feed) = watch.observe(
    Meter.Watching { peak: 0 }, capacity: 4, subscribers: 1
).expect("observe meter");
var live = owner;
let updates = feed.subscribe().expect("subscribe");
let _ = live.step(.Reading { value: 7 });
let notice = updates.recv().expect("feed readable").expect("revision");
println(notice.revision);
```

The same selection syntax works for a private mutable callback and a dynamic trait method. This excerpt reuses `Named` and `Person` from the trait example:

```hew
let count = 0;
var next = capture(var count) || -> i64 {
    sleep(1ms);
    count += 1;
    count
};
let number = select {
    value from next() => value,
    after 1s => 0,
};

let named: dyn (Named + Send + Sync) = Person { label: "ready" };
let name = select {
    value from named.name() => value,
    after 1s => "waiting",
};
```

For distributed services, `peer.export` and `peer.receive_service` exchange typed service grants. Receiving an actor's address and receiving authority to call an exported service are separate operations. The [development distribution specification](https://github.com/hew-lang/hew/blob/a340281056/docs/specs/HEW-DIST-SPEC.md) covers the peer and grant lifecycle.

With authenticated peer sessions already supplied, one side can offer the earlier `Store` actor and the other can acquire its interface:

```hew
fn offer(peer: net.PeerSession, store: Store, done: Stream<i64>) {
    let export = peer.export(store).expect("offer admission");
    let _ = done.recv();
    export.close();
}

fn read_remote(peer: net.PeerSession) {
    let service = peer.receive_service<Store>().expect("receive store");
    println(service.read().expect("remote reply"));
    service.close();
}
```

The module imports `std.net`; peer connection and authentication setup are omitted here. Closing the export revokes future claims, while a handler that already claimed its request may finish. A grant survives an authenticated reconnect between the same node sessions; interrupted calls are not retried, and an actor or node restart invalidates the grant.

### Extend indexing and stream framing through ordinary types

User-defined `Index` implementations and projected-field updates let container code support expressions such as `items[index].count += 1` while keeping the earlier value's snapshot. Strings use Unicode-scalar positions for indexing, lengths and ranges; `text[index]` produces a character, and a range produces a string. Use `get` for an optional result when a position may be outside the string. These positions count scalars, not the user-perceived characters that can contain several scalars.

For a small table with a named column, `Index<string>` supplies both optional and direct access:

```hew
type Table { value: i64; }

impl Index<string> for Table {
    type Output = i64;
    fn get(self, key: string) -> Option<i64> {
        if key == "value" { .Some(self.value) } else { .None }
    }
    fn at(self, key: string) -> i64 {
        self.get(key).expect("unknown column")
    }
}

let table = Table { value: 42 };
println(table["value"]);
var reports = [Summary { path: "first.txt", bytes: 4 }];
reports[0].bytes += 1;
```

Scalar indexing gives the same positions to single-character access, ranges and iteration:

```hew
let text = "Aé🐱";
assert(text.len() == 3);
assert(text[1] == 'é');
assert(text[1..3] == "é🐱");
for character in text.iter() { println(character); }
```

Generic sorting uses `sort.sort<T: Ord>` or `sort.sort_by` for an explicit comparator. The returned vector is independent of the input. Floating-point values need the comparator form when the program wants a total ordering, using `math.total_cmp` to include NaNs and signed zero deliberately. The [development migration guide](https://github.com/hew-lang/hew/blob/a340281056/docs/migrations/v0.6.2.md) lists the replaced string and sorting names.

```hew
import std.sort;
import std.math;

let ordered = sort.sort([3, 1, 2]);
let backwards = sort.reverse(ordered);
let floats = sort.sort_by([3.14, 1.41, 2.72], |a, b| math.total_cmp(a, b) < 0);
```

A byte stream can also use an application-defined `stream.Codec<T>` to turn chunks into frames or values into encoded output:

```hew
let messages = input.frames(codec);
let output = byte_sink.framed(encoder);
let another_writer = output.clone();
```

This excerpt assumes a byte input stream, a byte sink and codecs implementing the trait. The framing adapters keep partial input between chunks, and cloned framed sinks share the output while keeping complete sends together. The [stream codec example](https://github.com/hew-lang/hew/blob/a340281056/tests/core-acceptance/cases/user-codec-stream.hew) and [socket example](https://github.com/hew-lang/hew/blob/a340281056/tests/core-acceptance/cases/user-codec-socket.hew) include the codec definitions and cleanup behaviour.

### Let an actor own a scheduled request

A one-shot actor timer schedules a handler on `self` and returns a cancellation handle. Inside a named actor, the development form is:

```hew
let timer = mailbox(self, after: 5s, overdue: 500ms).refresh();
```

`after` is the minimum delay before submission. `overdue` is optional: it faults the owner with `CrashKind.TimerOverdue` if the handler has not **started** within that interval after the timer fires. Discarding the submission before it starts counts immediately.

Dropping `timer` leaves the actor-owned request scheduled. `timer.cancel()` before firing prevents delivery; after firing it disarms the overdue check without withdrawing an admitted message. Stopping or restarting the actor cancels its pending timers. A timer targets `self`, its handle cannot be sent to another actor, and a timer view refuses `.Wait` admission. The [timer example](https://github.com/hew-lang/hew/blob/a340281056/tests/core-acceptance/cases/actor-one-shot-lifetime.hew) includes cancellation, actor construction and payload cleanup.

Crash reporting uses typed values alongside these operations. `CrashInfo.kind` is a `CrashKind`, including `HandlerFailed` and `TimerOverdue`, and `DownTarget` distinguishes a local actor from a remote target with its full location. Code can match the public cause and target instead of depending on runtime integers.

For an actor whose supervisor permits restart, a crash hook can match the cause directly:

```hew
#[on(crash)]
fn crashed(info: CrashInfo) -> CrashAction {
    match info.kind {
        .TimerOverdue => println("scheduled work did not start"),
        .HandlerFailed => println("submitted handler returned an error"),
        _ => println(info.message),
    }
    CrashAction.Restart
}
```

## Try one change at a time

Use the [getting-started guide](/docs/getting-started) to install the matching SDK, then run the complete `sizes.hew` program with 0.6.0. Change one path to a missing file and handle that result locally; next, keep the two task handles and join them separately. Those small edits make the failure and concurrency choices visible before adding a service around them.

For an existing 0.5.6 project, start with the [0.6.0 migration guide](https://github.com/hew-lang/hew/blob/v0.6.0/docs/migrations/v0.6.0.md), resolve package dependencies, run `hew fmt --migrate --root .`, and review the changes before checking and rebuilding with the matching compiler, runtime and standard library.
