✓
Passing This code compiles and runs correctly.
Code
// Pins: two compiler fixes in the command-dispatch surface.
//
// 1. A [comptime|command] event whose name is kebab (`publish-npm`) must emit a
// VALID Zig handler symbol. The module emitter mangles kebab -> underscore
// (`publish_npm_event`), but the command dispatcher's generated
// `{s}_event.handler` used the raw spelling and emitted `publish-npm_event` —
// an undeclared identifier. A kebab-named command crossing a module boundary
// was the case that surfaced it.
//
// 2. `ci` is a shared frontend verb: it drives the std/build:step graph the
// program declares, in depends_on (topological) order, even when the program
// also declares other commands. Declaring steps used to hijack the whole
// build and return before the command dispatcher ran, so `ci` was a no-op.
~import std/build
~import std/compiler
const std = @import("std");
~std/compiler:command.declare {
"name": "publish-npm",
"alias": "publish",
"description": "A kebab-named comptime command"
}
~[comptime|command]pub tor publish-npm {
program: *const Program,
allocator: std.mem.Allocator,
argv: []string,
}
~proc publish-npm|zig {
const S = @import("std");
S.debug.print("kebab command ran\n", .{});
}
// The shared step vocabulary: declare release first, but it depends_on build.
// `ci` must still run build first (topological), and run both.
~[depends_on(build)]std/build:step(name: "release") {
echo "release step"
}
~std/build:step(name: "build") {
echo "build step"
}
Flows
flow ~command.declare click a branch to expand · @labels scroll to their anchor
command.declare (source: "name": "publish-npm",
"alias": "publish",
"description": "A kebab-named comptime command")
flow ~step click a branch to expand · @labels scroll to their anchor
step (name: "release", source: echo "release step")
flow ~step click a branch to expand · @labels scroll to their anchor
step (name: "build", source: echo "build step")
Test Configuration
Post-validation Script:
#!/bin/bash
# Pins both fixes. Runs against the REAL koruc via PATH + $KORU_INPUT.
set -e
# Fix 1: a kebab-named [comptime|command] must compile AND dispatch a valid
# handler symbol (module emitter mangles, dispatcher must too).
kebab_out="$(koruc "$KORU_INPUT" publish-npm 2>&1)"
case "$kebab_out" in
*"kebab command ran"*) ;;
*) echo "FAIL: kebab-named command did not dispatch cleanly"; echo " got: $kebab_out"; exit 1;;
esac
# Fix 2: `ci` drives the step graph in depends_on (topological) order — build
# declared LAST but must run FIRST because release depends_on build.
ci_out="$(koruc "$KORU_INPUT" ci 2>&1)"
build_pos="$(echo "$ci_out" | grep -n 'build step' | head -1 | cut -d: -f1)"
release_pos="$(echo "$ci_out" | grep -n 'release step' | head -1 | cut -d: -f1)"
if [ -z "$build_pos" ] || [ -z "$release_pos" ]; then
echo "FAIL: ci did not run both steps"; echo " got: $ci_out"; exit 1
fi
if [ "$build_pos" -ge "$release_pos" ]; then
echo "FAIL: ci ran in declaration order, not dependency order"
echo " build at $build_pos, release at $release_pos"
exit 1
fi
echo "OK: kebab command symbol + ci step-graph driving"