|

docs: release notes for 0.2.6 (bug 003 fix); backfill 0.2.3-0.2.5

Author: Chris Tusa <chris.tusa@leafscale.com>
Date: Jul 21, 2026 08:21
Changeset: aeec674a70f9dc5079d914c0b915bd0a71db93a5
Branch: default

Changed files:

Diff

diff -r 3f1d7f14d5e0 -r aeec674a70f9 docs/RELEASE_NOTES.md
--- a/docs/RELEASE_NOTES.md	Mon Jul 20 21:07:44 2026 -0500
+++ b/docs/RELEASE_NOTES.md	Tue Jul 21 08:21:02 2026 -0500
@@ -1,5 +1,60 @@
 # zyginit Release Notes
 
+## 0.2.6 — 2026-07-21
+
+**Bug-fix release.** Fixes bug 003 — spurious `exit=-1` service failures in
+first-boot reports on Hammerhead. Root-cause analysis found `exit=-1` was
+never an exec-failure code (a real exec failure exits 127); it was the
+"could not resolve an exit code" sentinel, produced by two distinct defects:
+
+- **Exec robustness / no silent failure.** Under first-boot I/O contention
+  (devfsadm + ZFS pool-finalize) the child's exec of a valid start command
+  could transiently fail, and the child then exited silently with an empty
+  per-service log. The child now retries `process_exec` (5×, 100 ms backoff)
+  and, on final failure, records the reason to both the per-service
+  `<name>.log` (fd 2, survives a privilege drop) and a new central
+  `/var/log/zyginit/zyginit.log`, then exits 127.
+- **Reap-race reconciliation** (the actual source of `-1`). The
+  contract-empty event on the bundle fd can beat the child's exit-status
+  posting; `handle_contract_event` used to commit the `-1` sentinel and tear
+  down tracking, after which the catch-all reaper discarded the real code. It
+  now defers when there is no hint, no resolvable code yet, and a child is
+  still tracked (`rt.pid > 0`), so the unconditional `reap_children`
+  re-dispatches with the true code within ~1 s. This fixes both the 127→-1
+  masking and the independent false-positive where an exit-0 oneshot that
+  lost the race was reported FAILED.
+
+New central operational log: `/var/log/zyginit/zyginit.log` (distinct from
+the per-service logs). Adds integration Suite 9b (spawn-failure capture);
+97/97 tests pass. The reap-race half rides the Hammerhead contract path
+(not exercised by the Linux stubs) and awaits an hh-alpha first boot to
+confirm in situ.
+
+## 0.2.5 — 2026-07-17
+
+**Reef 0.7.6 migration; no init-engine behavior change.** Migrated the suite
+to Reef 0.7.6: `Result`/`Option` idioms, TOML inline arrays, and the
+`socket` → `ctlsocket` module rename (avoids a clash with the stdlib
+`net.socket`, which `net.unix` now imports). Internal/tooling release — no
+source tarball was cut for 0.2.5.
+
+## 0.2.4 — 2026-06-13
+
+**Service mutual exclusion.** Adds the `[dependencies].conflicts` array:
+mutually-exclusive services both fail if both are enabled, and a start is
+refused if a conflicting peer is already running. Boot-time resolution fails
+both sides and surfaces the reason in `zygctl status`. A one-sided
+declaration is enforced symmetrically (both directions).
+
+## 0.2.3 — 2026-06-02
+
+**Boot/shutdown progress gauge relocated into the header divider.** The gauge
+previously lived on the volatile last screen row, where interleaved
+kernel/daemon writes would scroll it off. It now paints into the header's
+horizontal rule. `fmt_progress_bar` and `PROGRESS_WIDTH` were removed and
+`fmt_divider_gauge` added in `src/ui.reef`; two screen rows are reclaimed for
+the rolling tape.
+
 ## 0.2.2 — 2026-05-21
 
 **Repo content reshape; no behavioral change.** zyginit is now