Skip to content

Commit 82adf82

Browse files
committed
chore(release): v1.6.0 — four hang/abort fixes, two of them 18 days overdue
Smell-audited: depth 1: the release is the point of today's work, not a formality after it. Two of the four fixes (ADR-0175 spawn-to-register safepoint, ADR-0176 live-worker teardown) have been sitting on main since 2026-07-28 and 07-31 while Homebrew served 1.5.1 — so anyone who ran a `future` or a `promise` from a brew install could hit a glibc abort that was already fixed in the repo. A release process that depends on someone remembering to cut it will stop when attention moves, and it did. Fixed in this release: - glibc abort when a worker was live at process exit (ADR-0176; 6/32 -> 0/96) - SIGABRT from the non-safepoint spawn-to-register window on x86_64 Linux (ADR-0175) - `(wasm/run …)` ran guests unmetered — a spinning guest hung the host forever; now bounded by the same finite default `wasm/load` always had - `cljw.http.server` wedged indefinitely by one unfinished request head - namespace names with an empty segment resolved where clj refuses them Added: `run-server :header-timeout-ms`, `wasm/run :fuel` / `:max-memory-pages`. Both behaviour changes are called out under "Note for upgraders" with the opt-out. The CHANGELOG entry leads with who should upgrade rather than with a feature list, because two of these are crashes and the reader's first question is whether they are affected. Mac full gate green (416 passed / 0 failed / 0 skipped, serial). The x86_64 leg is re-running against dd3c608 after it caught two host-portability defects in the gates added earlier today.
1 parent dd3c608 commit 82adf82

3 files changed

Lines changed: 98 additions & 33 deletions

File tree

‎.dev/handover.md‎

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,27 @@
1212
Step 6). `build.zig.zon` `.zwasm` = tag pin
1313
`v2.4.0` (2026-08-03; zwasm's external-consumer release — nothing in
1414
it reaches cljw, pin hygiene only). Latest release:
15-
**v1.5.1** (2026-07-17; zwasm-pin patch release on top of v1.5.0 =
16-
the ADR-0174 host-class campaign + Thread lifecycle; tap carries
17-
cljw 1.5.1 + zwasm). CHANGELOG is the release-history SSOT.
18-
- **First task on resume MUST be**: continue the 2026-08-04 audit-remediation
19-
arc (`private/analysis/2026-08-04-tri-project/09_improvement_backlog.md` is
20-
the ordered list). Landed so far: doc-truth + `size_claims` widened
21-
(`77f690a3`), Issues/PR surface opened (`e897cbfc`), **ADR-0177**
22-
capability-claim gate + ROADMAP §1.1/§1.2/§1.3/§8.1/§8.3/§10.3 amendment.
23-
Next in order: **P1-2** (`data/placement.yaml` — kill or gate; it cites 3
24-
scripts of which 2 do not exist, is not wired into `run_all.sh`, covers
25-
49/683 vars, unchanged since 2026-05-25), **P1-5** (`category: security`
26-
active rows, one sweep), **P1-4** (`clojure.core` public surface: ~60 `-`
27-
internals + ~30 interface names are `ns-publics` — must land before 2.0),
28-
**P1-1** (NaN-box tag space is 64/64 — ADR + F-004 question for the user),
29-
then **release v1.6.0** and the distribution follow (tap + the three demo
30-
repos, all still pinned to cljw v1.0.0).
15+
**v1.6.0** (2026-08-04; four hang/abort fixes — ADR-0175 spawn-to-register
16+
safepoint, ADR-0176 live-worker teardown, D-347 unmetered `wasm/run`, D-339
17+
`run-server` head deadline — plus the opened Issues/PR surface).
18+
CHANGELOG is the release-history SSOT.
19+
- **First task on resume MUST be**: the NaN-box tag-space surgery
20+
(`private/notes/2026-08-04-nanbox-tag-space-investigation.md` has the
21+
measured classification + the ADR outline). The audit's "64/64 full, needs a
22+
user F-004 decision" was WRONG: 53 tags are actually NaN-boxed, 3 are
23+
heap-only (`tail_node` / `hamt_map_node` / `tval` — GC-traced, never a
24+
Value), and **7 are pure unused reservations** (`reader_conditional` /
25+
`class` / `array_chunk` / `matcher` / `tuple` / `box` / `wasm_fn` — zero
26+
references outside the enum; `Class` is a `.type_descriptor` and `Matcher`
27+
is a `host_instance`). So ~10 slots are recoverable WITHOUT touching F-004.
28+
Treating the reservations as binding was the Reservation-as-bias smell
29+
CLAUDE.md names explicitly. Then **P1-6** (WIT↔Clojure type-mapping shared
30+
spec with ClojureWit).
31+
The 2026-08-04 audit-remediation arc otherwise closed: doc-truth +
32+
`size_claims` widened (`77f690a3`), Issues/PR opened (`e897cbfc`),
33+
ADR-0177 capability-claim gate (`92d7926d`), D-339 (`c601aa75`), ADR-0178
34+
generated placement index (`4c52ebcc`), AD-057 + core-surface gate
35+
(`18e9ea5f`), D-347 (`b4b5ef83`), D-343 + security triage (`6bdeeeb2`).
3136
- **Unreleased on main**: envelope v9 (op_var_meta — def-meta rides
3237
the AOT wire), computed def-meta (D-316) — incl. `:tag` uniform-eval
3338
(`^String`→Class, `^Foo`→name error; the bare-symbol workaround
@@ -56,9 +61,10 @@
5661
- **v1.5.1** is the released line; v1.5.0 was the ADR-0174 host-class campaign
5762
+ Thread lifecycle. The v1.4.0 binary-size campaign (ADR-0172/0173) and the
5863
v1.3.x arc are in CHANGELOG.
59-
- Debug tooling: `scripts/nrepl_send.py`, `scripts/clj_diff_sweep.sh` +
60-
corpora, `scripts/binary_size_report.sh` (now gates every public size claim,
61-
ADR-0177), `scripts/check_capability_claims.sh` (ADR-0177).
64+
- Debug tooling: `nrepl_send.py`, `clj_diff_sweep.sh` + corpora,
65+
`binary_size_report.sh` / `check_capability_claims.sh` (ADR-0177),
66+
`gen_placement.sh` / `check_placement_status.sh` (ADR-0178),
67+
`check_core_surface.sh` (AD-057).
6268
- nREPL is single-connection (serial accept, D-117(a)): a second client waits
6369
while an editor is attached — probe via a fresh server, not the editor's port.
6470
- **Issues and PRs are OPEN** as of 2026-08-04 (`e897cbfc`); three issue
@@ -68,29 +74,27 @@
6874
## Standing units (tracked in .dev/debt.yaml)
6975

7076
- **D-565** — external-contributor reproducibility / doc-staleness sweep
71-
(fresh-clone onboarding audit, Discussion #11). Build/test/CI reproduce
72-
cleanly; gaps are doc rot (`zwasm_from_scratch`→`zwasm`, dead `OSS/zig`
73-
ref, missing `cleanup_orphans.sh`, README 1.0.0-vs-1.5.1, autonomous-vs-
74-
maintenance mismatch) + no CONTRIBUTING opt-out notes. Companion: zwasm D-526.
77+
(Discussion #11). PARTLY drained 2026-08-04: README version + CONTRIBUTING
78+
opt-out notes landed with the Issues/PR opening (`e897cbfc`). Residual is
79+
path rot (`zwasm_from_scratch`→`zwasm`, dead `OSS/zig` ref,
80+
`cleanup_orphans.sh`). Companion: zwasm D-526.
7581

7682
- **Perf campaign (§9.2.S) — PAUSED** (D-520 / D-386 / D-005/006).
7783
- **D-513** — clojure.core.reducers / clojure.repl / var :doc.
7884
- **D-548** — (a) DISCHARGED (ADR-0176); residual = (b) pmap
7985
wall-clock on the 3-vCPU runner (timing envelope, still gated).
80-
- CIDER upstream banner patch draft:
81-
`private/notes/cider-clojurewasm-banner-patch.md` (user-side PR).
86+
- CIDER upstream banner patch draft (user-side PR):
87+
`private/notes/cider-clojurewasm-banner-patch.md`.
8288

8389
## North star (ACTIVE, distal)
8490

85-
cljw's differentiator = **Wasm/edge-native (gap II) × VM-perf
86-
fusion→JIT (gap III)**. zwasm JIT (ADR-0200) is the cljw default;
87-
remaining = components-through-the-JIT (zwasm-side, D-500). Distal —
88-
needs a user nod; the §9.2.T public-ization sweep (easiest-first debt
89-
drain) is the active near-term mode.
91+
cljw's differentiator = **Wasm interop (gap II) × VM-perf fusion→JIT (gap
92+
III)**. zwasm JIT (ADR-0200) is the cljw default; remaining =
93+
components-through-the-JIT (zwasm-side, D-500). Distal — needs a user nod.
94+
NOTE ADR-0177: "edge execution" is an AIM owned by D-552, not a capability.
9095

9196
## Reading order (resume)
9297

93-
handover → `yq` the live `active:` list → ADR-0166 (public-ization
94-
sweep mode) → ROADMAP §9.0. Memories:
98+
handover → `yq` the live `active:` list → ADR-0166 → ROADMAP §9.0. Memories:
9599
`verify_against_releasesafe_binary` / `smoke_first_batch_full_gate` /
96100
`external-publish-payload-guard`.

‎CHANGELOG.md‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,52 @@ first stable `1.0.0` tag; pre-1.0 `alpha` / `rc` tags may still change surfaces.
77

88
## [Unreleased]
99

10+
## [1.6.0] - 2026-08-04
11+
12+
**Upgrade if you use threads, futures, promises, or `wasm/run`.** This
13+
release carries four fixes for ways cljw could hang or abort, two of them
14+
outstanding since 1.5.1 (2026-07-17).
15+
16+
### Fixed
17+
18+
- **A live worker at process exit could abort (glibc `abort`).** A
19+
`future` / `promise` whose worker was still running while the runtime tore
20+
down could crash the process instead of exiting. `exitBarrier` plus
21+
deinit-chokepoint guards make a live worker force a daemon-style hard exit
22+
rather than a teardown under its own feet. Measured: 6 failures in 32 runs
23+
before, 0 in 96 after. (ADR-0176, AD-056)
24+
- **Thread registration was not a GC safepoint (SIGABRT on x86_64 Linux).**
25+
The window between spawning a worker and registering it with the collector
26+
was not a safepoint, so a collection landing in that window could abort.
27+
Registration is now a safepoint, and the `TooManyThreads`
28+
run-unregistered fallthrough is closed. (ADR-0175)
29+
- **`(wasm/run …)` ran guests unmetered — an infinite loop in a guest hung
30+
the host forever.** `wasm/load` has always defaulted to a finite fuel and
31+
memory budget; `wasm/run` passed no budget at all, so the two sibling
32+
surfaces had opposite postures. `wasm/run` now takes the same finite
33+
default. Measured: a spinning guest ran past 15s before, traps
34+
`out_of_fuel` in about 1s after.
35+
- **`cljw.http.server` could be wedged by one unfinished request.** The
36+
accept loop had no read deadline, so a client that opened a connection and
37+
never completed the request head held the whole server — which binds
38+
0.0.0.0 — indefinitely. A request-head deadline now bounds it. Measured: a
39+
half-open connection blocked the next client for 12s before, 1s after.
40+
(Note: a serial server still handles one connection at a time; this bounds
41+
the wedge, it does not add concurrency.)
42+
- **Namespace names with an empty segment resolved.** `(require (symbol
43+
"..a.b"))` could load `a.b` because the munge collapsed the doubled
44+
separator. JVM Clojure refuses such names; so does cljw now. These names
45+
cannot be written through the reader, so only computed namespace names are
46+
affected.
47+
48+
### Added
49+
50+
- **`run-server` accepts `:header-timeout-ms`** — how long a connection may
51+
take to deliver its request head. Default 10000; `0` disables the deadline.
52+
- **`wasm/run` accepts `:fuel` and `:max-memory-pages`** — the same budget
53+
keys `wasm/load` already took. `0` or negative means unmetered, which is
54+
how you opt a trusted command out of the new default.
55+
1056
### Changed
1157

1258
- **zwasm pinned to v2.4.0** (its external-consumer release:
@@ -16,6 +62,21 @@ first stable `1.0.0` tag; pre-1.0 `alpha` / `rc` tags may still change surfaces.
1662
compiler-rt, and it builds at zwasm's default Wasm 3.0 level where the
1763
DCE guard is inert. Pin hygiene, not a behaviour follow; `-Dwasm`
1864
build + the phase16 wasm e2e suite verified green on the new pin.
65+
- **Issues and Pull Requests are open.** Reports of Clojure code that
66+
behaves differently here than on the JVM are the most useful thing you can
67+
file; there is an issue template for exactly that. Outside contributors are
68+
explicitly not asked to follow the internal commit / ledger conventions —
69+
see CONTRIBUTING.
70+
71+
### Note for upgraders
72+
73+
Two behaviour changes can surface in working code:
74+
75+
1. `(wasm/run …)` is now fuel-bounded by default. A legitimately long-running
76+
guest that exceeds roughly 1e9 instructions will trap; pass `{:fuel 0}` to
77+
restore the previous unbounded behaviour.
78+
2. `(require (symbol s))` with a computed `s` containing a leading, trailing,
79+
or doubled dot no longer resolves. Well-formed names are unaffected.
1980

2081
## [1.5.1] - 2026-07-17
2182

‎build.zig.zon‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.{
22
.name = .cljw,
3-
.version = "1.5.1",
3+
.version = "1.6.0",
44
.fingerprint = 0x1869d207073beffa,
55
.minimum_zig_version = "0.16.0",
66
.dependencies = .{

0 commit comments

Comments
 (0)