The persistent TS emit cache currently hashes source bytes, then an optional | separator and the config blob. This is not injective: source "1", config "2;" and source "1|2;", empty config both hash the byte stream "1|2;". A cached compile can therefore return JavaScript for a different source or compiler configuration. The old scheme also aliases source "a|b", empty config with source "a", config "b".
Acceptance:
- Use a versioned, unambiguous framing of source and config bytes so old disk keys cannot be mistaken for new ones.
- Prove distinct keys and actual cache misses for delimiter and empty-config collisions, including a TS driver compile path.
- Compile the shipped ts_cache module and run its public tests on the pinned Zig 0.17 and CI Zig 0.18 in Debug and ReleaseFast.
- Preserve existing cache/driver/Program tests; do not treat this scoped fix as full compiler parity.
Related: #884 (dual-toolchain source coverage), #66 (runtime/TS parity).