Six-step proof that https://wedgewack.org/ursa.lisp.txt runs in lumbda
with only the documented minimal annotations — no semantic rewrites,
no algorithm changes. New make target `prove-ursa-runs` wires it.
Steps:
1. Fetch /robots.txt; abort if it disallows /ursa.lisp.txt.
2. Fetch the source (209 lines, sha256 recorded in output).
3. Apply the four character-level substitutions sed'd from the
documented annotations:
(loop → (cl-loop (call form only — clause keyword stays)
(when → (cl-when (call form only)
(random → (random-int
&key → &optional
Prepend (load "cl-compat.lsp").
4. Verify that examples/ursa.lisp.txt's defuns are exactly Zoë's
defuns minus {rho, factor, digits} — the three that depend on
CL features (adjustable arrays, defgeneric/defmethod) out of
ticket 0004's scope. No extra edits anywhere.
5. Run tests/ursa.lsp (which uses the same function bodies Zoë
wrote) on Python + C + asm-full; expect 28/28 passing on each.
6. Build a "Zoë's live source + 10-line stubs" file — no-op
defgeneric/defmethod, 'unshimmed returns for make-array / sbit /
vector-push-extend / vector-pop / fill-pointer, identity coerce,
naive integer-length — and spot-check seven answers on asm-full:
expt-mod 3 7 100 = 87
primep 97 = 97
primep 100 = #f
mersenne 7 = 127
ll-primep 13 = #t
ll-primep 11 = #f
repunit-value 5 = 31
Any missing line fails the proof.
Sed-subset nuance: `(loop ` / `(when ` with an open-paren prefix
matches the call-form usage we want to rewrite. Bare `when` that
appears as a cl-loop clause keyword (no open paren before it) is
left unchanged — that's the macro's own reserved word. Same for
loop.
Usage:
make prove-ursa-runs (network required — live fetch + spot-check)
make zoe-favorites-test (offline; uses the committed examples/)