Releases: yinzers/yinz-lang
Release list
v0.3.1 — M5: Array-By-Value Element Storage + Auto-SoA Layout
[0.3.1] — 2026-07-04 — M5: Array-By-Value Element Storage + Auto-SoA Layout
Commit range: v0.3.0..v0.3.1.
What ships
array<Shape> (and map<K,Shape>) elements are now owned, by-value, and inline in the
heap buffer, instead of stored as pointers. This permanently fixes the array-element
stack-dangling miscompile class that the M3a ArrayShapeRuntimeFieldWithWait guard only
masked by rejecting the pattern outright — a runtime-field array<Shape> now correctly
survives crossing a wait, and the guard (plus its registry deferral) is gone.
Riding that new contiguous storage, the compiler can now automatically lay out large,
provably-safe hot-loop arrays as Struct-of-Arrays (SoA) instead of the default
Array-of-Structs layout — a pure codegen decision, zero syntax change, byte-identical
program output in both scheduling modes. The array-using-soa-layout Tier 3 lint fires
on a qualifying array's declaration with jargon-free WHAT/WHAT-INSTEAD/WHY hover text.
Honest performance note. The cache-locality win SoA promises is real — confirmed
~3.3x faster under an optimizing LLVM backend (opt-18 -O2) on the calibration
workload — but it is not realized in the binaries ynz build ships today, because
the compiler runs zero LLVM optimization passes by default (measured: net ~1.0x, no
detectable benefit, sometimes a few percent slower). SIZE_THRESHOLD ships as a
documented, provenance-recorded conservative default (workload, machine, variance, date,
revisit trigger — never a bare constant), not a crossover-calibrated number, since no
crossover exists to calibrate against in shipped O0 binaries. The correctness of the new
representation is unconditional; its measured perf payoff is conditional on future
compiler work (see Deferred, below).
Added
- Elem_size-aware
YnzArray/YnzMapABI — hard-cut, no parallel old-signature entry
points; a missed call site is a compile error, not a silent drift. - Auto-SoA layout: one authoritative
layout_decisions_query(shared with M4's
false-sharing padding transform — padding always wins over SoA for a cross-thread
shape, byte-layout-proven),array-using-soa-layoutTier 3 lint + registry entry,
LSP/VSCode wiring, docs graduation (IMP-collections.md). containsonarray<Shape>is field-wise value equality (number/int/bool fields);
string and nested-shape/collection fields compare by identity. Field-assign is
copy-on-persist (snapshot at assignment) across shape fields, map values, array
elements, and spawn descriptors — a genuine, documented divergence from JS/TS
reference semantics, spelled out indocs/reference/REF-collections.md.- The repo's first SoA-shaped example (
examples/pirates-roster's cannonball-volley
demo) and a committed suppression-enumeration report covering everyarray<Shape>
site in the example/fixture corpus.
Fixed
- The stack-dangling miscompile class for
array<Shape>/map<K,Shape>elements
crossing suspension points — gone by construction, not by rejection. - A pre-existing symmetric
map<K,Shape>miscompile (a loop-arm indirection mismatch),
caught by this milestone's own RED-fixture-first discipline. .copy()on an array was a pre-existing alias no-op in both layout modes (never a
real deep copy) — now a genuine one-level copy in both AoS and SoA.
Deferred — triaged 2026-07-04, tracked on the roadmap
Next-fix priority (real bugs, pre-existing, not introduced by this milestone):
- A codegen crash (ICE) on a bare int literal assigned into any
number-typed slot. - A general O0 stack-exhaustion SIGSEGV ceiling on very large hot loops (all layouts).
- A stale cross-profile
libynz_runtime.arelease archive can silently miscompile by
resolving old-ABI symbols instead of failing to link (an operational rebuild-clean
guard is in place; the structural ABI-version-check fix is tracked, not yet built).
Fine to defer past v1.0 (perf/process only, not bugs):
- Phase 5's codegen doesn't yet consume the per-field
hot_fieldsset the SoA analysis
already computes — a real, cheap, independently-actionable win distinct from needing
an optimizer. - Adding an actual LLVM optimization pass pipeline to
ynz build— the single root
cause blocking every code path the compiler emits, concurrency included, from
approaching the language's Rust-level-performance positioning. - A write-time hook to mechanically catch a recurring twin-derivation bug class
(unrelated to this milestone; carried from the M4 AAR).
v0.3.0 — Concurrency: Channels, Task Handles, Auto-Arc, Mixed CPU+I/O Overlap
Commit range: v0.3.0-m7..v0.3.0 (M3g + M4 content only — M3f and M3d, though present in this
git range because they merged after the v0.3.0-m6/v0.3.0-m7 tags were cut, are already
covered above and are NOT re-described here).
What ships
This is the final v0.3.0 release: the milestone where Yinz code genuinely runs
concurrently, safely, on one unified suspension substrate. It closes the last gap in
auto-parallelization (mixed CPU+I/O groups), and adds the concurrency-communication
surface — bounded channels, task handles, safe cross-thread sharing, and false-sharing
protection — on top of the poll-based substrate M3a/M3b/M3d already proved out. The
may-block suspension question is answered in exactly one authoritative place, threaded
into every consumer, closing a class of twin-computation-drift bug that had silently
miscompiled four prior milestones (M3a/M3d/M3e/M3g).
M3g — mixed CPU+I/O overlap
- A function body mixing one heavy CPU call and one I/O (
wait) call as independent
operations now runs them concurrently — CPU on a worker core, I/O suspended — instead
of sequentially. This was the last gap in "all independent operations
auto-parallelize": M3b covered pure I/O overlap, M3d covered pure-CPU overlap; M3g
fuses the two poll paths (one shared continuation re-drives both the CPU join-poll and
the I/O inline-poll on every resume) so a mixed group overlaps too, without
deadlocking — the failure mode a verify-first pass on M3d had proven genuinely
milestone-sized, not avoidance. - Output remains byte-identical to
--no-auto-parallelfor every fixture; the flag
self-gates the fusion exactly as it gates pure-CPU and pure-I/O promotion.
M4 — channels, task handles, auto-Arc, false-sharing padding
channel<T>()bounded channels — construction,send()/recv(), default capacity
64 (channel<T>(N)to override; no unbounded constructor by design).send()on a
full channel suspends the caller through the same poll-yield substrate aswait—
"a suspended producer is backpressure working correctly, not a deadlock," documented
as such indocs/reference/REF-concurrency.md.
Channel operations join the unified may-block source like any other suspension point.- Background task handles —
let h = background worker(...)yields a handle
supporting.send()into the running task and repeated.receive(), covering both
message replies from a long-running task and a plain suspending function's own
completion value. A collected result's ok-value is copied to a handle-owned buffer
before the frame frees (compile-time spawn-form-keyed — no runtime "was this
collected?" tracking anywhere); the bare fire-and-forget spawn path is unchanged. - Cross-thread auto-Arc — boundary exactness. The
share/lend-across-background
reject is now exact in both directions, including previously-silent unresolvable/
non-ident-callee call sites. The acquire-release runtime substrate ships; the codegen
EMISSION that would make cross-thread sharing atomic is deferred to v0.4+ (a
documented, tracked deferral — today's cross-thread read access is already safe via
the existing independent-copy path). - False-sharing auto-padding. Shapes with fields touched by different
background
tasks get automatic 64-byte cache-line padding — codegen-only, no source change
required. Thecross-thread-fields-not-paddedTier 3 lint fires when the compiler
can't safely auto-pad (cross-module-visible layout). This is the first layout
transform gated by--no-auto-parallel, and the gating is proven, not assumed. [[lint_rule]]registry mechanism — built from scratch (schema, parser,build.rs
constants, LSP seam), generic enough for future lint domains (M5's auto-SoA lint
reuses it with zero rework). Carriescross-thread-fields-not-paddedand
prefer-yielding-sleep(suggests the yieldingwait sleep(ms)over the
thread-parkingsleepBlocking(ms)in schedulable programs).- Teaching surface — a
channel_capacitymuted inlay hint (shows the default64,
click-to-make-explicit);auto_arcis registered with its full cautionary hover text
(fires once the v0.4+ emission lands);docs/reference/REF-concurrency.mdgained the
full channel/handle-form user spec including the backpressure teaching text; the VSCode
extension bumped to0.3.0.
Tests
The R6 may-block unification parity test (build-blocking — the fifth touch of the
twin-derivation class, now closed with one authoritative source); the R5 composed
deadlock-safety hostile fixture (child suspends on a full channel while the parent
polls .receive() — proven safe through the real compiler, not asserted); R1/R2
hostile fixtures (never-received channels, pool exhaustion); the R8 collection matrix
including the composed R5×R8 cell (a collected background child that both suspends on
send() and is collected at completion); the R3 cross-thread boundary-exactness matrix;
a full --no-auto-parallel cross-impl sweep across every new fixture, including the
false-sharing padding transform and the composed-suspension case, byte-identical in
both modes. Full workspace suite, clippy, and fmt green.
v0.3.0-m7 — M3d: Pure-CPU Statement Parallelization
M3d — Pure-CPU Statement Parallelization
Independent heavy pure-CPU calls now run on separate cores automatically — zero new syntax, output byte-identical to --no-auto-parallel. The CPU counterpart to M3b's I/O overlap; promotion is conservative (declining to sequential is always safe) and gated off in kernel mode and under --no-auto-parallel.
Highlights
- ynz-typeck
cpu_admission: single authority deciding CPU groups (consumed by both the IDE hint and codegen) +does_real_workworth-it fixpoint. - ynz-codegen: state-machine promotion lowering, group-poll join; reads the admission authority, cross-pinned to the IDE hint by a spawn-count parity test.
- ynz-runtime: joinable CPU spawn/poll/free C-ABI, panic re-raise, drop-detach — poll-based throughout (no synchronous join).
- ynz-abi (new crate): single-sourced spike-frame offsets, const-asserted cross-crate.
- Teaching:
parallel_groupsinlay hint.
Tests
15 danger-matrix + 8 hostile fixtures + corpus-wide cross-impl byte-identical sweep + spawn-count cross-pin parity tests. Full workspace suite green.
VSCode extension: install yinz-latest.vsix (stable URL) or the versioned yinz-0.3.0-m7.vsix below.
v0.3.0-m6 — M3f: Pre-Existing Codegen Correctness Fixes
Closes two confirmed silent miscompiles in the state-machine / auto-parallelization codegen — both wrong-answer-at-runtime bugs that v0.3.0-m5 shipped with. No new language surface: programs that were already correct are byte-identical; only programs that were silently producing wrong values change (now correct). This unblocks the final v0.3.0 release.
Fixes (M3f)
- Wide-
errorssame-callee value aliasing — twoletbindings of the same-> number errorsfunction (e.g.let p1 = fetchPrice(0); let p2 = fetchPrice(1)) no longer collapse to the same value. Anumber(decimal128) ok-value too wide for the result word used to live in the callee's shared staging slot, and a second same-callee call clobbered the first binding before it was read. Each binding now copies its value into its own storage at bind time. (Was:31.75 / 31.75; now:24.50 / 31.75.) - Parallel-group boolean sibling corruption — when independent suspending statements auto-parallelize and a boolean result is live across a later
wait, a sibling integer result no longer reads back0. The boolean's frame store was an 8-byte write into a 1-byte slot, overrunning the adjacent result. Restores the cross-implementation consistency oracle (--no-auto-parallelproduces byte-identical output to the default). (Was: default0vs--no-auto-parallel42; now:42in both.)
Tests
12 new regression fixtures + 12 integration tests covering the full trigger matrix (mixed result types — int, boolean, decimal128, and wide-errors — in parallel groups crossing a later wait), each asserting --no-auto-parallel byte-identity. The pirates-roster demo exercises both fixed patterns. Full workspace suite green.
Full diff: v0.3.0-m5...v0.3.0-m6
v0.3.0-m5 — M3e + M3b: Cross-Module Frame Serialization + Auto-Parallelization
[0.3.0-m5] — 2026-06-09 — M3e + M3b: Cross-Module Frame Serialization + Auto-Parallelization
Commit range: v0.3.0-m4..v0.3.0-m5
What changed
v0.3.0-m5 bundles two concurrency milestones. M3e lets a suspending function be
called across module boundaries — the M2/M3a substrate could only suspend within one
module. M3b makes independent suspending statements overlap automatically: write
straight-line code, get concurrent I/O for free, with no async/await and no spawn
syntax. Programs that compiled before are byte-identical; the new --no-auto-parallel
build flag is a permanent escape hatch and the cross-implementation consistency oracle.
Features (M3e — cross-module frame serialization)
- Cross-module
wait— a function in one module can nowwaiton a suspending
function defined in another module. The callee's full task-frame layout is serialized
through the export table so the state-machine codegen can rebuild it on the caller's
side. The universal-reject floor M3b shipped as an honest partial is lifted. - Conservative cross-boundary safety — an unresolvable edge (dynamic dispatch, FFI)
still produces a clean teaching error, never a silent non-suspension.
Features (M3b — auto-parallelization)
- Independent suspending statements overlap — two statements that each suspend and
don't depend on each other run concurrently via a single-threaded interleaved poll
(default ≈ the slower of the two, vs--no-auto-parallel≈ the sum). Zero new runtime
symbols — no thread spawn. waitis the ordering barrier —wait foo()completes (and joins all in-flight
overlapped work) before the next statement starts. Loop iterations stay sequential.backgroundgive/copy figured out for you — a value handed to abackgroundtask
is automatically given (move) when unused after, or deep-copied when still used. Heap
values get a real deep copy, freed when the task completes — no use-after-free, no leak.- Two new IDE hints —
wait_points(where the compiler suspends on I/O) and
background_routing(which pool abackgroundtask lands in) render as muted inlay
hints that read the effective suspend set, so they can't drift from actual behavior.
Soundness (M3b)
Auto-parallelization is sound by a type-based conservative floor: any argument whose
type is mutable-heap (a shape, array, map, maybe, union, or dynamic) is treated
as a potential aliased write, so a statement pair touching one runs sequentially. Golden
Rule 5 (compile-time safety) outranks Golden Rule 10 (efficiency) — the compiler forfeits
read-only-heap overlap rather than risk a data race. Primitive and string arguments
still overlap.
Known limitations / deferrals
background-handle result collection (ec-wrapper-collect-on-completion) — moved to
v0.3-M4. Collecting abackground-spawned-> T errorstask's result via a handle needs
the handle-collection syntax (.send/.receive), which ships separately. The inline-poll
path for-> T errorsworks today.- Read-only-heap overlap forfeited — the conservative floor sequentializes mutable-heap
arguments even when the callee only reads them. Reversal path: a type+alias-aware ownership
analysis. Documented indesign/concurrency.md.
Pre-existing bugs surfaced (not introduced by this release)
Two silent-wrong-output bugs were found during M3b adversarial review and confirmed to
pre-date auto-parallelization (identical wrong output with and without --no-auto-parallel).
Tracked on the roadmap as milestone M3f (blocks the v0.3.0 final release) and in
.claude/todos.md: (1) same-callee wide-errors (-> number errors) result slot reuse;
(2) a crossing local inside control flow after a wait. Neither is a regression.
Tests
1929 passing across the workspace (0 failed, 6 ignored). Cross-implementation oracle:
--no-auto-parallel equals default output on 196 + 31 fixtures, zero real divergence.
M3b passed a 5-reviewer cumulative review; M3e passed its own at close-out.
v0.3.0-m4 — M3a: wait in Loops + Frame-Backed Crossing Locals
[0.3.0-m4] — 2026-06-04 — M3a: wait in Loops + Frame-Backed Crossing Locals
Commit range: v0.3.0-m3..v0.3.0-m4
What changed
v0.3.0-m4 lifts the two harshest M2 compile-error guards (LocalCrossesWait and WaitInsideLoop) by completing the state-machine codegen substrate: frame-backed mutable locals and loop suspension. Every program that previously errored with one of these guards now compiles and produces correct output. Programs that compiled before are byte-identical.
This is v0.3-M3a — the first half of the original M3 plan, split out as its own shippable slice. M3b (statement-level auto-parallelization) builds on this substrate.
Features
- Frame-backed crossing locals — a
letlocal declared before awaitand used after now compiles correctly. The compiler flushes the local's value into the task frame before suspension and reloads it on resume. Every Yinz type is handled:int,bool(i1 zero-extended),float(bitcast),number(decimal128, 2 i64 slots),string(pointer viaptr_to_int),Shape(direct struct),array<T>(heap pointer),map<K,V>(heap pointer), andoptions(int-encoded). ONEynz_allocper task tree even for local-heavy functions — no per-crossing-local allocation. waitinsidewhileloops — the loop counter and any loop-carried locals are frame-backed; eachwaitsuspension preserves them. Resume re-enters the loop body for the current iteration. Iterations run sequentially (design/concurrency.md "Loop Iterations — Sequential by Default") — NOT parallelized. M3b handles auto-parallelization of independent statements.waitinsideforloops —for (x in array<T>)andfor (entry in map<K,V>)loops withwaitin the body. The array index and heap pointer are frame-backed; resume re-enters for the current index. Iteration order is preserved; output matches the hand-unrolled sequential form.waitinsidematcharms — awaitin anymatcharm resumes into the correct arm. Any bindings live across the suspension are frame-backed via the P1 mechanism.sleepAsync→sleep/sleepMs→sleepBlockingrename (P0) — the two sleep intrinsics now have their final names.sleep(ms)is the yielding form (suspends the function, OS thread freed).sleepBlocking(ms)blocks the OS thread (use only where thread-blocking is correct, e.g., background analytics).wait sleepBlocking(...)still emits the "waithas no effect" warning — intentional.
New diagnostics (WHAT/WHAT-INSTEAD/WHY format)
Kept-guard diagnostics reworded (P0) — no more false "ships in v0.3-M3":
SubExprSuspendViolation— reworded WHY states the step-by-step design rationale (Golden Rule 7) and notes M3b auto-parallelization of independent statements.MutualSuspensionCycle— reworded WHY states that self-recursion works and mutual cycles are always restructurable.
New P3 deferral diagnostics (clean compile errors, never silent wrong output):
FixedArrayIterWithWait—fixed<T>array as afor-iterator with await; stack pointer dangles after suspension. Usearray<T>.StoredRangeWithWait— arangelocal iterated by aforwithwait; inline the range expression.ExpressionIterWithWait— a call-expression collection (for (x in makeArray())) withwait; bind to a local first.UnsupportedCrossingLocalType(fixed) — afixed<T>local crossing await; usearray<T>.MapEntryFieldAfterWait—entry.key/entry.valueread after awaitin afor (entry in map)body; read fields before thewait.RangeCrossingLocalWithWait— arangelocal crossing a top-levelwait; inline the range.ArrayShapeRuntimeFieldWithWait—array<Shape>crossing awaitwith runtime-computed element fields; use all-literal field values. Conservative interim guard; lifts entirely when them3c-array-by-valuemilestone ships.
Known limitations (seven P3 deferrals — compile errors, not silent wrong output)
All seven are loud compile errors with WHAT/WHAT-INSTEAD/WHY diagnostics pointing to design/concurrency.md sections and named future milestones. None produce silent wrong output or crashes:
fixed<T>as for-iterator with a wait — stack pointer dangles; usearray<T>- Stored range local then iterated with a wait — inline the range
- Call-expression collection with a wait — bind to a local first
fixed<T>crossing local with a wait — usearray<T>- Map
entry.key/entry.valueafter a wait — read beforewaitor use an outer accumulator rangecrossing local with a wait — inline the rangearray<Shape>with runtime-computed element fields crossing a wait (conservative guard) — lifted bym3c-array-by-value
IDE surface
M3a adds NO new muted-hint domain and NO new lint rule. The wait_points muted-hint domain and background_routing fire in M3b. The prefer-yielding-sleep Tier-3 lint rides M4's [[lint_rule]] infra (not yet built). sleep/sleepBlocking hover docs updated with their renamed names and per-stdlib-design-rule danger annotation for sleepBlocking.
Demo / gallery
examples/pirates-roster/entrypoint.ynzextended with v0.3-M3a Phase 4 section (m3a_p4_demo): a roster scouting loop thatwait sleeps per item, with a crossing-localtotalaccumulator updated across 5 suspensions. Demonstratesfor+wait+crossing-local in realistic context (85+92+78+95+88=438).examples/primantis-orders/v0_3_m3a_errors.ynzupdated: removed theWaitInsideLooptrigger forforloops (P3 lifted it); addedSubExprSuspendViolationandMutualSuspensionCycletriggers for the two permanent kept guards; added triggers for four representative P3 deferrals (FixedArrayIterWithWait,StoredRangeWithWait,MapEntryFieldAfterWait,ArrayShapeRuntimeFieldWithWait).- Two cross-impl consistency tests added (
v03_m3a_p4_no_auto_parallel_*): assert--no-auto-parallelproduces byte-identical output to default on a crossing-local fixture and a for-loop fixture. Gate wired for M3b.
v0.3.0-m2 — Teaching-Surface Bug Hunt
Fixes every bug from the four-agent teaching-surface audit — 14 cataloged bugs + 3 same-class siblings across unused-import diagnostics, inlay-hint walkers, hover, completion, and the banned-jargon quick-fix (merged from v0.2.1-M10, PR #68).
Two behavior changes worth noting:
let → consthints now fire far more often (the over-suppression bug meant the flagship hint almost never appeared in real code).- Inlay hints render in Pittsburgh gold (
#ffd23f) and anchor at end-of-line.
Full notes: see CHANGELOG.md [0.3.0-m2].
VSCode extension: install yinz-0.3.0-m2.vsix, or pin to the stable latest URL:
https://github.com/yinzers/yinz-lang/releases/latest/download/yinz-latest.vsix
v0.3.0-m1 — Runtime Bootstrap + Working `background`
What's new
background fn(args) now actually runs on a separate thread. Previously (v0.1, v0.2), background parsed and type-checked but ran sequentially. M1 ends that: background tasks spawn on a thread-pool runtime; main continues immediately.
Features
- Working
background— fire-and-forget on a separate thread.background fn(value.give)andbackground fn(value.copy())both work. sleepMs(ms)intrinsic — synchronous sleep for testing and demos.- Large-copy warning —
background fn(largeStruct.copy())where the copy exceeds 64 bytes warns and suggests.give. .giveinlay hint — VSCode shows.give (transfers ownership; no copy)inline when the large-copy warning fires.
Safety errors
- Lend-cross-thread —
background fn(lend-param)is now a compile error. - Kernel-mode rejections —
backgroundandwaitin--kernelmode are compile errors.
Improvements
- Parser forward-progress guarantee (was hanging on certain error-recovery inputs).
- Cross-impl corpus determinism harness (69 fixtures, all deterministic).
VSCode extension
Hover over background to see updated WHAT/WHAT-INSTEAD/WHY docs. Bump to v0.3.0-m1.
Install: code --install-extension yinz-latest.vsix
Note:
screenshots/background-concurrent.pngis a placeholder — replace with a real screenshot before the v0.3.0 final release.
v0.2.0 — LSP Full Experience + Compiler Bug Fixes
v0.2.0 — LSP Full Experience + Compiler Bug Fixes
This release closes out the v0.2 dev-loop series and ships the full editor experience.
8 new LSP capabilities
- Go-to-definition — Cmd+click any identifier → jumps to declaration (cross-file)
- Find All References — lists every use-site across the project
- Rename — F2 atomic rename; validates against Yinz keywords and banned jargon
- Format on save — delegates to
ynz-fmt; normalizes to LF line endings - Inlay hints — type annotations, ownership modifiers, auto-promotion hints
- Code actions — quick-fix for every diagnostic with a WHAT-INSTEAD
- Semantic tokens — richer color differentiation (keywords / types / functions / variables)
- Structured diagnostics —
code+datafields on every LSP diagnostic
Other improvements
- Doc-comment hover:
///doc comments appear in hover popups - Completion narrowing:
score.shows only int methods whenscore: int ynz build --json: NDJSON diagnostic output for CI/tooling. Schema stable at"v0.2.0".
3 compiler correctness fixes
- Hidden-field default eval:
hidden bar: string = "default"now evaluates to"default"instead of null - Dynamic-dispatch coercion: passing a
ConcreteFootodynamic Fooparams now compiles whenConcreteFoo follows Foo - UFCS const-lend parity:
const p; p.heal(20)now errors identically toheal(p, 20)whenhealrequireslend
Install
curl -L https://github.com/yinzers/yinz-lang/releases/latest/download/yinz-latest.vsix -o yinz-latest.vsix
code --install-extension yinz-latest.vsixv0.2.0-m4 — ynz watch
ynz watch — rebuild-on-save daemon
ynz watch is now live. Save a .ynz file; it recompiles and re-runs within a second.
Quick start
ynz watch examples/basics/ # build + run on every save
ynz watch --check foo.ynz # build only (CI gate)
ynz watch --json foo.ynz | jq . # NDJSON event streamWhat ships
- Sub-second incremental rebuild via a long-lived salsa
CompilerDbdaemon — file events mutateSourceFile.textinputs; salsa invalidates downstream queries automatically. - Child process lifecycle — compiled binary spawned in its own process group (
setsid); SIGTERM → 2s grace → SIGKILL on each rebuild cycle; unconditional Drop prevents zombies. --jsonevent stream —watch-ready,build-start,diagnostic(one per compile error with WHAT/WHAT-INSTEAD/WHY),build-end,child-spawn,watch-shutdown. Schema version:v0.2-m4-unstable(semver-stable at v0.2.0 final).- EPIPE handling —
ynz watch --json | head -1exits cleanly withwatch-shutdown { reason: "pipe-closed" }. - 3-layer memory defense for 24h+ continuous use:
- Salsa LRU caps: lex(128) parse(128) signatures(128) check(64) codegen(32)
- Periodic DB rebuild every 500 cycles or 4h (monotonic; shadow
HashMappreserves source state — zero data loss) - RSS polling via
memory-stats; soft-warn at 1GB, hard-stop at 4GB with WHAT/WHAT-INSTEAD/WHY exit message
Demo
examples/watch_demo/ — minimal project; edit the print message and save
Deferred
YNZ_WATCH_LRU_*runtime tuning env vars (documented, not yet wired)- Windows full validation pass
- Interactive commands (
rto rebuild,qto quit) — v0.3+