○
Planned This feature is planned but not yet implemented.
cross-module qualified phantom state unification (ratified design)
Code
// Aspirational: cross-module phantom state unification (the ratified design,
// OUTSTANDING_DESIGN_DECISIONS.md "phantom state cross-module resolution").
//
// A USER module references a phantom state DECLARED in an imported library
// module, via the qualified form `<app/lib/store:secret>`. The qualified state
// must RESOLVE through the import map and UNIFY with the `<secret!>` that
// make-secret issues — so this compiles, runs, and prints "ok".
//
// Today this is RED: phantom_semantic_checker.zig keys module_map on the dot
// local_name and canonicalizes with the dot separator, so a slash-qualified
// app/lib/store:secret fails to resolve (KORU040 "Unknown module 'app/lib/store'
// ... Module not imported") even though app/lib/store IS imported. The fix is
// the ratified design: canonical form -> slash, module_map slash keying,
// qualifier resolved through the import map like an event path.
//
// This is the scalar-phantom case (the obligation is on []const u8, a builtin
// with no home module) — the case that proves bare-is-not-enough and the state
// must name its own module. See also 330_088 (bare-outside rejection) and
// 330_089 (taint-tracking capability use case).
~import std/io
~import app/lib/store
// Consume app/lib/store's secret obligation cross-module.
~event use-secret { s: []const u8<app/lib/store:!secret> }
| used []const u8
~proc use-secret|zig {
return .{ .used = s };
}
~app/lib/store:make-secret(payload: "shh")
| secret s |> app/lib/store:reveal(s)
| plain p |> use-secret(p)
| used _ |> std/io:print.ln("ok")
Must succeed:
Compile and run without errors.
Expected output
ok
Flows
flow ~make-secret click a branch to expand · @labels scroll to their anchor
make-secret (payload: "shh")
Imported Files
// A module that ISSUES a phantom-tagged scalar obligation, for the cross-module
// unification tests (330_087, 330_088, 330_089).
//
// `secret` is a compile-time taint tag: `make-secret` issues `<secret!>` (an
// obligation that the value must be `reveal`-ed before use); `reveal` consumes
// `<!secret>` and returns a plain value. This is the minimal taint-tracking
// vocabulary — a module that declares a phantom-state vocabulary carried on a
// builtin scalar (no home module of its own), which is exactly why the state
// must name its own module rather than being implied by the type.
const std = @import("std");
~pub event make-secret { payload: []const u8 }
| secret []const u8<secret!>
~proc make-secret|zig {
return .{ .secret = payload };
}
// Consume the secret obligation: discharges <secret!> -> a plain value.
~pub event reveal { s: []const u8<!secret> }
| plain []const u8
~proc reveal|zig {
return .{ .plain = s };
}
Test Configuration
MUST_RUN