Bump zwasm v1.8.0 → v1.9.0#3
Merged
Merged
Conversation
chaploud
added a commit
that referenced
this pull request
May 23, 2026
Root-cause hardening after the 2026-05-23 long-context investigation (`private/notes/llm_long_context_research.md`, 523 lines). The investigation found this session's symptoms (smell recognised → push anyway, ROADMAP-blind compliance, etc.) were not LLM attention decay but **CLAUDE.md's own "進め bias" + autonomous loop's instruction centrifugation** (~80% combined). Fix: 1. `.dev/project_facts.md` (new) — user-declared invariants the loop must treat as fact even when ROADMAP / ADR text admits other readings. F-001 (zwasm v2 unavoidable; carries its own JIT + GC), F-002 (finished-form wins; smallest-diff is tie-breaker not veto), F-003 (decision-deferral on structural plans). Added to CLAUDE.md Step 1a Phase reading list. 2. CLAUDE.md "Stop only when (closed list)" extended from 2 to 3 conditions. Condition 3 is **smell depth ≥ 3 fires 2× in one cycle → ADR-phase mode switch** (not a stop; the loop pauses the per-task work, forks a fresh-context subagent to draft a root-cause ADR, accepts inline, resumes). This catches goal drift the per-cycle sensor is too narrow to see. 3. CLAUDE.md Step 6 + § "ADR-level designs are handled inline" + .dev/principle.md depth ≥ 2 branch: **Devil's-advocate `general-purpose` subagent with fresh context is mandatory** before stamping ADR `Status: Proposed → Accepted`. Brief: produce 3 alternative shapes (smallest-diff / finished-form-clean / wildcard). Output embedded verbatim into ADR's "Alternatives considered". Counters the main loop's accumulated momentum by sourcing alternatives from a context without it. 4. CLAUDE.md Step 6 commit message shape: every source-bearing commit body must carry `Smell-audited: <depth 0-4>: <one-line summary>`. The deterministic enforcement (PreToolUse hook on git push) lands in the next commit. Handover refreshed: cold-start reading order grows from 4 to 5 files (project_facts.md inserted as #3); recent-landings block gains Wave 3 description. Smell-audited: 1: noted "private/notes/ reference in scripts" smell — local-only research note path baked into hook script + CLAUDE.md; deferred (sufficient for current session, file can be promoted to docs/ja/archive/ if cross-session access is needed; recorded inline only).
chaploud
added a commit
that referenced
this pull request
May 23, 2026
Wave 4 of the 2026-05-24 user-direction session. Captures the four direction confirmations the user gave after reviewing the struct-imagination research note (cw v0 GC + 45-tag enumeration / zwasm v1+v2 GC / Clojure JVM 140-class survey): - F-004 NaN-box second generation = 4 × 16 = 64 slot, 44-bit pointer (128 TB user space — fits all supported platforms). cw v0's slot-sharing (5 types in one delay slot) is explicitly rejected. Day-1 plan absorbs newly-imagined types: range / map_entry / tagged_literal / string_seq / array_seq / sorted_map / sorted_set / persistent_queue + wasm funcref / externref (for F-001 zwasm integration). - F-005 Numeric tower = user-observable JVM-surface compatible (Long overflow → BigInt; (/ 1 3) → Ratio; 1.5M → BigDecimal), internal Zig-stdlib-affine (std.math.big.int.Managed backing, Ratio = (BigInt × BigInt), BigDecimal = (unscaled BigInt, i32 scale)). All heap-allocated in F-004 Group D. - F-006 GC = single-generation mark-sweep + free-pool + 3-layer allocator (cw v0 path inheritance). cw v0 D100 root-set gaps (5 sources patched late) are pre-enumerated in the Phase 5 GC ADR draft. zwasm v2 heap stays separate; cw GC allocator injects into zwasm internal bookkeeping (avoids cw v0 D110 dual-GC leak). Generational deferred to ROADMAP §89.2. - F-007 Chapter cadence stays dormant. The user explicitly does not want it to resume unprompted; AI must not propose, draft, or re-activate the cadence on its own. Recorded in ADR-0025 revision history. Threaded through: - .dev/project_facts.md: F-004 / F-005 / F-006 / F-007 appended (with verbatim quotes + "what this changes for the loop" + cross-references). File grows from 3 to 7 facts. - .dev/structure_plan.md (new): anticipated directory tree Phase 5-20, marked with ★new / ★split + (D-NNN) for each divergence from the as-shipped src/ tree. Built from F-001.. F-007 + the research note. Each Phase entry owner amends in place when actual decisions land. - .dev/debt.md: D-011 / D-014a / D-027 / D-036 descriptions rewritten to embed F-NNN references and concrete shape (so the per-Phase debt sweep reads the direction without round- tripping to project_facts). - .dev/ROADMAP.md §9.7 (Phase 5) and §9.18 (Phase 16) placeholders gain "Entry facts" lines naming F-NNN to load. - .dev/decisions/0025_chapter_archive_boundary.md revision history records F-007 (user-trigger-only resumption). - .dev/handover.md cold-start reading order grows from 5 to 6 files (project_facts + structure_plan inserted as #3 and #5). - .claude/skills/continue/SKILL.md resume procedure step 2a reads project_facts + structure_plan before ROADMAP. Smell-audited: 0: clean — no source files touched, doc layer only
chaploud
added a commit
that referenced
this pull request
May 24, 2026
§9.7 task 5.0 closer. Encodes the survey at
private/notes/phase5-skeleton-audit.md (676 lines, gitignored) as
a tracked decision so §9.7 rows 5.1-5.16 execute against a fixed
activation classification map without re-deriving from the
survey.
Two load-bearing decisions:
§1 Classification of the 8 Phase-4 skeletons:
4.13 io_interface matches FF (Phase 14, ADR-0015 a2)
4.17 type_descriptor restructure (5.11)
4.18 protocol restructure (Phase 7, D-040)
4.19 ObjectHeader matches FF (5.3)
4.20 host/_host_api matches FF (Phase 6 host wave)
4.22 binding_stack reverted (6a48e90 — terminal)
4.23 numeric/big_int restructure (5.2 + 5.9)
4.24 lazy_seq restructure (5.7)
4.25 dispatch/method_table matches FF (Phase 7, D-040)
§2 Critical-path activations for 5.16 exit smoke:
5.2 → 5.3 → 5.4-5.6 → 5.7 → 5.8 → 5.9-5.10 → 5.11 → 5.12
→ 5.15 (build_options flip, mechanical after 5.12)
→ 5.16 (exit smoke).
Parallel-safe: 5.13 (analyzer split), 5.14 (host placeholder
doc).
Devil's-advocate subagent forked with fresh context per CLAUDE.md
§ "ADR-level designs are handled inline" / principle.md
"Devil's-advocate subagent is mandatory at depth ≥ 2". Subagent
output reflected verbatim into Alternatives considered (Alt 1
smallest-diff / Alt 2 finished-form-clean split / Alt 3 wildcard
pattern-ADR). Subagent recommendation: Alt 1.
Main loop disposition: Alt 1 applied with §3 reduced to a
pointer (not deleted entirely — the link to the survey's "5.1
input bullets" stays so future readers find them without
re-discovering); §4 removed entirely per the subagent's
accurate F-003-overlap observation; subagent's omitted-
constraints #1 (per-row OrbStack gate) and #2 (5.15 in critical
path) reflected into §2. Omitted-constraint #3 moot now that §3
is a pointer.
ROADMAP §9.7 row 5.0 flipped to [x] in-place with the survey
SHA / row count + the Alt 1 disposition recorded so future
audits can reconstruct the deferral choice from the row text.
Smell-audited: 1: Devil's-advocate alternative Alt 1 applied
(structural ADR shrink — depth-2 amendment of the draft before
Accepted). The original draft carried the 8 constraint bullets
verbatim; the subagent surfaced the duplication-with-5.1
concern accurately and proposed three alternatives within the
F-NNN envelope. None violated F-001..F-008. F-003 (decision-
deferral) is the active constraint here: ADR-0026 should not
pre-commit decisions the survey only surfaces — 5.1's ADR-0027
/ ADR-0028 cluster owns the bullets at the moment they bind.
chaploud
added a commit
that referenced
this pull request
May 30, 2026
…er verb D-162 finished-form decision. eval is a Layer-2 primitive; the only missing reach is the built-in macro_table (a process constant; user macros resolve via env Vars). Adopt Alt 2 (DA-recommended): a typed driver.evalValue verb (valueToForm→analyze→evalForm) consumed by the eval primitive with zero casts; the table reaches the driver via one documented ?*const anyopaque Runtime field set in the setupCorePrefix funnel (same concession as evalChunk, confined behind the typed verb). Rejected Alt 1 (per-primitive anyopaque cast — Smallest-diff-bias that compounds across structural-class-#3 recurrences) and Alt 3 (process singleton — needs forbidden module-level var per §13). DA output embedded verbatim in Alternatives considered. Smell-audited: 2: ADR-level structural choice (precedent for class #3 "primitive needs setup-time resource"); DA fork mandatory at depth 2, output embedded; picked finished-form-clean Alt 2 over smaller Alt 1 per F-002 (cycle size not a constraint).
chaploud
added a commit
that referenced
this pull request
May 30, 2026
…(D-162) Discharges D-162 per ADR-0058. eval was absent because a runtime primitive could not reach the built-in macro_table (a setup-time param, not on rt/env). Finished form (DA-recommended Alt 2): - Runtime.macro_table: ?*const anyopaque — a documented BORROW of the Layer-1 macro_dispatch.Table, type-erased per the zone barrier (same concession as VTable.evalChunk), set once in the setupCorePrefix funnel after registerInto. Process-constant table; user macros resolve via env Vars and need no table. - driver.evalValue(rt, env, locals, arena, value, loc) — a typed Layer-1 verb (valueToForm → analyze(table) → evalForm) that casts the erased pointer back at the ONE site. Reusable by future load-string / REPL read+eval (structural-defect class #3 precedent). - eval primitive (Layer 2 core.zig) calls evalValue with zero casts; per-call arena off rt.gpa holds the transient Form+Node, result Value is GC-allocated and survives. 10 e2e (phase14_eval.sh): read-string round-trip, self-eval literals, constructed lists, special forms, built-in macros (when/->/and expand inside eval — the structural proof), nested eval. Gate 169/169. Fidelity limit (follow-up): char/bignum/hash_map literals raise macro_return_not_data until valueToForm is extended. Smell-audited: 2: ADR-0058 landed first with DA fork; picked finished- form-clean Alt 2 (typed verb) over smaller Alt 1 (per-primitive cast) per F-002 — cycle size is not a constraint.
chaploud
added a commit
that referenced
this pull request
Jun 4, 2026
…090 §2) Smell-audited: 1: Phase B implementation increment #2 per ADR-0090 §2. Added gc_mutex (std.Io.Mutex) to GcHeap; lock alloc/pin/unpin (gc_heap.zig) + the whole collect() cycle (mark_sweep.zig) via the io_default singleton (the allocator API takes no io arg). Makes allocation thread-safe under F-006 — the foundation the #3 ThreadGcContext root-publication handshake builds on for collection safety. Not reentrant (alloc never calls collect; collect never allocates). Uncontended + runtime-inert today (single-threaded; real threads land at #4 future/pmap), so no observable behaviour change. New concurrency test: 4 threads x 500 allocs through a threaded io serialize race-free (allocations.len == alloc_count == 2000). Full --serial-e2e gate green 247/0; the io_default-default-single-threaded gc tests still pass (uncontended lock). bench staged per source-bearing policy (also absorbs the session's dangling doc-commit gate samples). Stale 'lock deferred to Phase B' docstring updated to describe the landed lock.
chaploud
added a commit
that referenced
this pull request
Jun 4, 2026
…locks #3; re-analysis gated (D-244) Smell-audited: 2: Bad-Smell interrupt surfaced while designing increment #3. root_set.zig roots ns_vars/current_frame/macro_root_slot/permanent_roots but NOT the VM operand stack (vm.zig local Value array) nor tree_walk native-stack intermediates; safe today only because collect() runs at quiescent explicit points (no auto-collect). For Phase B real threads (#4), a mid-eval worker's operand/native-stack Values are un-rooted -> concurrent collect UAF; plus a pushFrame/popFrame read-during-write race during another thread's root walk. So ADR-0090 §2 Alt-2's 'no safepoint needed' is insufficient for mid-eval workers. Recorded as ADR-0090 Revision history + D-244 (the #3 gating design step): re-analyse with a DA-fork (safepoint Alt-1 vs publish-VM-operand-stack-root + forbid-tree_walk-during-collect) BEFORE the handshake code. The §1-2/§5-7 spine + increments #1/#2 are unaffected (the alloc lock is needed by either mechanism).
chaploud
added a commit
that referenced
this pull request
Jun 4, 2026
…fepoint + per-frame root publication) Smell-audited: 2: D-244 (the #3 gating design step) resolved via a Step-0 survey + mandatory DA-fork. Survey: cw v0 has the SAME latent bug (vestigial ThreadRegistry; safepoint never landed) — no working mechanism to re-derive. DECISION = Alternative B: (1) force-VM worker thunks via evalChunkErased (D-196 discharged -> build.zig already .vm, so Q2's tree_walk-default fork is moot); (2) the safe point is the ALLOCATION BOUNDARY not the back-edge (Q1: vector/map/set-literal + rest-list-cons loops hold a fresh accumulator across the next alloc, un-installed -> a back-edge poll misses it; the back-edge poll survives as liveness-only); (3) publication is a per-thread CHAIN of operand-stack frames (eval recurses), not one stack. Q3 frame-pop race closed by STW-at-safepoint. No F-NNN amendment (F-006 envelope is expressive enough; no write barrier). Alt C (arena-isolated data-parallel) rejected for the spine (shared-mutable atom/agent/ref -> F-011 divergence) but kept as a future pure-pmap optimization. DA output reflected verbatim. D-244 status -> DECIDED; impl pending = #3 code.
chaploud
added a commit
that referenced
this pull request
Jun 4, 2026
…worker-only register, fold-not-11th-source)
Worked out the #3a implementation design (the delicate GC-root-walker rewire): registry lives IN root_set.zig (a separate gc_thread.zig would cycle via macro_root_slot); ThreadGcContext = {frame_slot, macro_slot} pointers to a worker's TLS; only worker threads register (main reads own TLS directly -> existing single-thread tests stay green, empty registry = current behaviour); FOLD the registry pass into the current_frame/macro_root_slot cursors rather than add an 11th RootSource (the 10-source count is asserted + ADR-0028 §5). #3b (safepoint + per-eval-frame operand-stack publication) couples to #4. Captured as the impl checklist so the most-correctness-critical code proceeds from a complete design.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cancellableflag defaults to true and the existingWasmModule.*API is unchanged.Test plan
zig build— clean build greenbash test/run_all.sh --quick— 4/4 pass (zig build test, cljw test 83 namespaces, e2e wasm, deps.edn e2e)