✓
Passing This code compiles and runs correctly.
Code
// PINS: a comptime transform at the ROOT of a store lifecycle arm body emits
// its expansion.
//
// The arm body is walked depth-first, so a transform sitting at its root fires
// BEFORE the store declaration transforms, and leaves its expansion on the
// invocation (`Invocation.inline_body`). The store then rebuilds that body as
// the root of a synthesized flow — and a flow root is emitted from
// `Flow.inline_body`, while only a nested continuation is emitted from the
// invocation's slot. The two slots are the shape this test guards: carry the
// expansion across the rebuild, or the emitter falls through to a plain handler
// call.
//
// `! discharge` is the IN-FILE CONTROL and pins the other position: its
// `print.ln` sits one link down a chain, so it is emitted from the nested slot.
// Both arms print, and each reaches the emitter by a different route.
//
// `std/io:print`/`print.ln` are the sharp probe for this because they reroute
// to `print.impl` for shape checking (io.kz:14). An unemitted expansion still
// leaves a real event and a real handler behind — so the failure mode this pins
// is SILENCE, not a diagnostic, and is indistinguishable at the source from an
// arm that ran.
import std/io
import std/store
import app/lib/src
std/store:new(batch, capacity: 2) { *app/lib/src:Src<live!> }
! inserted _ |> std/io:print.ln("arm inserted")
! discharge s |> app/lib/src:close(s): id |> std/io:print.ln("arm discharge {{ id:d }}")
std/io:print.ln("start")
app/lib/src:open(id: 9, work: 1): a |> std/store:insert(batch) { a }
| row _ |> std/io:print.ln("inserted")
| full f |> app/lib/src:close(s: f): id |> std/io:print.ln("full {{ id:d }}")
Actual
start
arm inserted
inserted
arm discharge 9
Expected output
start
arm inserted
inserted
arm discharge 9
Flows
flow ~new click a branch to expand · @labels scroll to their anchor
new (expr: batch, capacity: 2, source: *app/lib/src:Src<live!>)
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "start")
flow ~open click a branch to expand · @labels scroll to their anchor
open (id: 9, work: 1)
Imported Files
// A synthetic PARTICIPANT with curl's exact contract, so the pump shape can be
// probed without libcurl or a terminal.
//
// open → mints *Src<live!> (curl: multi.start | started)
// step → BORROWS <live>, `| running` / `| complete` (curl: poll)
// close → CONSUMES <!live>, hands a value back (curl: finish/cancel)
//
// close returning a value is the load-bearing detail: it leaves the column with
// ZERO void dischargers, so a store holding one must be drained by an explicit
// `! discharge` arm rather than auto-discharged (690_109's shape).
const std = @import("std");
pub const Src = struct { id: i64, left: i64 };
~pub tor open { id: i64, work: i64 } -> *Src<live!>
~proc open|zig {
const s = std.heap.page_allocator.create($mod.Src) catch unreachable;
s.* = .{ .id = id, .left = work };
return s;
}
~pub tor step { s: *Src<live> }
! ?moved i64
| running
| complete
~proc step|zig {
if (s.left <= 0) return .{ .complete = .{} };
s.left -= 1;
moved(s.id);
if (s.left == 0) return .{ .complete = .{} };
return .{ .running = .{} };
}
~pub tor close { s: *Src<!live> } -> i64
~proc close|zig {
const id = s.id;
std.heap.page_allocator.destroy(s);
return id;
}
Test Configuration
MUST_RUN