Each gpu-worker.lsp now listens on both wire-TCP (existing :8320) and
HTTP/1.1+CORS (new :8321), sharing one handle-request dispatcher. Lets
a tab on https://lumbda.com/playground/ POST to its own machine via
http://localhost:8321/ — browsers permit localhost from HTTPS origins
without TLS, so no proxy, no cert, no fox-owned infra required for the
decentralized run-your-own-bend story.
main() forks at startup: child runs http-run-loop on :8321, parent
keeps existing run-loop on :8320. Adding a new op-head to handle-request
exposes it over both transports automatically. Binary modes
(BSHK/BCGB/BSCP/BSRT/BSB3) stay wire-only — they exist for native
callers who already cache the binary locally; browser callers send
S-expression recipes the worker dispatches the same way.
Two latent defects fixed to make CPU-only and Python-tier hosts work:
- vram-used-mib now file-exists? guards /usr/bin/nvidia-smi. Python
tier's spawn-process-stdio raises FileNotFoundError on missing
binary, not returning #f as the prior code expected, which crashed
every worker on a CPU-only laptop.
- fork-self return discriminated via (number? pid) not (eq? pid 0).
Python tier's (eq? 0 #f) returns #t because == conflates int 0
with bool False; pre-existing run-loop has the same risk but
C/asm tier (identity eq?) masks it for the production case.
Phase 2 (server-side factory ops: compile uploaded .lsp recipes into
.bin before bending — the foxhop champion-circuit workflow) deferred
until authentication lands; today a worker on the public internet
would let any caller occupy our GPU.
Operational Caddy + DNS proposals in plans/bend-http-deploy.md cover
the personal-remote-access endpoint chain (proxy.unturf.com edge →
ai.foxhop.net Caddy → 3090-ai:8321) gated by trusted-IP allowlist —
applied separately.
Also codifies the playground "CSS Grid only, never flexbox" rule in
CLAUDE.md: all www/ and wasm/ stylesheets are already grid-only;
documenting the invariant so future edits don't drift.
Tests: smoke-bend-http.sh — (ping)→(ok pong), unknown-op fallback,
OPTIONS CORS preflight — all PASS. Wire path unchanged, verified
round-trip via 8-digit-prefix framing.
gpu-worker.lsp gains a cuda-sim-ops-bin op handler that spawns
demo_ops from www.foxhop.net/ecdsa/cuda via spawn-process-stdio,
drains stdout, & parses our (cuda-sim-result ...) portal back.
Each call now emits two log lines:
;;; bend RECV cuda-sim-ops-bin ops=PATH n-batches=N t-ms=...
;;; bend DONE cuda-sim-ops-bin n-batches=N wall-ms=W cpu-ms=C gpu-ms=G mismatches=0 gpu/cpu=R
so we can tell how fast bend jobs run on CPU vs GPU per call.
CLAUDE.md & www/index.html mention this integration is now live
end-to-end across our fleet.
CLAUDE.md rewritten to avoid the verb "to be" and to prefer "a"/"our"
over "the" when a thing counts as one of many or as shared. Same rule
applied to www/index.html (tagline now "feedback as a primitive", body
prose cleaned of is/are/be, table header now "What a tier buys",
section heads trimmed of definite articles). Monospace body stays,
ChunkFive titles stay.
Whitepaper now ships in two formats:
* Makefile target `make whitepaper-html` runs rst2html5 with
embedded minimal.css + responsive.css (docutils bundled), then
injects the same uncloseai.js module script that the homepage
carries, and stamps a meaningful <title>. 180 KB self-contained.
* PDF build target renamed to `make whitepaper-pdf`;
`make whitepaper` now builds both.
www/lumbda-whitepaper.html symlinks to the generated HTML (same
pattern as the PDF symlink). .gitlab-ci.yml resolves both symlinks to
real files before rsync so the proxy gets byte-identical copies.
Homepage now exposes both formats side-by-side via two .cta buttons
and the footer lists HTML + PDF.
Historical internal name "uncommonlisp" retired in favor of the
public name "lumbda" ahead of lumbda.com going live. Scope of
this commit:
Source files renamed:
uncommonlisp.py -> lumbda.py
asm/uncommonlisp.s -> asm/lumbda.s
c/uncommonlisp.h -> c/lumbda.h
whitepaper/uncommonlisp-whitepaper -> whitepaper/lumbda-whitepaper (.rst + .pdf)
Binaries renamed (tracked ones; c/ was always gitignored):
asm/uncommonlisp, asm/uncommonlisp-gc, asm/uncommonlisp.o,
asm/uncommonlisp-gc.o -> asm/lumbda(-gc)(.o)
c/.gitignore -> ignores lumbda
Internal string updates (sed pass ordered longest-first):
asm/uncommonlisp -> asm/lumbda
c/uncommonlisp -> c/lumbda
uncommonlisp.py -> lumbda.py
UNCOMMONLISP_BIN -> LUMBDA_BIN (asm/test.sh env var)
"uncommonlisp> " -> "lumbda> " (asm REPL prompt baked into binary)
UNCOMMONLISP -> LUMBDA (macros, comments)
uncommonlisp -> lumbda (prose)
Binary portal magic updated:
"ULPORTAL" -> "LUMBDAB1" # "Lumbda Binary v1"
Old portal files are not backward-compatible — this is a deliberate
break since it's the rename moment. S-expression portals already
carry their own ";; lumbda-portal v1" header and remain cleanly
versioned.
WHITEPAPER.pdf / WHITEPAPER.rst symlinks repointed to the renamed
files. Makefile's whitepaper target targets lumbda-whitepaper.pdf.
Not changed (intentional, separate phases):
- Filesystem directory /home/fox/git/uncommonlisp itself
(fox renames locally and the gitlab repo URL in a follow-up)
- tests.py hardcoded cwd=/home/fox/git/uncommonlisp
(matches the current on-disk location; will flip when the
directory rename ships)
- Git history (immutable; old commits still say uncommonlisp,
which is correct — that's what they were)
Verified:
137 asm no-GC + 137 asm GC + 571 Python + 83 C + 189 shared
functional tests all pass under the new names.
bench-gc-http (2000 req): all 4 cells behave as expected
(cells 1/2 flat, 3 leaks, 4 bounded at 1 chunk).
Python REPL, C REPL, asm REPL all start cleanly.
Language gets a proper name. Tagline per fox:
Lumbda — a just-in-time lambda language. Fast from first
principles, workloads migratable across basic UNIX systems.
Phase 1 scope: prose mentions of the language in the whitepaper,
README, and CLAUDE.md. File paths, binary names, and the repo
directory still use the historical "uncommonlisp" identifier —
those are Phase 2 (needs GitLab coordination + build-path edits).
- Whitepaper title "Feedback Is All You Need" → "Lumbda", with
the prior title preserved as a subtitle thread. New header
linkblock lists lumbda.com first, then uncloseai.com and
permacomputer.com.
- README.md opens with the tagline, points at lumbda.com.
- CLAUDE.md banner clarifies Lumbda-the-language vs the historical
repo/binary names.
- ~25 prose mentions of "uncommonlisp" in the paper are now
"Lumbda"; file-path refs (python3 uncommonlisp.py, ./c/uncommonlisp,
uncommonlisp.py, asm/uncommonlisp.s) unchanged.
- Benchmark methodology table widened slightly to fit the new
6-char label.
No behavior change, no benchmarks rerun, 975 tests still pass.
Other agents share this machine. An OOM crash takes their state
down too, not just mine. The earlier "trap + pgrep verify" pattern
depended on me not forgetting; two crashes proved that's not enough.
Adds a mandatory `ulimit -v 524288` (512 MB virt) to the pattern
alongside the existing timeout + trap + verify. The kernel kills
any rogue process at the cap, so even if all three earlier layers
fail simultaneously, shared RAM is untouched.
Verified: an asm process in a runaway (cons n ...) loop SIGKILL'd
by the kernel within ~1 second when capped at 512 MB, before
timeout 5 fired.
Also noted:
- ulimit only affects the current shell + children, so it cannot
degrade other agents.
- Use `pkill -u "$USER"` explicitly — don't pkill foreign processes.
- Prefer foreground runs with timeout over backgrounding when
feasible; the .lsp can exit on its own via *max-requests*.
Second crash on 2026-04-17 proved the earlier "Asm memory discipline"
section was aspirational. Rules were documented, blackops kept
spawning backgrounded asm servers for quick RSS checks during the
heap-snapshot and RPC work, and one escaped again.
This revision makes the discipline procedural:
- Wrap EVERY backgrounded asm spawn with `timeout N`, even for a
"quick test" — the mental overhead is zero; the consequence of
forgetting is a crashed machine.
- Trap EXIT/INT/TERM at the top of every block that backgrounds
anything, not just benchmark scripts.
- MANDATORY pgrep verification at the end of each block before
moving on. If the verification returns output, pkill and
investigate — do not proceed.
- The discipline applies to Python + C servers too (they block
ports even without the OOM risk).
Documented both crashes explicitly so future sessions know this
rule has teeth.
Prevent recurrence of 2026-04-16 incident where a leaked asm HTTP
server grew to 19.3 GB RSS and crashed the machine.
examples/http-server.lsp:
- Adds *max-requests* = 50000 hard ceiling. Server self-terminates
before unbounded heap growth reaches dangerous levels.
- Loop tracks request count, exits cleanly + closes server socket.
tests/web-benchmark.sh:
- SPAWNED_PIDS array tracks every background process.
- EXIT/INT/TERM trap kills them all (SIGTERM then SIGKILL).
- stop_server does SIGTERM with 500ms grace period then SIGKILL.
- Final straggler check via pgrep narrows to actual HTTP server
processes (not shell/tmux with "uncommonlisp" in the name).
- pkill -9 fallback as belt-and-suspenders.
CLAUDE.md:
- New "Asm memory discipline" section documents the bump allocator
leak behavior and the required operational discipline.
- Test counts updated (571 py + 83 c + 132 asm + 189 shared = 975).
Full continuations: FullCont captures frames/stack/env with deep copy.
VM trampoline via setjmp/longjmp. Multi-shot safe via deep_copy_env.
Portal (new c/portal.c): serialize env + continuation to JSON,
resume on another machine. portal-checkpoint! triggers mid-VM save.
83/83 C unit tests + 181/181 functional tests pass.
Scanner renamed to unmoad (~/git/unmoad.com/). Run before every commit.
Machine learning agents propagate MOAD-0001 by default — the scanner
catches what our weights miss.
4 architecture diagrams (Graphviz DOT → PNG):
python-architecture.dot — bytecode VM + continuations + portal
c-architecture.dot — tree-walker + VM + JIT tiers
asm-architecture.dot — syscalls-only, 13KB binary
jit-pipeline.dot — AST → x86_64 machine code flow
docs/README.md — full architecture docs with embedded diagrams
and performance summary across all implementations.
Makefile: add asm-repl, docs target, clean-docs. Header comments
document all targets and test suites.
CLAUDE.md: add "A diagram is worth 10,000 words" (russell@unturf.com),
implementation table, test suite inventory.
Assembly is 2.5-4x faster than C interpreter on recursive workloads.
JIT remains 33x faster than hand-written assembly.