{"_id":"@ai-ecoverse/hot-glue","_rev":"5-97aa40c235a9d9a2a9766f7f397290e3","name":"@ai-ecoverse/hot-glue","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@ai-ecoverse/hot-glue","version":"0.1.0","keywords":["webassembly","wasm","macros","lisp","wat","self-hosting","wasi"],"license":"Apache-2.0","_id":"@ai-ecoverse/hot-glue@0.1.0","maintainers":[{"name":"trieloff","email":"lars@trieloff.net"},{"name":"karlpauls","email":"karlpauls@gmail.com"}],"homepage":"https://github.com/ai-ecoverse/hot-glue#readme","bugs":{"url":"https://github.com/ai-ecoverse/hot-glue/issues"},"bin":{"hotglue":"dist/cli.js"},"dist":{"shasum":"15473a6b9e3d1e602d80032717e6c9f696e78bb6","tarball":"https://registry.npmjs.org/@ai-ecoverse/hot-glue/-/hot-glue-0.1.0.tgz","fileCount":30,"integrity":"sha512-NZ3RBzzVggxi5sbEAPOFA0zTqgbwDU6UCPLR67BhsDO5gzNT5/YI1oYtfq1PlQZiK8jEaSoL23osjuKQNjhSoQ==","signatures":[{"sig":"MEUCIQC9tYtO5AcsXL8PubnVK9imzWw5xz3LlLu4Aajf3UkmmgIgdhNLpDRhzgd3/J/gRBwExbiFuH0xAvuuZmq5nGHcUx4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":331069},"main":"dist/bootstrap.js","type":"module","types":"./dist/bootstrap.d.ts","engines":{"node":">=20"},"scripts":{"film":"npm run -s bootstrap > /dev/null && wasmtime --dir src --dir examples --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm film.hma > dist/film.wasm && node scripts/projector.mjs dist/film.wasm","test":"vitest run","build":"tsc && cp src/*.hma dist/","compile":"wasmtime --dir src --dir examples --dir . --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm","prepack":"npm run build","build:as":"npx tsx src/cli.ts src/as.hma","perlmutt":"node scripts/perlmutt.mjs","bootstrap":"mkdir -p dist/hotglue && npx tsx src/cli.ts src/as.hma > dist/hotglue/as.wat && npx tsx src/cli.ts src/expand.hma > dist/hotglue/expand.wat && npx tsx src/cli.ts src/hotglue.hma > dist/hotglue/hotglue.wat && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/as.wat > dist/hotglue/as.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/expand.wat > dist/hotglue/expand.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/hotglue.wat > dist/hotglue/hotglue.wasm && echo 'bootstrap done — now: npm run -s compile -- program.hma > program.wasm'","build:web":"npx tsx src/build-web.ts","build:zig":"zig build-exe examples/native/fnv.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1048576 --stack 8192 --export=fnv1a --export=motto_ptr --export=motto_len -femit-bin=examples/native/fnv.wasm && zig build-exe examples/native/mix.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1179648 --stack 8192 --export=stamp -femit-bin=examples/native/mix.wasm","test:watch":"vitest","build:braid":"npm run -s build:zig && mkdir -p dist && npx tsx src/cli.ts src/as.hma > dist/as.wat && npx tsx src/cli.ts examples/braid.hma > dist/braid-sup.wat && npx tsx src/cli.ts examples/stamp-seam.hma > dist/braid-seam.wat && wasmtime run --invoke run dist/as.wat < dist/braid-sup.wat > dist/braid-sup.wasm && wasmtime run --invoke run dist/as.wat < dist/braid-seam.wat > dist/braid-seam.wasm && wasm-merge dist/braid-sup.wasm env examples/native/fnv.wasm fnv examples/native/mix.wasm mix dist/braid-seam.wasm seam -o dist/braid.wasm && echo 'dist/braid.wasm — run: wasmtime dist/braid.wasm'","build:espeak":"bash scripts/build-espeak-wasi.sh","build:expand":"npx tsx src/cli.ts src/expand.hma","build:ffmpeg":"bash scripts/build-ffmpeg-wasi.sh","build:frei0r":"npx tsx src/cli.ts examples/mandelzoom.hma > /tmp/mandelzoom.wat && npx tsx src/cli.ts src/as.hma > /tmp/as.wat && wasmtime run --invoke run /tmp/as.wat < /tmp/mandelzoom.wat > /tmp/mandelzoom.wasm && node -e \"const b=require('fs').readFileSync('/tmp/mandelzoom.wasm');let o='const unsigned char hotglue_wasm[] = {';for(let i=0;i<b.length;i++)o+=(i%12?' ':'\\n  ')+'0x'+b[i].toString(16).padStart(2,'0')+',';o+='\\n};\\nconst unsigned int hotglue_wasm_len = '+b.length+';\\n';require('fs').writeFileSync('/tmp/mandelzoom_wasm.c',o)\" && clang -O2 -shared -fPIC -I \"$WASMTIME_CAPI/include\" examples/native/frei0r_hotglue.c /tmp/mandelzoom_wasm.c \"$WASMTIME_CAPI/lib/libwasmtime.a\" -lpthread -ldl -lm -o hotglue_mandel.so && echo 'built hotglue_mandel.so — run: FREI0R_PATH=$PWD ffmpeg -f lavfi -i frei0r_src=size=256x256:framerate=30:filter_name=hotglue_mandel:filter_params=x -t 5 out.mp4'","build:native":"clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export=poke -Wl,--export=crc32 examples/native/crc32.c -o examples/native/crc32.wasm && rustc --target wasm32-unknown-unknown --crate-type=cdylib -C opt-level=z -C lto -C strip=symbols -C panic=abort examples/native/fmix.rs -o examples/native/fmix.wasm","build:webgpu":"bash scripts/build-mandel-webgpu.sh","fetch:kokoro":"mkdir -p models/kokoro/onnx models/kokoro/voices && B=https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main && curl -LsSf -o models/kokoro/config.json $B/config.json && curl -LsSf -o models/kokoro/tokenizer.json $B/tokenizer.json && curl -LsSf -o models/kokoro/tokenizer_config.json $B/tokenizer_config.json && curl -LsSf -o models/kokoro/onnx/model_quantized.onnx $B/onnx/model_quantized.onnx && curl -LsSf -o models/kokoro/voices/af_heart.bin $B/voices/af_heart.bin","train:oyster":"python3 scripts/train-oyster.py","build:expand-gc":"npx tsx src/cli.ts src/expand-gc.hma"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/ai-ecoverse/hot-glue.git","type":"git"},"_npmVersion":"11.19.0","description":"A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly","directories":{},"_nodeVersion":"26.7.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^3.0.0","binaryen":"^132.0.0","kokoro-js":"^1.2.1","typescript":"^5.7.0","@types/node":"^22.19.11","@ffmpeg/core":"^0.11.0","@ffmpeg/ffmpeg":"^0.11.6","playwright-core":"^1.62.1","semantic-release":"^25.0.9","@6over3/zeroperl-ts":"^1.0.10"},"peerDependencies":{"binaryen":"^132.0.0"},"peerDependenciesMeta":{"binaryen":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hot-glue_0.1.0_1788163041258_0.8007513588055486","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@ai-ecoverse/hot-glue","version":"0.1.1","keywords":["webassembly","wasm","macros","lisp","wat","self-hosting","wasi"],"license":"Apache-2.0","_id":"@ai-ecoverse/hot-glue@0.1.1","maintainers":[{"name":"trieloff","email":"lars@trieloff.net"},{"name":"karlpauls","email":"karlpauls@gmail.com"}],"homepage":"https://github.com/ai-ecoverse/hot-glue#readme","bugs":{"url":"https://github.com/ai-ecoverse/hot-glue/issues"},"bin":{"hotglue":"dist/cli.js"},"dist":{"shasum":"5e3a68c3fec9fad98fbf1539588ea88e8dff5b07","tarball":"https://registry.npmjs.org/@ai-ecoverse/hot-glue/-/hot-glue-0.1.1.tgz","fileCount":30,"integrity":"sha512-bFSLCCa8LoOgTsYybAgcpKfTin7MkuMNSJG2tJIaJ+U8MTSnTruk+fSvXQnk3T3VGpgqomu4022PPuLdtGWHww==","signatures":[{"sig":"MEYCIQDbhmS/9ayUo8Pt0IyyF44SRM4CwwiwsA9Zv/uzQv1N/gIhAP5P10vY6vvQuJ2BdTN4caWT9lF0gqQ8J6sLrbm8RZxw","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-ecoverse%2fhot-glue@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":331154},"main":"dist/bootstrap.js","type":"module","types":"./dist/bootstrap.d.ts","engines":{"node":">=20"},"gitHead":"5f8c4bd17e19e221ba91fa1fbbdd1020a509e1cd","scripts":{"film":"npm run -s bootstrap > /dev/null && wasmtime --dir src --dir examples --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm film.hma > dist/film.wasm && node scripts/projector.mjs dist/film.wasm","test":"vitest run","build":"tsc && cp src/*.hma dist/","compile":"wasmtime --dir src --dir examples --dir . --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm","prepack":"npm run build","build:as":"npx tsx src/cli.ts src/as.hma","perlmutt":"node scripts/perlmutt.mjs","bootstrap":"mkdir -p dist/hotglue && npx tsx src/cli.ts src/as.hma > dist/hotglue/as.wat && npx tsx src/cli.ts src/expand.hma > dist/hotglue/expand.wat && npx tsx src/cli.ts src/hotglue.hma > dist/hotglue/hotglue.wat && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/as.wat > dist/hotglue/as.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/expand.wat > dist/hotglue/expand.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/hotglue.wat > dist/hotglue/hotglue.wasm && echo 'bootstrap done — now: npm run -s compile -- program.hma > program.wasm'","build:web":"npx tsx src/build-web.ts","build:zig":"zig build-exe examples/native/fnv.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1048576 --stack 8192 --export=fnv1a --export=motto_ptr --export=motto_len -femit-bin=examples/native/fnv.wasm && zig build-exe examples/native/mix.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1179648 --stack 8192 --export=stamp -femit-bin=examples/native/mix.wasm","test:watch":"vitest","build:braid":"npm run -s build:zig && mkdir -p dist && npx tsx src/cli.ts src/as.hma > dist/as.wat && npx tsx src/cli.ts examples/braid.hma > dist/braid-sup.wat && npx tsx src/cli.ts examples/stamp-seam.hma > dist/braid-seam.wat && wasmtime run --invoke run dist/as.wat < dist/braid-sup.wat > dist/braid-sup.wasm && wasmtime run --invoke run dist/as.wat < dist/braid-seam.wat > dist/braid-seam.wasm && wasm-merge dist/braid-sup.wasm env examples/native/fnv.wasm fnv examples/native/mix.wasm mix dist/braid-seam.wasm seam -o dist/braid.wasm && echo 'dist/braid.wasm — run: wasmtime dist/braid.wasm'","build:espeak":"bash scripts/build-espeak-wasi.sh","build:expand":"npx tsx src/cli.ts src/expand.hma","build:ffmpeg":"bash scripts/build-ffmpeg-wasi.sh","build:frei0r":"npx tsx src/cli.ts examples/mandelzoom.hma > /tmp/mandelzoom.wat && npx tsx src/cli.ts src/as.hma > /tmp/as.wat && wasmtime run --invoke run /tmp/as.wat < /tmp/mandelzoom.wat > /tmp/mandelzoom.wasm && node -e \"const b=require('fs').readFileSync('/tmp/mandelzoom.wasm');let o='const unsigned char hotglue_wasm[] = {';for(let i=0;i<b.length;i++)o+=(i%12?' ':'\\n  ')+'0x'+b[i].toString(16).padStart(2,'0')+',';o+='\\n};\\nconst unsigned int hotglue_wasm_len = '+b.length+';\\n';require('fs').writeFileSync('/tmp/mandelzoom_wasm.c',o)\" && clang -O2 -shared -fPIC -I \"$WASMTIME_CAPI/include\" examples/native/frei0r_hotglue.c /tmp/mandelzoom_wasm.c \"$WASMTIME_CAPI/lib/libwasmtime.a\" -lpthread -ldl -lm -o hotglue_mandel.so && echo 'built hotglue_mandel.so — run: FREI0R_PATH=$PWD ffmpeg -f lavfi -i frei0r_src=size=256x256:framerate=30:filter_name=hotglue_mandel:filter_params=x -t 5 out.mp4'","build:native":"clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export=poke -Wl,--export=crc32 examples/native/crc32.c -o examples/native/crc32.wasm && rustc --target wasm32-unknown-unknown --crate-type=cdylib -C opt-level=z -C lto -C strip=symbols -C panic=abort examples/native/fmix.rs -o examples/native/fmix.wasm","build:webgpu":"bash scripts/build-mandel-webgpu.sh","fetch:kokoro":"mkdir -p models/kokoro/onnx models/kokoro/voices && B=https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main && curl -LsSf -o models/kokoro/config.json $B/config.json && curl -LsSf -o models/kokoro/tokenizer.json $B/tokenizer.json && curl -LsSf -o models/kokoro/tokenizer_config.json $B/tokenizer_config.json && curl -LsSf -o models/kokoro/onnx/model_quantized.onnx $B/onnx/model_quantized.onnx && curl -LsSf -o models/kokoro/voices/af_heart.bin $B/voices/af_heart.bin","train:oyster":"python3 scripts/train-oyster.py","build:expand-gc":"npx tsx src/cli.ts src/expand-gc.hma"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:007b6e84-f1fc-4bea-9c07-2ef06da93c4c"}},"repository":{"url":"git+https://github.com/ai-ecoverse/hot-glue.git","type":"git"},"_npmVersion":"11.19.1","description":"A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^3.0.0","binaryen":"^132.0.0","kokoro-js":"^1.2.1","typescript":"^5.7.0","@types/node":"^22.19.11","@ffmpeg/core":"^0.11.0","@ffmpeg/ffmpeg":"^0.11.6","playwright-core":"^1.62.1","semantic-release":"^25.0.9","@6over3/zeroperl-ts":"^1.0.10"},"peerDependencies":{"binaryen":"^132.0.0"},"peerDependenciesMeta":{"binaryen":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hot-glue_0.1.1_1788163859229_0.20732282131387914","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@ai-ecoverse/hot-glue","version":"0.2.0","keywords":["webassembly","wasm","macros","lisp","wat","self-hosting","wasi"],"license":"Apache-2.0","_id":"@ai-ecoverse/hot-glue@0.2.0","maintainers":[{"name":"trieloff","email":"lars@trieloff.net"},{"name":"karlpauls","email":"karlpauls@gmail.com"}],"homepage":"https://github.com/ai-ecoverse/hot-glue#readme","bugs":{"url":"https://github.com/ai-ecoverse/hot-glue/issues"},"bin":{"hotglue":"dist/cli.js"},"dist":{"shasum":"6881b1c219babf93c3cad6efd30a6586f0118246","tarball":"https://registry.npmjs.org/@ai-ecoverse/hot-glue/-/hot-glue-0.2.0.tgz","fileCount":30,"integrity":"sha512-y+XVvAe6nRX1MXlr4xn0W09NKZQmQzsyQD+M5fmxep0FDFC0VmyRIuP1Sa8LLC02FkAJTjB82Tr1sJHjkLnpWQ==","signatures":[{"sig":"MEQCIA3/HtWgvoPpuSBbnEy0iXuDP1ioL9SzveSjE5YjVeYQAiBDysebLR07fH48dPFmqM/u5K9uNS9gAFEzdsD0tIaYbQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-ecoverse%2fhot-glue@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":334049},"main":"dist/bootstrap.js","type":"module","types":"./dist/bootstrap.d.ts","engines":{"node":">=20"},"gitHead":"a6aa50e649667277028fe3a35848c0b4264e686e","scripts":{"film":"npm run -s bootstrap > /dev/null && wasmtime --dir src --dir examples --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm film.hma > dist/film.wasm && node scripts/projector.mjs dist/film.wasm","test":"vitest run","build":"tsc && cp src/*.hma dist/","compile":"wasmtime --dir src --dir examples --dir . --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm","prepack":"npm run build","build:as":"npx tsx src/cli.ts src/as.hma","perlmutt":"node scripts/perlmutt.mjs","bootstrap":"mkdir -p dist/hotglue && npx tsx src/cli.ts src/as.hma > dist/hotglue/as.wat && npx tsx src/cli.ts src/expand.hma > dist/hotglue/expand.wat && npx tsx src/cli.ts src/hotglue.hma > dist/hotglue/hotglue.wat && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/as.wat > dist/hotglue/as.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/expand.wat > dist/hotglue/expand.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/hotglue.wat > dist/hotglue/hotglue.wasm && echo 'bootstrap done — now: npm run -s compile -- program.hma > program.wasm'","build:web":"npx tsx src/build-web.ts","build:zig":"zig build-exe examples/native/fnv.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1048576 --stack 8192 --export=fnv1a --export=motto_ptr --export=motto_len -femit-bin=examples/native/fnv.wasm && zig build-exe examples/native/mix.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1179648 --stack 8192 --export=stamp -femit-bin=examples/native/mix.wasm","test:watch":"vitest","build:braid":"npm run -s build:zig && mkdir -p dist && npx tsx src/cli.ts src/as.hma > dist/as.wat && npx tsx src/cli.ts examples/braid.hma > dist/braid-sup.wat && npx tsx src/cli.ts examples/stamp-seam.hma > dist/braid-seam.wat && wasmtime run --invoke run dist/as.wat < dist/braid-sup.wat > dist/braid-sup.wasm && wasmtime run --invoke run dist/as.wat < dist/braid-seam.wat > dist/braid-seam.wasm && wasm-merge dist/braid-sup.wasm env examples/native/fnv.wasm fnv examples/native/mix.wasm mix dist/braid-seam.wasm seam -o dist/braid.wasm && echo 'dist/braid.wasm — run: wasmtime dist/braid.wasm'","build:espeak":"bash scripts/build-espeak-wasi.sh","build:expand":"npx tsx src/cli.ts src/expand.hma","build:ffmpeg":"bash scripts/build-ffmpeg-wasi.sh","build:frei0r":"npx tsx src/cli.ts examples/mandelzoom.hma > /tmp/mandelzoom.wat && npx tsx src/cli.ts src/as.hma > /tmp/as.wat && wasmtime run --invoke run /tmp/as.wat < /tmp/mandelzoom.wat > /tmp/mandelzoom.wasm && node -e \"const b=require('fs').readFileSync('/tmp/mandelzoom.wasm');let o='const unsigned char hotglue_wasm[] = {';for(let i=0;i<b.length;i++)o+=(i%12?' ':'\\n  ')+'0x'+b[i].toString(16).padStart(2,'0')+',';o+='\\n};\\nconst unsigned int hotglue_wasm_len = '+b.length+';\\n';require('fs').writeFileSync('/tmp/mandelzoom_wasm.c',o)\" && clang -O2 -shared -fPIC -I \"$WASMTIME_CAPI/include\" examples/native/frei0r_hotglue.c /tmp/mandelzoom_wasm.c \"$WASMTIME_CAPI/lib/libwasmtime.a\" -lpthread -ldl -lm -o hotglue_mandel.so && echo 'built hotglue_mandel.so — run: FREI0R_PATH=$PWD ffmpeg -f lavfi -i frei0r_src=size=256x256:framerate=30:filter_name=hotglue_mandel:filter_params=x -t 5 out.mp4'","build:native":"clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export=poke -Wl,--export=crc32 examples/native/crc32.c -o examples/native/crc32.wasm && rustc --target wasm32-unknown-unknown --crate-type=cdylib -C opt-level=z -C lto -C strip=symbols -C panic=abort examples/native/fmix.rs -o examples/native/fmix.wasm","build:webgpu":"bash scripts/build-mandel-webgpu.sh","fetch:kokoro":"mkdir -p models/kokoro/onnx models/kokoro/voices && B=https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main && curl -LsSf -o models/kokoro/config.json $B/config.json && curl -LsSf -o models/kokoro/tokenizer.json $B/tokenizer.json && curl -LsSf -o models/kokoro/tokenizer_config.json $B/tokenizer_config.json && curl -LsSf -o models/kokoro/onnx/model_quantized.onnx $B/onnx/model_quantized.onnx && curl -LsSf -o models/kokoro/voices/af_heart.bin $B/voices/af_heart.bin","train:oyster":"python3 scripts/train-oyster.py","build:expand-gc":"npx tsx src/cli.ts src/expand-gc.hma"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:007b6e84-f1fc-4bea-9c07-2ef06da93c4c"}},"repository":{"url":"git+https://github.com/ai-ecoverse/hot-glue.git","type":"git"},"_npmVersion":"11.19.1","description":"A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^3.0.0","binaryen":"^132.0.0","kokoro-js":"^1.2.1","typescript":"^5.7.0","@types/node":"^22.19.11","@ffmpeg/core":"^0.11.0","@ffmpeg/ffmpeg":"^0.11.6","playwright-core":"^1.62.1","semantic-release":"^25.0.9","@6over3/zeroperl-ts":"^1.0.10"},"peerDependencies":{"binaryen":"^132.0.0"},"peerDependenciesMeta":{"binaryen":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hot-glue_0.2.0_1788164384094_0.7974343255805181","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@ai-ecoverse/hot-glue","version":"0.2.1","keywords":["webassembly","wasm","macros","lisp","wat","self-hosting","wasi"],"license":"Apache-2.0","_id":"@ai-ecoverse/hot-glue@0.2.1","maintainers":[{"name":"trieloff","email":"lars@trieloff.net"},{"name":"karlpauls","email":"karlpauls@gmail.com"}],"homepage":"https://github.com/ai-ecoverse/hot-glue#readme","bugs":{"url":"https://github.com/ai-ecoverse/hot-glue/issues"},"bin":{"hotglue":"dist/cli.js"},"dist":{"shasum":"eb32299737f9a9714fc3dc4830af2f4807807a7a","tarball":"https://registry.npmjs.org/@ai-ecoverse/hot-glue/-/hot-glue-0.2.1.tgz","fileCount":30,"integrity":"sha512-NzsTc0EBeXLAgmgP53JkftTVecq0llLn/diLpYN3FnpPffJdiyKFPDRUwG80TD6+cB/ULF/eq0xrupcWDtvwRg==","signatures":[{"sig":"MEUCIQClZ9DFZVvb52ON+0UqtS1f0xUXPKZtTfs0JFVnSkVY6AIgHrGbClLqZ5ndDfiy5oktTVl/TQU0AuJTBfPwz9fSyus=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-ecoverse%2fhot-glue@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":335893},"main":"dist/bootstrap.js","type":"module","types":"./dist/bootstrap.d.ts","engines":{"node":">=20"},"gitHead":"a4d111a1c14d17ec391259f559c81352dc235133","scripts":{"film":"npm run -s bootstrap > /dev/null && wasmtime --dir src --dir examples --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm film.hma > dist/film.wasm && node scripts/projector.mjs dist/film.wasm","test":"vitest run","build":"tsc && cp src/*.hma dist/","compile":"wasmtime --dir src --dir examples --dir . --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm","prepack":"npm run build","build:as":"npx tsx src/cli.ts src/as.hma","perlmutt":"node scripts/perlmutt.mjs","bootstrap":"mkdir -p dist/hotglue && npx tsx src/cli.ts src/as.hma > dist/hotglue/as.wat && npx tsx src/cli.ts src/expand.hma > dist/hotglue/expand.wat && npx tsx src/cli.ts src/hotglue.hma > dist/hotglue/hotglue.wat && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/as.wat > dist/hotglue/as.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/expand.wat > dist/hotglue/expand.wasm && wasmtime run --invoke run dist/hotglue/as.wat < dist/hotglue/hotglue.wat > dist/hotglue/hotglue.wasm && echo 'bootstrap done — now: npm run -s compile -- program.hma > program.wasm'","build:web":"npx tsx src/build-web.ts","build:zig":"zig build-exe examples/native/fnv.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1048576 --stack 8192 --export=fnv1a --export=motto_ptr --export=motto_len -femit-bin=examples/native/fnv.wasm && zig build-exe examples/native/mix.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1179648 --stack 8192 --export=stamp -femit-bin=examples/native/mix.wasm","test:watch":"vitest","build:braid":"npm run -s build:zig && mkdir -p dist && npx tsx src/cli.ts src/as.hma > dist/as.wat && npx tsx src/cli.ts examples/braid.hma > dist/braid-sup.wat && npx tsx src/cli.ts examples/stamp-seam.hma > dist/braid-seam.wat && wasmtime run --invoke run dist/as.wat < dist/braid-sup.wat > dist/braid-sup.wasm && wasmtime run --invoke run dist/as.wat < dist/braid-seam.wat > dist/braid-seam.wasm && wasm-merge dist/braid-sup.wasm env examples/native/fnv.wasm fnv examples/native/mix.wasm mix dist/braid-seam.wasm seam -o dist/braid.wasm && echo 'dist/braid.wasm — run: wasmtime dist/braid.wasm'","build:espeak":"bash scripts/build-espeak-wasi.sh","build:expand":"npx tsx src/cli.ts src/expand.hma","build:ffmpeg":"bash scripts/build-ffmpeg-wasi.sh","build:frei0r":"npx tsx src/cli.ts examples/mandelzoom.hma > /tmp/mandelzoom.wat && npx tsx src/cli.ts src/as.hma > /tmp/as.wat && wasmtime run --invoke run /tmp/as.wat < /tmp/mandelzoom.wat > /tmp/mandelzoom.wasm && node -e \"const b=require('fs').readFileSync('/tmp/mandelzoom.wasm');let o='const unsigned char hotglue_wasm[] = {';for(let i=0;i<b.length;i++)o+=(i%12?' ':'\\n  ')+'0x'+b[i].toString(16).padStart(2,'0')+',';o+='\\n};\\nconst unsigned int hotglue_wasm_len = '+b.length+';\\n';require('fs').writeFileSync('/tmp/mandelzoom_wasm.c',o)\" && clang -O2 -shared -fPIC -I \"$WASMTIME_CAPI/include\" examples/native/frei0r_hotglue.c /tmp/mandelzoom_wasm.c \"$WASMTIME_CAPI/lib/libwasmtime.a\" -lpthread -ldl -lm -o hotglue_mandel.so && echo 'built hotglue_mandel.so — run: FREI0R_PATH=$PWD ffmpeg -f lavfi -i frei0r_src=size=256x256:framerate=30:filter_name=hotglue_mandel:filter_params=x -t 5 out.mp4'","build:native":"clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export=poke -Wl,--export=crc32 examples/native/crc32.c -o examples/native/crc32.wasm && rustc --target wasm32-unknown-unknown --crate-type=cdylib -C opt-level=z -C lto -C strip=symbols -C panic=abort examples/native/fmix.rs -o examples/native/fmix.wasm","build:webgpu":"bash scripts/build-mandel-webgpu.sh","fetch:kokoro":"mkdir -p models/kokoro/onnx models/kokoro/voices && B=https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main && curl -LsSf -o models/kokoro/config.json $B/config.json && curl -LsSf -o models/kokoro/tokenizer.json $B/tokenizer.json && curl -LsSf -o models/kokoro/tokenizer_config.json $B/tokenizer_config.json && curl -LsSf -o models/kokoro/onnx/model_quantized.onnx $B/onnx/model_quantized.onnx && curl -LsSf -o models/kokoro/voices/af_heart.bin $B/voices/af_heart.bin","train:oyster":"python3 scripts/train-oyster.py","build:expand-gc":"npx tsx src/cli.ts src/expand-gc.hma"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:007b6e84-f1fc-4bea-9c07-2ef06da93c4c"}},"repository":{"url":"git+https://github.com/ai-ecoverse/hot-glue.git","type":"git"},"_npmVersion":"11.19.1","description":"A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^4.0.0","binaryen":"^132.0.0","kokoro-js":"^1.2.1","typescript":"^5.7.0","@types/node":"^26.0.0","@ffmpeg/core":"^0.11.0","@ffmpeg/ffmpeg":"^0.11.6","playwright-core":"^1.62.1","semantic-release":"^25.0.9","@6over3/zeroperl-ts":"^1.0.10"},"peerDependencies":{"binaryen":"^132.0.0"},"peerDependenciesMeta":{"binaryen":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/hot-glue_0.2.1_1788167669181_0.584527457662392","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@ai-ecoverse/hot-glue","version":"0.3.0","type":"module","description":"A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly","keywords":["webassembly","wasm","macros","lisp","wat","self-hosting","wasi"],"repository":{"type":"git","url":"git+https://github.com/ai-ecoverse/hot-glue.git"},"main":"dist/drive.js","bin":{"hotglue":"dist/hotglue.js"},"scripts":{"build":"tsc && cp src/*.hma dist/","prepack":"npm run build && npm run -s bootstrap && cp dist/hotglue/*.wasm dist/","build:as":"npx tsx src/cli.ts src/as.hma","build:expand":"npx tsx src/cli.ts src/expand.hma","build:expand-gc":"npx tsx src/cli.ts src/expand-gc.hma","build:native":"clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export=poke -Wl,--export=crc32 examples/native/crc32.c -o examples/native/crc32.wasm && rustc --target wasm32-unknown-unknown --crate-type=cdylib -C opt-level=z -C lto -C strip=symbols -C panic=abort examples/native/fmix.rs -o examples/native/fmix.wasm","build:frei0r":"npx tsx src/cli.ts examples/mandelzoom.hma > /tmp/mandelzoom.wat && npx tsx src/cli.ts src/as.hma > /tmp/as.wat && wasmtime run --invoke run /tmp/as.wat < /tmp/mandelzoom.wat > /tmp/mandelzoom.wasm && node -e \"const b=require('fs').readFileSync('/tmp/mandelzoom.wasm');let o='const unsigned char hotglue_wasm[] = {';for(let i=0;i<b.length;i++)o+=(i%12?' ':'\\n  ')+'0x'+b[i].toString(16).padStart(2,'0')+',';o+='\\n};\\nconst unsigned int hotglue_wasm_len = '+b.length+';\\n';require('fs').writeFileSync('/tmp/mandelzoom_wasm.c',o)\" && clang -O2 -shared -fPIC -I \"$WASMTIME_CAPI/include\" examples/native/frei0r_hotglue.c /tmp/mandelzoom_wasm.c \"$WASMTIME_CAPI/lib/libwasmtime.a\" -lpthread -ldl -lm -o hotglue_mandel.so && echo 'built hotglue_mandel.so — run: FREI0R_PATH=$PWD ffmpeg -f lavfi -i frei0r_src=size=256x256:framerate=30:filter_name=hotglue_mandel:filter_params=x -t 5 out.mp4'","build:web":"npx tsx src/build-web.ts","build:ffmpeg":"bash scripts/build-ffmpeg-wasi.sh","build:espeak":"bash scripts/build-espeak-wasi.sh","build:webgpu":"bash scripts/build-mandel-webgpu.sh","bootstrap":"bash scripts/bootstrap.sh","compile":"wasmtime --dir src --dir examples --dir . --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm","fetch:kokoro":"mkdir -p models/kokoro/onnx models/kokoro/voices && B=https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main && curl -LsSf -o models/kokoro/config.json $B/config.json && curl -LsSf -o models/kokoro/tokenizer.json $B/tokenizer.json && curl -LsSf -o models/kokoro/tokenizer_config.json $B/tokenizer_config.json && curl -LsSf -o models/kokoro/onnx/model_quantized.onnx $B/onnx/model_quantized.onnx && curl -LsSf -o models/kokoro/voices/af_heart.bin $B/voices/af_heart.bin","perlmutt":"node scripts/perlmutt.mjs","train:oyster":"python3 scripts/train-oyster.py","film":"npm run -s bootstrap > /dev/null && wasmtime --dir src --dir examples --preload expand=dist/hotglue/expand.wasm --preload as=dist/hotglue/as.wasm dist/hotglue/hotglue.wasm film.hma > dist/film.wasm && node scripts/projector.mjs dist/film.wasm","test":"vitest run","test:watch":"vitest","build:zig":"zig build-exe examples/native/fnv.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1048576 --stack 8192 --export=fnv1a --export=motto_ptr --export=motto_len -femit-bin=examples/native/fnv.wasm && zig build-exe examples/native/mix.zig -target wasm32-freestanding -O ReleaseSmall -fno-entry --import-memory --initial-memory=2097152 --global-base=1179648 --stack 8192 --export=stamp -femit-bin=examples/native/mix.wasm","build:braid":"npm run -s build:zig && mkdir -p dist && npx tsx src/cli.ts src/as.hma > dist/as.wat && npx tsx src/cli.ts examples/braid.hma > dist/braid-sup.wat && npx tsx src/cli.ts examples/stamp-seam.hma > dist/braid-seam.wat && wasmtime run --invoke run dist/as.wat < dist/braid-sup.wat > dist/braid-sup.wasm && wasmtime run --invoke run dist/as.wat < dist/braid-seam.wat > dist/braid-seam.wasm && wasm-merge dist/braid-sup.wasm env examples/native/fnv.wasm fnv examples/native/mix.wasm mix dist/braid-seam.wasm seam -o dist/braid.wasm && echo 'dist/braid.wasm — run: wasmtime dist/braid.wasm'"},"devDependencies":{"@6over3/zeroperl-ts":"^1.0.10","@ffmpeg/core":"^0.11.0","@ffmpeg/ffmpeg":"^0.11.6","@types/node":"^26.0.0","binaryen":"^132.0.0","kokoro-js":"^1.2.1","playwright-core":"^1.62.1","semantic-release":"^25.0.9","tsx":"^4.19.2","typescript":"^5.7.0","vitest":"^4.0.0"},"license":"Apache-2.0","publishConfig":{"access":"public"},"engines":{"node":">=20"},"peerDependencies":{"binaryen":"^132.0.0"},"peerDependenciesMeta":{"binaryen":{"optional":true}},"gitHead":"8fe5dad34fa8fc856f7aff01e0bb6fda199581e5","types":"./dist/drive.d.ts","_id":"@ai-ecoverse/hot-glue@0.3.0","bugs":{"url":"https://github.com/ai-ecoverse/hot-glue/issues"},"homepage":"https://github.com/ai-ecoverse/hot-glue#readme","_nodeVersion":"24.19.0","_npmVersion":"11.19.1","dist":{"integrity":"sha512-D1JlKFcSfJAplgd0Tf0z74hkKDG4ggHJk0NrRX7uL7GGy/ShEQt0VPlnzG+FISrTii2l0GiGtfqtfiWnbGosvQ==","shasum":"80b4dfb6c480428a8a2215c4d27d5d7dd9acd10d","tarball":"https://registry.npmjs.org/@ai-ecoverse/hot-glue/-/hot-glue-0.3.0.tgz","fileCount":27,"unpackedSize":326669,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-ecoverse%2fhot-glue@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDIkHIgpfFOmRHMGfH9FZjCJMeHduFoZPwVKZxnyfTTwQIgQbKTXjN2wZFp3yB8CS4YFh+Z6lUlUZyfWbfcU8eBWO0="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:007b6e84-f1fc-4bea-9c07-2ef06da93c4c"}},"directories":{},"maintainers":[{"name":"trieloff","email":"lars@trieloff.net"},{"name":"karlpauls","email":"karlpauls@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hot-glue_0.3.0_1788184619938_0.8597188991780462"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-31T07:57:20.945Z","modified":"2026-08-31T13:57:00.454Z","0.1.0":"2026-08-31T07:57:21.387Z","0.1.1":"2026-08-31T08:10:59.356Z","0.2.0":"2026-08-31T08:19:44.218Z","0.2.1":"2026-08-31T09:14:29.315Z","0.3.0":"2026-08-31T13:57:00.070Z"},"bugs":{"url":"https://github.com/ai-ecoverse/hot-glue/issues"},"license":"Apache-2.0","homepage":"https://github.com/ai-ecoverse/hot-glue#readme","keywords":["webassembly","wasm","macros","lisp","wat","self-hosting","wasi"],"repository":{"type":"git","url":"git+https://github.com/ai-ecoverse/hot-glue.git"},"description":"A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly","maintainers":[{"name":"trieloff","email":"lars@trieloff.net"},{"name":"karlpauls","email":"karlpauls@gmail.com"}],"readme":"# Hot Glue\n\n**A macro expander for WebAssembly, written in WebAssembly, operating on WebAssembly.**\n\nHot melt adhesive — the industrial term, which is better than any pun because it\nis simply what the thing is. Hot Glue is a Lisp whose object language is WAT and\nwhose meta language is itself. Macros are hygienic. The expander expands its own\nsource. The assembler assembles its own source. The compiler is a 2.5 KB wasm\nbinary that compiles the expander, the assembler, and itself, byte-identically to\nthe bootstrap path — and after the bootstrap, no program here is TypeScript.\n\nFile extension: `.hma`.\n\n---\n\n## Quick start\n\nUse the expander without installing anything:\n\n```sh\nnpx @ai-ecoverse/hot-glue program.hma > program.wat\nwasmtime program.wat\n```\n\nNo TypeScript ran in that. The package carries the three organs the bootstrap\nmints — `expand.wasm`, `as.wasm`, `hotglue.wasm` — and Node hosts them; stage 0\nstays in the checkout, where it belongs. Which means a binary needs no toolchain\nat all, not even a wasmtime:\n\n```sh\nnpx @ai-ecoverse/hot-glue -w program.hma > program.wasm\n```\n\nThe prelude travels with it, so `(use prelude.hma)` resolves against the sources\nshipped beside the program — there is no checkout for it to need, and an entry\nfile that is not a path is looked up the same way. `--help` says the rest; `-O`\nemits *optimized* wasm, if the optional `binaryen` peer is installed. To keep it\naround, `npm install -g @ai-ecoverse/hot-glue` and call it `hotglue`.\n\nThe organs are files, so a program that would rather host them itself does not\nhave to vendor them:\n\n```js\nimport { compile, wasmPath } from '@ai-ecoverse/hot-glue';\n\nwasmPath('as');                                // …/dist/as.wasm, a WASI reactor\ncompile('(use prelude.hma)\\n(module)\\n').bin;  // source in, binary out\n```\n\nOne version pins the sources and the binaries together, which is the whole\npoint of shipping them as one thing. The release gate proves the relation\nrather than asserting it: it expands `as.hma` with the shipped toolchain,\nassembles it with the shipped assembler, and requires the bytes that come out\nto be the shipped assembler.\n\nOr work on the language itself:\n\n```sh\nnpm install\nnpm test                              # 21 suites, all under wasmtime\n```\n\nExpand a program to WAT with the stage-0 bootstrap and run it:\n\n```sh\nnpx tsx src/cli.ts examples/fizzbuzz.hma > /tmp/fizzbuzz.wat\nwasmtime /tmp/fizzbuzz.wat\n```\n\nOr close the loop — build the wasm compiler and never touch TypeScript again:\n\n```sh\nnpm run bootstrap                     # dist/hotglue/{expand,as,hotglue}.wasm\nnpm run -s compile -- examples/fizzbuzz.hma > /tmp/fizzbuzz.wasm\nwasmtime /tmp/fizzbuzz.wasm\n```\n\nThe browser is an expansion host too. `npm run build:web` writes\n`web/playground.html`: source → WAT → binary → execution, entirely inside one\ntab, no server and nobody phoned.\n\n## What it looks like\n\nMacros are the argument; the machine is the proof.\n\n```lisp\n(defmacro $divisible? (n d)\n  `(i32.eqz (i32.rem_u ,n ,d)))\n\n(defmacro $for (init test step body)\n  `(splice\n     ,init\n     (block $break\n       (loop $continue\n         (br_if $break (i32.eqz ,test))\n         ,body\n         ,step\n         (br $continue)))))\n```\n\n`$break` and `$continue` are macro-born labels; hygiene keeps them from\ncapturing yours. Beneath the surface, `src/clj.hma` teaches the reader an\naccent — brackets, `loop`/`recur`, threading, folding arithmetic whose bare\nnumbers wrap their own `i32.const`:\n\n```lisp\n(use clj.hma)\n\n(func (export \"steps\") (param $n i32) (result i32)\n  ($loop [$x (local.get $n) $count 0]\n    ($if (= (local.get $x) 1)\n         (local.get $count)\n         (recur ($if (zero? (rem (local.get $x) 2))\n                     (quot (local.get $x) 2)\n                     (+ (* 3 (local.get $x)) 1))\n                (inc (local.get $count))))))\n```\n\nBoth compile to the same honest WAT.\n\n## The spiral\n\nEvery rung is the acceptance test for the one below it.\n\n| | | |\n|---|---|---|\n| **Stage 0** | `src/bootstrap.ts` | 458 lines of TypeScript: reader, expander, lowerer. The only TypeScript that matters — and it is not in the package. |\n| **Stage 2** | `src/as.hma` | An assembler written in Hot Glue. WAT in on stdin, a binary module out on stdout. |\n| **Stage 3** | — | The assembler assembles its own source; the child assembles it again; the two binaries are byte-identical. |\n| **Stage 4** | `src/expand.hma` | The expander itself in wasm. `expand.wat` run on its own source prints the text it is running as. |\n| **Stage 6** | `src/expand-gc.hma` | The expander re-founded on Wasm GC — nodes as `struct` subtypes, matched by `br_on_cast`. |\n| **Stage 7** | — | Floating point, placed where it costs nothing: floats are *symbols* to the expanders, and only the assembler mints IEEE bits. |\n| **The flow** | `src/hotglue.hma` | The compiler as a wasm binary, driving expander and assembler as imported modules over a four-verb byte protocol. |\n\n`src/prelude.hma` is the macro library that makes WAT bearable at scale;\n`src/reel.hma` expands a declarative film into a wasm module.\n\n## Libraries, under their own meter\n\nModule fragments in the Clojure accent, composed into a `(module …)` with\n`(use …)`, and proven the house way — by the suite that measures itself:\n\n- **`src/json-read.hma`** — a streaming JSON reader. A pull parser over\n  windows of bytes the caller lends it: `$jr-fill` a chunk, ask `$jr-next`\n  for the next event, lend another when it answers *more*. Structural bytes\n  are never copied, the container stack is one bit per nesting level, and\n  only string and number tokens pass through a buffer the caller sizes —\n  a gigabyte of JSON parses in a few hundred bytes of state. Escapes\n  unwind, `\\uXXXX` mints UTF-8, surrogate pairs fuse; numbers keep their\n  raw spelling so floats need no f64 to survive the trip.\n- **`src/json-write.hma`** — the mirror: call the shape of the document and\n  minimal JSON accretes in the caller's buffer. Commas place themselves\n  from one \"has elements\" bit per level; `$jw-int` prints any i32,\n  INT_MIN included, by holding the magnitude negative.\n- **`src/glue-test.hma`** — clojure.test, poured hot. `(deftest …)`\n  re-defines itself after every use, carrying the accumulated roster in\n  its own macro body, so `(run-tests)` expands to the whole suite before\n  the first byte of wasm exists. `(is-fail …)` forgives exactly one\n  failure, which is how the framework's failure paths test themselves.\n- **`src/cov.hma`** + **`src/cov-clj.hma`** — coverage as macros. `(hit)`\n  stamps a bitmap byte and re-defines itself to stamp the next: the probe\n  counter lives in the macro table, not in any runtime cell. `cov-clj`\n  re-defines the accent's branching macros so every arm pays a probe;\n  raw WAT `(if …)` stays below the meter, which is where the reporter\n  itself must stand.\n- **`src/glue-alloc.hma`** — the memory map, derived instead of\n  declared: `(take name size)` claims the next band and defines\n  `(name)` as its folded base. The allocator is a self-re-defining\n  macro — it lives in the macro table and is gone before the module\n  exists.\n- **`src/canary.hma`** — sentinels that die out loud. `(defcanary\n  addr)` posts a tripwire at a border; `(canaries-check)` traps the\n  program the moment one has changed. Silent corruption becomes a\n  crash with a location.\n\nEvery base address lives in **`src/glue-mem.hma`** and nowhere else —\nreader at 8192, writer at 8448, framework at 8704, coverage bitmap at\n16384. A host with its own memory map (say, a string pool that runs\npast 8192) ships its own copy of that one file: `(use …)` resolves\nnames against the program's directory before the toolchain's, so the\nhost's map loads first and the libraries follow it wherever it points.\n\nHow these fare against wasm modules from the wild — shared memories,\nZig bands, the i64 seam — is\n**[`docs/wilderness-memory.md`](docs/wilderness-memory.md)**.\n\n`test/json-suite.hma` holds the whole argument to 100%: every assertion\nand every probe, or FAIL. It passes three times over — expanded by stage\n0, assembled by `as.hma`'s own binary, and compiled by the wasm compiler\nwith no TypeScript in the room. The verdict needs no particular runner:\nwasmtime and `node:wasi` print the same transcript.\n\n## The binary wilderness\n\nA module boundary is a module boundary regardless of what civilization lies\nbehind it. Hot Glue's civility compiles away before the border is reached.\n\n- **`examples/interop.hma`** — three languages on one stack: the message in Hot\n  Glue's memory, CRC-32 from C, MurmurHash3's finalizer from Rust.\n- **`examples/mandelzoom.hma`** — the Lisp as an ffmpeg video source, twice\n  over: a self-describing Y4M pipe, and `examples/native/frei0r_hotglue.c`, a\n  frei0r plugin that hosts the assembled module through the wasmtime C API.\n- **`examples/gpt.hma`** — a transformer inference engine, the whole of one, in\n  395 lines of the Clojure accent. Byte-level vocabulary, RMSNorm, rotary\n  embeddings, ReLU² MLP. `$exp` does its `2^k` step as a single\n  `f32.reinterpret_i32` of a shifted exponent field: the float format itself,\n  asked politely, is an exponentiator.\n- **`examples/film.hma`** — a film is a program. `scripts/projector.mjs` is a\n  lamp that has never read a film; it learns what to load by asking\n  `WebAssembly.Module.imports`. Six languages appear in the credits — Lisp,\n  Perl, WGSL, C, Rust, JavaScript — and the only one that ever leaves a sandbox\n  is the glue, which owns no hot path to leave with. The picture no longer\n  needs a browser either: `GPU_WASI=1` dispatches `examples/mandel.wgsl` as a\n  `wasi:webgpu` component instead of a Chromium tab, and the two renderers\n  disagree on 0.04% of bytes — boundary pixels where two software Vulkans part\n  company by one escape iteration.\n- **`examples/braid.hma`** — three civilizations, one linear memory, on\n  purpose: two Zig modules banded by `--global-base` and `--stack`, a\n  Hot Glue supervisor whose bands are `(take …)`n not pinned, canaries\n  on every border, and an explicit-typed adapter module for the u64\n  import — `wasm-merge` fuses the lot into one module with one memory,\n  the overlay some platforms force, done structurally instead of\n  luckily. `npm run build:braid`, then `wasmtime dist/braid.wasm`. The\n  doctrine is [`docs/wilderness-memory.md`](docs/wilderness-memory.md).\n- **`examples/perl-driver.hma`** — a supervisor with no memory of its own,\n  importing zeroperl's and re-exporting it, so Perl 5 runs under plain wasmtime.\n- **`tools/emscripten-gates/`** — the doctrine for giants that ship only as\n  Emscripten builds: read the JS glue as text, classify every minified gate by\n  what its body does, then serve the same gates from a host with no JavaScript\n  in it. Executed rather than theorised — ffmpeg-core boots and prints its full\n  `-version` banner with none of its own JavaScript ever running.\n\nThe full argument, stage by stage, is **[`docs/wasm-macros.md`](docs/wasm-macros.md)** — the\ndesign document that came first and was kept honest afterwards.\n\n## Things you build yourself\n\nFour artifacts are described here by recipe rather than carried as commits. The\ntests that need them skip cleanly when they are absent, so nothing below is\nrequired to work on the language.\n\n| Artifact | Build it with | Wanted by |\n|---|---|---|\n| `examples/native/ffmpeg.wasm` | `npm run build:ffmpeg` (wasi-sdk 25; ffmpeg n5.1.6 with x264) | the film's cut, `test/projector.test.ts` |\n| `examples/native/espeak.wasm` | `npm run build:espeak` (wasi-sdk; espeak-ng 1.51) | `SPEAK_WASI=1`, the pure-wasm voice |\n| `examples/oyster.npt` | `npm run train:oyster` (CPU PyTorch, ~820k params) | `test/gpt.test.ts`, the playground's prompt box |\n| `web/playground.html` | `npm run build:web` | the browser as expansion host |\n| `dist/braid.wasm` | `npm run build:braid` (zig; binaryen's wasm-merge) | `test/braid.test.ts`, the overlay done on purpose |\n| `tools/mandel-webgpu/wasi-gfx-runtime/` | `npm run build:webgpu` (clones and patches wasi-gfx-runtime; needs cargo and wasm-tools) | `GPU_WASI=1`, the browserless GPU path in `test/projector.test.ts` |\n\nKokoro's weights arrive with `npm run fetch:kokoro`. The six patches under\n`patches/tract/` teach the pure-Rust ONNX runtime what Kokoro's fp32 export\ndemands; they are upstream-shaped and apply with `git am`.\n\n## Requirements\n\n- **Node 20+** and **npm** — the bootstrap, the tests, the lamps.\n- **[wasmtime](https://wasmtime.dev)** — every rung above stage 0 is proven by\n  running it. Without wasmtime the suite still collects, but the interesting\n  tests skip.\n- Optional: **clang** and **rustc** with wasm targets (`npm run build:native`),\n  **Python 3** with PyTorch (`npm run train:oyster`), **wasm-tools** for the\n  component work (`scripts/make-envelope.mjs`, `test/envelope.test.ts`), a full\n  Chromium for the playground and WebGPU tests (Playwright's stripped headless\n  has no `navigator.gpu` — ask for the full build).\n\n## Releases\n\nPublished to npm as\n[`@ai-ecoverse/hot-glue`](https://www.npmjs.com/package/@ai-ecoverse/hot-glue).\nNobody types a version number: when `main` moves, `semantic-release` reads the\nnext one off the commit log, and `.github/workflows/release.yml` runs the gate,\npublishes the tarball, tags the commit and writes the GitHub release.\n\nThe gate is `scripts/verify.sh`, and CI runs the same script on every branch —\nthe same script, not a second copy of its steps, so a green pull request means a\ngreen release. It builds, runs the suite, then packs the tarball, installs it\nsomewhere else entirely, and uses it: `main` resolves, the bin runs without tsx,\nand a piped `(use prelude.hma)` finds the prelude with no checkout to find it in.\nThat last part is what the suite cannot see, because the suite runs against\n`src/`. Run it yourself with `bash scripts/verify.sh`.\n\nWhich makes the subject line load-bearing.\n\n| Subject line | Bump | |\n|---|---|---|\n| `fix: …` | patch | 0.1.0 → 0.1.1 |\n| `feat: …` | minor | 0.1.0 → 0.2.0 |\n| any commit with a `BREAKING CHANGE:` footer | major | 0.1.0 → 1.0.0 |\n| anything else | none | — |\n\nProse is still welcome. It moves to the body, under a conventional subject.\n\nNo npm token is stored anywhere. The workflow asks GitHub for an OIDC token and\nnpm trusts *the repository and the workflow file* rather than a secret somebody\nhas to rotate; the tarball gets a provenance attestation on the way past. The\none-time setup is on npmjs.com, under the package's **Trusted publisher**\nsettings: GitHub Actions, `ai-ecoverse/hot-glue`, workflow `release.yml`.\n\n0.1.0 went out by hand, because npm has no settings page for a package that does\nnot exist yet and therefore nowhere to name a trusted publisher before the first\npublish ([npm/cli#8544](https://github.com/npm/cli/issues/8544)). It is the only\nrelease without a provenance attestation. Everything from 0.1.1 on is the\nworkflow's.\n\nThe published tarball is `dist/`: the compiled stage-0 bootstrap, and the `.hma`\nsources beside it, where `(use prelude.hma)` looks for them. Everything else —\nthe tests, the examples, the film, the recipes below — stays here in the\nrepository.\n\n## Where this came from\n\nHot Glue was explored inside\n[trieloff/allegorithm](https://github.com/trieloff/allegorithm), on the\n`claude/wasm-macro-design-tszl1h` branch, and carved out here with its history\nintact — twenty-six commits, beginning as *nacre* and renamed partway through.\n`git log --follow src/bootstrap.ts` still reaches «Nacre stage 0», across both\nthe rename and the flattening into this repository.\n\nNacre survives where it always belonged: in the oyster, in the pearl, and in\nperlmutt's mother tongue.\n\nThe exploration is still running up there, so the carve is a script rather than\nan afternoon. `tools/upstream-sync/` holds the whole transform — the path\ninclude-set, the content-rewrite rules, and the upstream sha tracked so far:\n\n```sh\ntools/upstream-sync/sync.sh --check     # has upstream moved? (exit 3 = yes)\ntools/upstream-sync/sync.sh --verify    # rebuild this tree from upstream, diff\ntools/upstream-sync/sync.sh             # port what's new onto a branch\n```\n\n`--verify` is the load-bearing one: it re-derives every carried file from\nupstream and compares byte for byte. That the transform is *reproducible*, not\nmerely done, is what lets new upstream commits apply as ordinary patches — they\narrive already spelling `src/` where upstream said `src/hotglue/`.\n\n## License\n\nApache-2.0. See [LICENSE](LICENSE).\n","readmeFilename":"README.md"}