Skip to content

Commit a68aa41

Browse files
authored
Merge pull request #16 from BuddhiLW/staging
v1.14.0: string/walk/slurp parity fixes, bench tier rebuilt, wasm FFI measured, cljw-native suites
2 parents 5343c81 + 10f0b61 commit a68aa41

137 files changed

Lines changed: 5809 additions & 2080 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude/CLAUDE.md‎

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,23 +88,24 @@ preserved), and `main` is the working branch:
8888

8989
## Language policy
9090

91-
Public project. **English by default** for code, comments, identifiers,
92-
commit messages, README, ROADMAP, ADRs, `.dev/`, `.claude/`, all
93-
configuration. **Japanese** for chat replies, `private/notes/<task>.md`
94-
per-task notes, and (when re-activated) `docs/ja/learn_clojurewasm/NNNN_*.md`
95-
learning narratives. The per-chapter cadence is currently **dormant**
96-
per ADR-0025; existing chapters live read-only under
97-
[`docs/ja/archive/`](../docs/ja/archive/).
98-
99-
Don't mix Japanese into English docs. In `docs/ja/`, body is Japanese;
100-
code blocks keep their original English identifiers.
101-
102-
Chat replies default to Japanese via the project output style
103-
[`.claude/output_styles/japanese.md`](../.claude/output_styles/japanese.md)
104-
(activated by `outputStyle: "Japanese"` in `.claude/settings.json`). That
105-
single setting is sufficient — the redundant SessionStart re-injection was
106-
removed. To work in another language, override `outputStyle` per-machine in
107-
`.claude/settings.local.json` (gitignored); code / commits / docs stay English.
91+
Public project, **English everywhere**: code, comments, identifiers, commit
92+
messages, chat replies, `private/notes/<task>.md`, README, ROADMAP, ADRs,
93+
`.dev/`, `.claude/`, configuration.
94+
95+
Japanese was the original author's working language. This fork's maintainer
96+
does not read it, so as of 2026-09-04 the Japanese policy is retired: the
97+
`outputStyle: "Japanese"` setting is gone from `.claude/settings.json`, and
98+
per-task notes are written in English.
99+
100+
`docs/ja/archive/` stays as it is. It is chaploud's authored work, the
101+
per-chapter cadence is dormant per ADR-0025, and archived material is not
102+
retranslated.
103+
104+
### Writing style
105+
106+
No em-dashes, no `...` ellipsis character, no LLM padding. Use a comma, a
107+
colon, parentheses, or a full stop. State the fact and stop. Long rationale
108+
goes in an ADR or hive memory, not inline in a README.
108109

109110
## Working agreement
110111

@@ -364,10 +365,10 @@ Then:
364365
**Step 7 — Per-task note** (written from hot context)
365366

366367
Copy `.claude/skills/code_learning_doc/TEMPLATE_TASK_NOTE.md` to
367-
`private/notes/<phase>-<task>.md`. Fill in: 一行サマリ / 詰まった
368-
ポイント (1-3 個) / 教科書との対比 (Step 0 survey の要約) /
369-
設計判断 / 章を書くときに必ず触れる点. Gitignored. Then immediately
370-
begin the next task's Step 0.
368+
`private/notes/<phase>-<task>.md`. Fill in, in English: summary /
369+
what was non-obvious (1-3 items) / comparison against the textbook
370+
codebases (the Step 0 survey, condensed) / design decisions / what to cite
371+
later. Gitignored. Then immediately begin the next task's Step 0.
371372

372373
### When the active work unit completes (gap-area model, ADR-0142)
373374

‎.claude/rules/accepted_divergences.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
paths:
33
- "src/**/*.zig"
44
- "src/lang/clj/**"
5-
- "scripts/clj_diff_sweep.sh"
6-
- "scripts/check_corpus_regression.sh"
5+
- "scripts/clj_diff_sweep.clj"
6+
- "scripts/corpus_regression.clj"
77
- "scripts/check_accepted_divergences.sh"
88
- ".dev/accepted_divergences.yaml"
99
- "test/diff/clj_corpus/**"

‎.claude/rules/clj_diff_sweep.md‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ two disciplines that keep that work honest.
66

77
## The harness — don't hand-roll the loop
88

9-
`scripts/clj_diff_sweep.sh` is the SSOT for "run these exprs through both
9+
`scripts/clj_diff_sweep.clj` is the SSOT for "run these exprs through both
1010
runtimes and show me the diffs". Do NOT write ad-hoc
11-
`for e in …; cljw vs clj` shell loops — they are unreviewable, throw away
11+
`for e in …; cljw vs clj` loops — they are unreviewable, throw away
1212
the result, and repeatedly re-derive the same methodology.
1313

1414
```sh
15-
bash scripts/clj_diff_sweep.sh exprs.txt # one bare value-expr per line
16-
printf '%s\n' '(map inc [1])' | bash scripts/clj_diff_sweep.sh -
17-
bash scripts/clj_diff_sweep.sh exprs.txt --corpus seqfns # append OKs to a corpus
15+
bb scripts/clj_diff_sweep.clj exprs.txt # one bare value-expr per line
16+
printf '%s\n' '(map inc [1])' | bb scripts/clj_diff_sweep.clj -
17+
bb scripts/clj_diff_sweep.clj exprs.txt --corpus seqfns # append OKs to a corpus
1818
```
1919

20-
Methodology baked into the script (header has the detail): clj runs ONCE
21-
over a batch (one `(prn EXPR)` per line); cljw runs one expr at a time;
22-
both are `timeout`-wrapped; bound every seq producer with `(take N …)`.
20+
Methodology baked into the Clojure harness: persistent clj and cljw nREPL
21+
servers receive one bounded request per expression; process ownership and
22+
cleanup stay in one babashka boundary. Bound every seq producer with
23+
`(take N …)`.
2324

2425
## Discipline 1 — corpus-backed discharge (anti D-177)
2526

@@ -30,7 +31,7 @@ mechanically re-checkable. The 2026-06-02 audit found **D-177 discharged
3031
with `take-while`/`take-nth`/`partition-by` listed as done when they were
3132
not** — a false-positive-discharge lie. The fix for that lie class is:
3233
*never list coverage you did not probe*, and leave the probe behind as a
33-
corpus line. `scripts/check_corpus_regression.sh` re-runs every corpus and
34+
corpus line. `scripts/corpus_regression.clj` re-runs every corpus and
3435
fails on any DIFF, so a regression (or an over-claim) surfaces.
3536

3637
## Discipline 2 — big-bang, don't drip-feed

‎.claude/rules/gate_cadence.md‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ found the cost/risk axis is **unit-vs-e2e, not additive-vs-shared**:
3232
the only part worth batching.
3333

3434
So the smoke = the fast correctness core (both-backend `zig build test`
35-
+ zlinter + `build_cljw` + `corpus_regression` + **the changed e2e
36-
step(s)**). Because it carries the full diff oracle, the smoke
35+
+ zlinter + `build_cljw` + `corpus_regression` + `test_reach`/`e2e_reach`
36+
+ the measured-near-zero static invariants `doc_coverage`, `epipe_head`, and
37+
`gate_parity` + **the changed e2e step(s)**). Because it carries the full diff
38+
oracle, the smoke
3739
**authorises shared-code commits too** — the old "additive vs risky"
3840
split is retired. Only the full e2e suite is deferred.
3941

@@ -139,7 +141,8 @@ run OUTSIDE both gate tiers. Fixed cadence so they cannot silently rot
139141
chain** — plus on demand after a compat-surface campaign lands.
140142

141143
Stale if: the smoke stops being ≤ ~60s or the full gate's e2e-vs-unit
142-
cost asymmetry changes (re-measure); a new shared-risk surface the smoke
144+
cost asymmetry changes (re-measure candidates with `test/run_all.sh --only`);
145+
a new shared-risk surface the smoke
143146
core does NOT cover appears (the miss-window grows beyond CLI/REPL/
144147
filesystem/http/GC e2e — re-scope what the smoke runs); or the batch of
145148
5 proves wrong in practice.

‎.claude/settings.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"defaultMode": "acceptEdits",
3-
"outputStyle": "Japanese",
43
"model": "claude-opus-4-8",
54
"permissions": {
65
"allow": [
Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- Per-task short note. Lives in private/notes/<phase>-<task>.md (gitignored).
2-
Five minutes to fill in. The future chapter writer reads this; you
3-
do not. -->
2+
Five minutes to fill in. English, per CLAUDE.md language policy.
3+
No em-dashes, no padding. State the fact and stop. -->
44

55
---
66
task: §9.X.Y
@@ -11,49 +11,28 @@ files:
1111
- src/<path>.zig
1212
---
1313

14-
## 一行サマリ
14+
## Summary
1515

16-
<task で何が動くようになったか、1 行>
16+
<one line: what works now that did not before>
1717

18-
## 詰まったポイント
18+
## What was non-obvious
1919

20-
1. <非自明な点 1>
21-
2. <非自明な点 2>
22-
3. <非自明な点 3>
20+
1. <finding 1>
21+
2. <finding 2>
22+
3. <finding 3>
2323

24-
## 教科書との対比
24+
## Comparison against the textbooks
2525

2626
- **cw v0** (git tag `v0.5.0`, via `git worktree add ../cw-v0 v0.5.0`):
27-
<cw v0 はどうしているか、ファイル名 + 1 行>
27+
<what v0 does, filename + one line>
2828
- **Clojure JVM / Babashka / Zig stdlib**:
29-
<該当する場合のみ>
29+
<only when relevant>
30+
- **DIVERGENCE**: <where this project deliberately differs, and why>
3031

31-
## 設計判断(却下した案)
32+
## Design decisions
3233

33-
- 案 A: ... 却下理由: ...
34-
- 案 B: ... 却下理由: ...
34+
- <decision, and the alternative it beat>
3535

36-
## 暫定ログ (this cycle)
36+
## Worth citing later
3737

38-
<!-- Mandatory section. See .claude/rules/provisional_marker.md. List
39-
every PROVISIONAL marker this cycle introduced / discharged /
40-
newly surfaced. Empty list (= 0 net delta, none surfaced) is a
41-
valid entry; write "なし" explicitly so audit_scaffolding can
42-
tell "thought about it" from "forgot to record". -->
43-
44-
- 導入: <file>:<line> ref [refs: D-NNN, feature_deps.yaml#<key>]
45-
理由 1 行: ...
46-
- 消化: <file>:<line> の marker 削除 (D-NNN close, feature_deps
47-
entry status: provisional → landed)
48-
- 想定外: <file>:<line> で新規暫定発見 → D-NNN row 起票
49-
50-
## 章を書くときに必ず触れるべき点
51-
52-
- <演習 1 候補>
53-
- <演習 2 候補>
54-
- <Feynman 課題候補>
55-
- <次章への伏線>
56-
57-
## TODO(直後の task に持ち越す事項)
58-
59-
- <あれば>
38+
- <the thing a future reader would otherwise have to re-derive>

‎.dev/ROADMAP.md‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ audit trail, not as a forward-looking instruction.
10411041
| 16 | **Wasm/edge-native** BUILT (gap area II) · ClojureScript→JS = future | component build/run/require ship (`cljw.wasm/*`); CLJS→JS genuinely unbuilt | |
10421042
| 17 | **VM perf: fusion → JIT** PARTIAL (gap area III) | superinstruction/fusion slice landed (D-386 / O-018/019/021/023); narrow ARM64 JIT = milestone M | |
10431043
| 18 | math + module/deps DONE · **C FFI** = future | `clojure.math` + deps.edn ship; C FFI (`dlopen`/libffi) genuinely unbuilt | |
1044-
| 19 | **Wasm/edge-native** cont. — WIT auto-binding (gap area II) | component require BUILT; gap = WIT marshalling (D-404) + zwasm integration shape (D-036/D-350) | |
1044+
| 19 | **Wasm/edge-native** cont. — WIT auto-binding (gap area II) | component require BUILT; gap = WIT marshalling (D-404); command/handle embedding shape settled by ADR-0124/D-350 | |
10451045
| 20 | **broad JIT** = future (distal; gated on gap-area-III fusion outcome) | narrow ARM64 JIT (milestone M) is the near-term scope; broad JIT decided after fusion lands | |
10461046

10471047
### 9.0 Completion-grade gap-area model (ADR-0142 / F-015 / D-440)
@@ -1081,8 +1081,9 @@ in ADRs / debt rows / overlays still resolve while R4/R5 rewrite them at source)
10811081
(gated, engine correct without them): D-244 #4a' auto-collect, D-245 Option C
10821082
blocking monitor.
10831083
- **(II) Wasm / edge-native** — `cljw.wasm/*` component build/run/require BUILT
1084-
(`src/runtime/cljw/wasm/`, embeds zwasm v2 per F-001). Gaps: WIT param marshalling
1085-
(**D-404**), zwasm integration finished-form (**D-036 / D-350 / D-039**).
1084+
(`src/runtime/cljw/wasm/`, embeds zwasm v2 per F-001). Gap: WIT param marshalling
1085+
(**D-404**). The core command/handle shape and I/O responsibility split are
1086+
settled (**ADR-0124 / D-350 / D-039**); D-036 retains only JIT coordination.
10861087
- **(III) VM perf (fusion → JIT)** — arith/compare-branch superinstructions +
10871088
reduce/lazy-seq fusion landed (**D-386 / O-018/019/021/023**). Gaps: remaining
10881089
fusion surface; **narrow ARM64 JIT (F-010 milestone M)** → broad JIT go/no-go
@@ -1525,10 +1526,12 @@ surface}.zig`, embedding zwasm v2 (`@import("zwasm")`, F-001 — SHA-pinned dep,
15251526
interp-only). e2e `phase16_wasm_{run,component,ffi,require_component}.sh` (real,
15261527
build `-Dwasm`). Gated `-Dwasm` opt-in by design (lazy dep), NOT unimplemented.
15271528
1528-
**Gaps**: WIT param-type marshalling raises `feature_not_supported`
1529-
(`component.zig`) for some types → **D-404** (full WIT↔EDN table); zwasm
1530-
integration finished-form → **D-036 / D-350 / D-039** (responsibility split,
1531-
embedding shape). Entry facts: F-001 (zwasm unavoidable) · F-004 · F-006 · F-008
1529+
**Gap**: WIT param-type marshalling raises `feature_not_supported`
1530+
(`component.zig`) for some types → **D-404** (full WIT↔EDN table). The integration
1531+
finished form is settled: persistent core-library handles, one-shot captured WASI
1532+
commands, and persistent WASI components (**ADR-0124 / D-350**); cw Tier-1 I/O
1533+
and zwasm WASI remain separate (**D-039**). D-036 retains only JIT coordination.
1534+
Entry facts: F-001 (zwasm unavoidable) · F-004 · F-006 · F-008
15321535
(zwasm v2 spec review). Consult zwasm `docs/zig_api_design.md` +
15331536
`docs/consuming_prerelease_zwasm.md` (the SHA-pin procedure).
15341537
@@ -1569,8 +1572,8 @@ work, low priority.
15691572
15701573
**Status: component require BUILT** (see §9.18). **Gap**: full WIT auto-binding
15711574
(`(wasm/component "x.wasm")` → bindgen → Clojure namespace) — some WIT param
1572-
marshalling is fixture-blocked → **D-404**; the zwasm integration shape is
1573-
**D-036 / D-350**. This is the same Wasm/edge-native gap area as §9.18.
1575+
marshalling is fixture-blocked → **D-404**. The zwasm embedding shape is settled
1576+
by **ADR-0124 / D-350**. This is the same Wasm/edge-native gap area as §9.18.
15741577
15751578
### 9.22 broad JIT = future bucket (formerly "Phase 20"; distal)
15761579

‎.dev/accepted_divergences.yaml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ accepted:
224224
recorded divergence. The class-NAME simple form (BigInt, not the FQCN) is
225225
additionally the AD-003 no-JVM-class surface.
226226
derives_from: "F-005 (numeric tower collapses BigInt/BigInteger into one `.big_int`) + AD-003 (simple class name, no JVM Class)"
227-
pin: "test/e2e/phase14_biginteger.sh — biginteger_prints_N + biginteger_class_bigint lock cljw's `5N` print and BigInt class (the divergent values, not clj's 5 / java.math.BigInteger)"
227+
pin: "test/clj/suites/biginteger_test.clj — the `biginteger-is-bigint-the-ad-016-divergence` deftest (cases biginteger_prints_N + biginteger_class_bigint) locks cljw's `5N` print and BigInt class (the divergent values, not clj's 5 / java.math.BigInteger)"
228228
- id: "AD-017"
229229
summary: "A deftype mutable field's `^long` / primitive type hint is parsed-and-ignored; cljw does not enforce clj's 'must assign primitive to primitive mutable'."
230230
example: '(deftype C [^:unsynchronized-mutable ^long n] P (go [this] (set! n "hi") n)) (go (->C 0)) => cljw "hi" / clj compile error (primitive mismatch)'
@@ -1083,7 +1083,7 @@ accepted:
10831083
already realised or was already cancelled — the JVM's contract.
10841084
example: '(let [f (future (Thread/sleep 5000))] [(.cancel f false) (.isCancelled f)]) => cljw [true true] / clj [false false] — the JVM refuses to cancel a running task when the flag is false.'
10851085
derives_from: "D-442 / ADR-0153 (cooperative cancellation) + ADR-0059 (no JVM thread interrupt)."
1086-
pin: "test/e2e/future_methods.sh — cancel_flag_is_ignored_ad065."
1086+
pin: "test/clj/suites/future_methods_test.clj — cancel_flag_is_ignored_ad065."
10871087

10881088
- id: "AD-066"
10891089
area: "collections"

0 commit comments

Comments
 (0)