013 tap chains

✓ Passing This code compiles and runs correctly.

Code

// Test tap chains - tap invokes event that also has taps
// This verifies TAP_FUNCTION_CONTEXT prevents infinite recursion
const std = @import("std");
~import "$std/taps"

~event main_flow {}
| done {}

~event logger {}
| done {}

~event metrics {}
| done {}

~proc main_flow {
    std.debug.print("Main flow executed\n", .{});
    return .{ .done = .{} };
}

~proc logger {
    std.debug.print("Logger invoked\n", .{});
    return .{ .done = .{} };
}

~proc metrics {
    std.debug.print("Metrics collected\n", .{});
    return .{ .done = .{} };
}

// Tap on main_flow that invokes logger
~tap(main_flow -> *)
| done |> logger()
    | done |> _

// Question: Should this tap on logger fire when logger is invoked from a tap?
// Answer: YES - chained taps fire by default (full observability)
// Use [opaque] annotation if you need to hide internal implementation from tap matching
~tap(logger -> *)
| done |> metrics()
    | done |> _

~main_flow()
| done |> _
input.kz

Expected Output

Main flow executed
Logger invoked
Metrics collected

Test Configuration

MUST_RUN