Commit graph

23 commits

Author SHA1 Message Date
3d6d5d1010
playground: free-form code option + encrypted vault, single-scroll layout
Free-form radio adds a 5th demo slot. When selected, a vault bar appears
under the controls: enter a password, "unlock" derives a per-device
vault and decrypts (or creates fresh). Edits in the editor auto-save
350ms after typing stops. Reload + same password restores the code.

Same Web Crypto stack as /repl/ (PBKDF2 + AES-GCM, vault id =
SHA-256(password || device-salt)).

Layout: one shared vertical scroller — code pane and output pane both
grow with content, the body scrolls. No more independent in-pane
scrollers fighting the page.

Home page split into "Demo" and "REPL" sections with their own CTAs.
2026-06-14 12:56:25 -04:00
d8ffab5ea6
repl: /repl/ page with encrypted multi-tab sessions
Interactive REPL at lumbda.com/repl with:
  - multi-tab sessions (click + to add, × to close, double-click to rename)
  - per-tab tier selector (python/c/asm/all-three race)
  - persistent transcripts encrypted in localStorage via Web Crypto
    (PBKDF2 + AES-GCM, vault id = SHA-256(password || device-salt) —
    same pattern as unsandbox's vault-encryption-design.md, native
    crypto.subtle API instead of CryptoJS)
  - ephemeral mode (skip vault, transcripts vanish on reload)
  - one worker per (tab × tier) — state persists across evals in a tab
  - reboot tier button (terminate this tab's worker, fresh state next eval)
  - cancel button (kills the running worker in active tab)

Home page now links to both /playground/ and /repl/.

Tier state itself does NOT persist across reloads — the transcript does,
but defines/set!/hash-tables vanish with the worker. Portal save/resume
in WAT (deferred) will let a tier session survive close+reopen.
2026-06-14 12:50:35 -04:00
9c25d46e13
home page: link to the WebAssembly playground
Adds a "Try it in your browser" section at the bottom of www/index.html
pointing to /playground/, plus a footer link for redundancy. Lands the
three-tier WASM SPA committed in 346b873 as a discoverable surface on
lumbda.com.
2026-06-14 11:49:40 -04:00
718a93ff2d
www: strip private www.foxhop.net/ecdsa.html links; promote v3 in index
foxhop CLAUDE.md update: www.foxhop.net is private (book.foxhop.net
source + research artifacts). URLs like https://www.foxhop.net/ecdsa.html
do not exist & must not appear in public posts or external links.
Public-facing copy of ECDSA work belongs on foxhop.net wiki (remarkbox
RST pages), not as static HTML under www.foxhop.net/.

Stripped two external links:

  bend.html  — "secp256k1 point-addition challenge work at
               foxhop.net/ecdsa" → "(research artifact, internal repo)"
  index.html — same pattern → "internal ECDSA research"

Also brought index.html catalog highlight in sync with Day-3:
  was: secp256k1 batched point-mul (6.5 Gkeys/s on a 4090, surveyed)
  now: 13.6 Mkeys/s on a 3090, ~309x coincurve CPU

The 4090 projection moves out of the lead because we now have a
measured number on our actual hardware.
2026-06-05 18:20:23 -04:00
a17c114263
bend.html: dedicated page + 27-form catalog with published speedups
Splits a dense bend section out of index.html (now 6 lines: tagline,
example, three highlights, CTA) into a new public page at
lumbda.com/bend.html carrying:

  * full wire protocol (S-exp + binary BSHK modes)
  * tier-choice table (Py / C / asm × S-exp / binary)
  * real workload table from foxhop ecdsafail measurements
  * 2 live forms + 7 surveyed forms (Wave 1: secp256k1 batch-mul,
    CGBN bignum, Pollard rho, Stim-on-GPU stabilizer, Bernstein-Yang
    inverse, NTT, CUB sort/scan)
  * 20 surveyed forms (Wave 2) sorted by speedup descending —
    minhash 600-1000x, cuckoo filter 378x, ChaCha20 400 GB/s,
    SAT 93x, Dilithium PQ 57.7x, BLAKE3 tree, cuFFT batched,
    Bloom filter modern, GEMM FP8, hash-join 1.8T tuples/s on
    1024xA100, cuGraph 38B TEPS, TRUST triangle 1T TEPS, nvCOMP 2.2x
  * skipped section listing forms that don't pass the threshold,
    so the catalog stays honest about what GPU dominates vs not
  * cited canonical references for every entry

CATALOG.md mirrors the same data — single source of truth in repo;
bend.html renders the same metadata for public reading.

Build order remains: A cuda-secp256k1-batched-mul, D Clifford
stabilizer, B CGBN bignum.
2026-06-05 13:02:31 -04:00
78ff89fb8b
bend: cuda-sim-ops-bin handler + per-call CPU/GPU telemetry
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.
2026-06-05 10:18:11 -04:00
01ea93f68f
binary wire mode: 12x faster than host hashlib at 1M inputs
The S-expression wire format was the bottleneck at huge payload sizes
-- 23.8 s end-to-end for 1M x 16 B inputs on the Python tier, while
the actual CUDA kernel finishes the same workload in ~47 ms. The
hex-S-exp parser ate everything between.

New binary wire mode (magic 'BSHK' prefix; payload is the daemon's
binary portal format verbatim) bypasses S-expression parsing entirely.
Worker writes the blob to disk, calls daemon process-bin, reads result,
prepends 'BSHR' magic, replies.

Measured 3090-ai, daemon warm, localhost:

  workload      Py S-exp    Py binary   C S-exp    C binary
  100 x 16 B     3.43 ms     0.74 ms    0.40 ms    0.15 ms
  1k x 16 B     23.24 ms     0.76 ms    2.77 ms    0.22 ms
  10k x 16 B   218.82 ms     1.27 ms    CLIFF      0.88 ms
  100k x 16 B  2,219 ms     10.18 ms    CLIFF     10.35 ms
  1M x 16 B   23,811 ms    159    ms    CLIFF    157    ms

150x speedup at 1M inputs on Python tier. C tier S-exp CLIFFs
between 1k and 10k inputs (reader payload limit); binary mode
bypasses the CLIFF entirely. At 100k+ inputs both tiers converge
since file I/O + CUDA kernel dominates over wire framing.

Host comparison: hashlib.shake_256 over 1M tiny inputs takes ~2 s
on a single Python core. Bend via binary worker = 157 ms = 12x
faster than host. Bend now wins at huge workloads, not just heavy
ones.

Implementation:

  lumbda.py
    * tcp-send/tcp-recv switched to latin-1 (1:1 byte mapping)
      so binary payloads pass through cleanly. UTF-8 was mangling
      bytes with replacement chars.
    * write-binary-file / read-binary-file primitives.

  c/builtins.c
    * write-binary-file / read-binary-file matching Python tier.

  examples/cuda-fanout/wire.lsp
    * wire-send-raw / wire-recv-raw helpers that frame a raw
      payload string without S-expression serialization.

  examples/cuda-fanout/gpu-worker.lsp
    * handle-binary-shake: write portal blob, daemon process-bin,
      read result, wire-send 'BSHR' + bytes.
    * handle-one dispatches on first 4 bytes of payload: 'BSHK'
      goes to binary path, anything else stays S-exp.

  examples/cuda-fanout/bench_tiers.py
    * make_payload_binary builds the BSHK protocol payload.
    * --binary flag in CLI.

  www/index.html
    * full S-exp + binary comparison table.
    * 'bend now beats host hashlib at huge workloads' headline finding.
2026-06-05 09:40:45 -04:00
d69e8ed859
asm tier: delete-file + worker now fully functional; 3-tier bench
Three defects fixed today on the asm tier worker path:

1. Multi-line "..." docstrings crashed asm tier's scheme_read.
   wire.lsp, bend.lsp, gpu-worker.lsp had docstrings spanning
   several lines; replaced with ;; comments before each define.
   asm tier loads these cleanly now.

2. asm tier lacked delete-file. handle-cuda-shake-fanout called
   it to clean up temp portal files. Added bi_delete_file via
   SYS_UNLINK = 87 syscall (~20 LoC asm). BI_DELETEFILE constant
   slotted after sibling-agent's BI_STRTOSYM.

3. All Scheme files in examples/cuda-fanout/ now ASCII-only.
   Earlier em-dash / × / → / μ tripped asm tier's reader in
   subtle ways during file load. iconv pass + sed fixes.

Result: all three tiers complete the bench through their own
cliff. New 3-tier table:

  workload              Python      C tier      asm tier
  small (3 × 16 B)       1.27 ms    0.16 ms     0.21 ms
  small (100 × 16 B)     3.43 ms    0.40 ms     1.99 ms
  medium (1000)         23.24 ms    2.77 ms     CLIFF
  med (10k)            218.82 ms    CLIFF       CLIFF
  huge (50k)         1,099 ms       CLIFF       CLIFF
  huge (100k)        2,219 ms       CLIFF       CLIFF
  huge (1M)         23,811 ms       CLIFF       CLIFF

asm tier at 0.21 ms beats Python by 6× at smallest workload,
matches C at the bottom (~30% slower). asm cliffs at 1000;
C tier cliffs at 10k. Both cliffs are reader/buffer limits
inside the tier, not network or kernel. CUDA kernel itself
finishes 1M × 16B in ~47 ms — three orders of magnitude under
any tier's wire cost at huge scale.

bench_tiers.py made cliff-resilient: respawns worker on per-
workload failure & continues, so the full row prints for every
tier instead of bailing on first cliff.

www/index.html: full 3-column table + honest framing of when
each tier earns its slot.
2026-06-05 09:24:26 -04:00
e1fe20c5b9
wire.lsp: recv-exact O(n²) → O(n); bench reports linear Python scaling
wire.lsp's recv-exact previously accumulated received chunks via
`(string-append acc chunk)` in a loop — quadratic on payload size.
Replaced with a chunk-list accumulator + single `(apply string-append
…)` at the end. Lumbda's string-append knows total length up front
& allocates once.

Python tier now scales linearly across input counts (~22 µs per input):

  workload             Python      C tier
  small  (3 × 16 B)    1.25 ms    0.16 ms    8× C win
  small  (100 × 16 B)  3.39 ms    0.40 ms    8× C win
  medium (1000)        23.52 ms   2.60 ms    9× C win
  med    (10k)         220.15 ms  (cliff)
  huge   (50k)         1,100 ms   (cliff)
  huge   (100k)        2,225 ms   (cliff)
  huge   (1M)          23,811 ms  (cliff)

C tier cliffs somewhere between 1k & 10k inputs per call — its reader
hits a payload limit we still need to track down. CUDA kernel for
1M × 16B finishes in ~47 ms on this 3090, so at huge sizes the wire
cost dominates regardless of tier.

Web page updated with the linear-scaling table & honest framing: at
small inputs C wins by 9×; at huge inputs the right next move is a
binary wire mode parallel to the daemon's already-binary portal
format. Stalls are gone.
2026-06-05 08:55:43 -04:00
373c8ea0d3
bench + www: honest huge-workload numbers + wire bottleneck found
Added a write-to-string-shim.lsp for asm tier (which lacks the
native builtin); asm launch script pre-defines *argv* + loads the
shim so wire.lsp's wire-send finds a write-to-string definition.
Python/C tiers keep the native builtin — the shim is opt-in.

Bench extended with two huge workloads (100k × 16 B, 1M × 16 B).

Real numbers, 3090-ai, daemon warm, both ends localhost:

  workload              Python    C tier   C win
  small (3 × 16 B)       1.16 ms   0.14 ms   8.3×
  small (100 × 16 B)     3.39 ms   0.42 ms   8.1×
  medium (1000 × 16 B)  23.26 ms   2.67 ms   8.7×
  huge (100k × 16 B)    2,220 ms   STALL     n/a
  huge (1M × 16 B)     24,338 ms   STALL     n/a

THE FINDING: at huge sizes, the bottleneck is the S-expression
text wire format, not the CUDA kernel. shake256-fanout finishes
1M × 16B in ~47 ms; the Python worker takes 24 SECONDS end-to-end
because wire.lsp's recv-exact accumulates chunks via string-append
in a loop — O(n²) at multi-MB payload sizes. C tier fails outright.

The right fix is binary wire framing between client + worker,
parallel to the binary portal format the daemon + leaf already use.
That's a separate piece of work; today's Web page edit calls it out
honestly so visitors know when bend is the right tool.

asm tier worker hosting still has process-management quirks
(doesn't survive nohup detachment in this environment); bench
ships with --skip-asm by default in this run.
2026-06-05 08:50:36 -04:00
f24afcc5d9
bench + www: real numbers — C tier ~9× faster than Python as worker host
Wrote examples/cuda-fanout/bench_tiers.py — spawns a worker per
tier, fires N TCP round-trips at three workload sizes through the
warm daemon, reports median + p99.

Measured on 3090-ai, daemon warm:

  workload             Python   C tier   C win
  small  (3 × 16 B)    1.27 ms  0.14 ms  9.1×
  small  (100 × 16 B)  3.46 ms  0.41 ms  8.4×
  medium (1000 × 16 B) 23.51 ms 2.67 ms  8.8×

Ratio stays at ~9× across the grid — the per-byte cost of
Python's S-expression reader/printer compared to the C tier's
reader. Justifies the LUMBDA=c default landed in the previous
commit.

asm tier worker starts up & listens (after the launch script
predefines *argv* '()), but bench script saw malformed responses on
this run — likely a write-to-string format difference between asm
& Python/C reader. Leaving for follow-up; published numbers cover
the tiers that completed end-to-end.

www/index.html bend section gains the measured table under a new
'Tier choice for the worker host' subsection. Replaces the earlier
hand-wavy ~10× claim with the actual measured numbers.
2026-06-05 08:39:31 -04:00
14edb57cd4
make gpu-worker: default to C tier
C tier is ~10× faster than Python tier on wire orchestration & has
the same primitives shipped this session. Python tier still available
for development debugging via LUMBDA=python; asm via LUMBDA=asm.

Auto-builds the chosen tier (c-build or asm-build) before launching
so a fresh clone runs cleanly without 'make c-build && make gpu-worker'
two-step.

Web page Start-a-GPU-worker subsection updated to match.
2026-06-05 08:34:43 -04:00
f119f581a1
Makefile + www: make gpu-worker target & start-worker docs
Adds a one-shot target so any host with nvcc can stand up a bend
worker without remembering the launch incantation.

  make gpu-worker
    → make -C examples/cuda-fanout shake256-fanout
    → writes examples/cuda-fanout/launch.lsp (wire + worker + main)
    → cd examples/cuda-fanout
    → python3 -u ../../lumbda.py launch.lsp --port 9091

  make gpu-worker LUMBDA=c PORT=9001     # C tier host on port 9001
  make gpu-worker LUMBDA=asm             # asm tier host

Uses python3 -u so the worker's status lines ("gpu-worker:
ready …", "listening on port 9091") appear live; bypasses Python's
default stdout buffering that masked them during development.

www/index.html bend section gains a 'Start a GPU worker' subsection
with the same make targets so the website visitor doesn't need to
spelunk the repo to find them.

Also adds gpu-worker, gpu-worker-bin, gpu-worker-test to .PHONY.
2026-06-05 08:19:51 -04:00
9410816bdc
www: bend section on lumbda.com
New section between Portal and EML universality proof. Brief
explanation of the bend primitive + a worked code example showing:

  - tiny inputs stay local (cost below threshold)
  - heavy inputs ship to a GPU worker (cost above threshold)
  - one tier-portable (bend …) macro, with bend-call as the asm form

Mentions the measured 1.5–10× wins against host hashlib on the
SHAKE256 fan-out workload, calls out the ~100 MB break-even
threshold so visitors know when bend pays off.

Cites the cuda-fanout README + integration design for callers who
want the wire contract and per-tier hosting story.

License: AGPLv3, matching the rest of the site.
2026-06-05 08:16:56 -04:00
5566865815 logo: revert artwork to source orientation (was over-flipped)
Source PNG from the MPS lumbda-logos product is already an inverted λ
(hooks at top-left + bottom-right, V-body). My prior commit applied
vertical + horizontal flips on top of that, which undid the inversion
and produced a right-side-up calligraphic λ — the opposite of what
the artwork was drawn to express.

Regenerate both PNG variants (lumbda-logo.png black,
lumbda-logo-green.png #227842) directly from the source with no
flips. Only transform: alpha-from-brightness so anti-aliased edges
survive over any background.

Homepage img src picks up ?v=2 so any browser with the flipped
version in disk cache re-fetches. Logo size stays 3.33× the
wordmark font (10.66rem). PDF + HTML rebuilt — embed-images.py
base64-inlines the new PNG into the HTML automatically.
2026-04-19 17:42:14 -04:00
ecf0c89de2 www + whitepaper: adopt custom λ mark from MPS, green, 3× wordmark size
Fetched the lumbda-logos artwork from
media.unturf.com/c/fbd3d473-.../lumbda-logos (a MakePostSell product),
applied both flips (vertical + horizontal, = 180°) at bake time so the
PNG ships oriented correctly without any CSS transform dance, and
recolored non-background pixels to brand green (#227842) with alpha
derived from pixel brightness so anti-aliased edges stay smooth.

Two PNG variants ship under whitepaper/diagrams/:
  * lumbda-logo.png        dark ink for print contexts
  * lumbda-logo-green.png  #227842 for web

www/ carries symlinks to both.

Homepage (www/index.html): replaces the CSS-rendered λ with an
<img class="lambda-mark"> element sized 9.6rem — 3× the 3.2rem
wordmark font — stacked below "lumbda." on its own line.

Whitepaper (whitepaper/lumbda-whitepaper.rst): adds the logo as the
first figure above the permacomputer-logo, 24% width, centered.
Regenerated PDF + HTML; embed-images.py base64-inlines the new file
automatically so the HTML stays single-file.

CI (.gitlab-ci.yml): generalizes the symlink resolver from two
explicit `cp -L` calls into a `find www -type l` loop, so every
current and future symlinked asset deploys without per-file CI edits.
2026-04-19 17:32:43 -04:00
2fccdddf44 www: stack logo vertically — wordmark on top, λ mark beneath
λ in front was reading as a "Y" attached to the wordmark ("ylumbda.").
Move the mark under the wordmark as a standalone logo below the name.
Sitting alone, the flipped λ doesn't get recruited into the first
letter and reads as its own glyph — a lambda turned on its head.
2026-04-19 17:20:24 -04:00
26c6cca6da www: logo — distinct oversized flipped λ beside "lumbda.", green period
Previous design folded the flipped λ inside the wordmark as the "l".
That read as a cute substitution but didn't work as a brand mark.
Split them: the λ now stands on its own, rotated upside-down, 5rem
(larger than the 3.2rem wordmark), so it reads as a logo symbol
separate from the text.

Wordmark restores a proper lowercase "l" in "lumbda" — readable,
copy-pasteable, searchable. Trailing period picks up a new --green
design token (#2a8a3a light / #6fd68a dark) so the declarative stop
also reads as growth — matches the permacomputer ethos.

Layout: flex logo-row with baseline alignment and a small gap; the λ
hangs from the wordmark's cap-line for a balanced mark-and-wordmark
composition.
2026-04-19 17:12:51 -04:00
8a51e1fd7f www: logo becomes "lumbda." with a vertically-flipped λ for the l
Wordmark now renders λumbda. — flipped λ stands in for the "l",
visual pun on lambda (the primitive the language shells around),
trailing period as declarative closure. All-lowercase, accent-colored
period. aria-label="lumbda." keeps screen readers reading the name
correctly; the λ and the period both carry aria-hidden.
2026-04-19 17:05:05 -04:00
718f878f7d www: HTML whitepaper + prose rewrite avoiding "to be" and "the"
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.
2026-04-19 16:23:56 -04:00
af02e9b1c0 www: canonical slug /lumbda-whitepaper.pdf + embed uncloseai.js
Rename www/whitepaper.pdf → www/lumbda-whitepaper.pdf (symlink target
unchanged; slug now descriptive for search/citation). Update the CTA
and footer links in index.html, plus the .gitlab-ci.yml symlink-resolve
step. Companion Caddyfile redirect in proxy.unturf.com keeps old
/whitepaper.pdf links working via 301.

Add <script src="https://uncloseai.com/uncloseai.js" type="module"> to
<head>, matching www.unturf.com + timehexon.com pattern — brings the
permacomputer chat/AI integration to lumbda.com's front door.
2026-04-19 16:17:43 -04:00
af3e308a95 www: ChunkFive for logo/titles; normalize asm references to "GNU asm"
ChunkFive webfont (woff2 + woff, ~43 KB total) dropped into
www/fonts/chunkfive/; style.css adds @font-face with font-display:swap
and applies the family to header h1 (3.2rem logo) and main h2
(1.5rem section titles). Monospace body text unchanged. Font files
reused from www.unturf.com; SIL OFL.

index.html: "x86_64 assembly interpreter" and table-row labels
"Pure x86_64 assembly" / "Assembly + naive mark-sweep GC" now read
"GNU asm" — precise and consistent with how we talk about the tier
elsewhere.
2026-04-19 16:08:02 -04:00
e2a74832ef www/: static docroot for lumbda.com
Minimal, monospace, readable. Works as a drop-in docroot for
any static server (nginx, caddy, python -m http.server, etc.).
Light/dark mode via prefers-color-scheme. No JS, no fonts, no
third-party anything.

Files:
  www/index.html    landing page (tagline, get-it, four-tier
                    table, portal summary, EML proof blurb,
                    license, whitepaper CTA)
  www/style.css     ~150 lines, CSS vars for theming
  www/robots.txt    allow everything
  www/404.html      referenced by servers that support custom
                    error pages
  www/whitepaper.pdf -> ../whitepaper/lumbda-whitepaper.pdf
                    (symlink — one source of truth, rebuilds
                    via `make whitepaper` auto-propagate)

Smoke-tested with python3 -m http.server: 200 on /,
Content-Type: application/pdf for /whitepaper.pdf,
Content-Length matches the current 2.67 MB PDF,
/robots.txt serves, /nonexistent returns 404.

No new build step — docroot is pure static files the existing
whitepaper target already produces. A web server configured
with docroot=www/ and fallback 404.html has a working lumbda.com
today.
2026-04-19 11:21:56 -04:00