Add a general Janet interop bridge and an nREPL implemented on top of it.
Interop bridge (evaluator):
- A qualified symbol whose namespace is `janet` or `janet.<module>` resolves
against Janet's environment: `janet/<name>` -> root binding (janet/slurp),
`janet.<module>/<name>` -> module binding (janet.net/server, janet.os/clock).
The explicit `janet` segment marks every crossing into host code (where
Clojure semantics, e.g. collection representation, no longer hold). This makes
the whole Janet stdlib — networking included — reachable from Clojure.
jolt.nrepl (Clojure, src/jolt/jolt/nrepl.clj):
- bencode codec (encode + streaming decode), ported from nrepl.bencode.
- server: accept loop via janet.net/accept + janet.ev/call (Janet's built-in
handler arity-checks Jolt closures, so we drive accept ourselves); ops clone/
describe/eval/load-file/close/ls-sessions/interrupt/eldoc following
babashka.nrepl response shapes. eval captures *out* by rebinding Janet's :out,
reports ns, streams out, and isolates the eval namespace (current-ns is global
ctx state) restoring it afterward. Vars are rendered as #'ns/name (pr-str
loops on a var's cyclic ns refs).
- client: connect / request / client-eval / client-clone / client-close.
CLI: `jolt nrepl [port]` starts the server and writes .nrepl-port; the Clojure
source is embedded at build time so the binary is self-contained from any cwd.
Tests: test/spec/nrepl-spec.janet (bencode), test/integration/nrepl-test.janet
(server+client over a real TCP/bencode wire, server in a subprocess).