This document states what you can depend on across alcove/Adder releases, what is still moving, and how changes are communicated. It is the contract behind "can I bet mission-critical work on this?".
alcove follows Semantic Versioning with an explicit
pre-1.0 caveat: while the version is 0.x, the language is still
converging, so a minor bump (0.2 → 0.3) may include a breaking change to a
surface marked unstable below. Every such change is called out under
Changed/Breaking in CHANGELOG.md. Patch bumps
(0.2.0 → 0.2.1) are always backward-compatible.
At 1.0 the stable surface below is frozen under normal semver (no breaking changes without a major bump), and the dialect surface (Adder syntax) is finalized.
The running version is ALCOVE_VERSION in alcove.h; tools/release.sh reads
it for artifact names and tags.
- The core evaluation model — lexical scope, the special forms
(
def/fn/if/let/do/and/or/cond/case/while/…), proper tail calls, and macro expansion semantics. - The error-as-value model — errors are first-class values that propagate
through normal calls;
error?/error-message/tryare the safe operations on a possibly-error value. (Pinned with conformance asserts; see the semantics appendix ofdocs/alcove-language.md.) - The numeric tower — fixnums, exact rationals, bounded decimals, and floats, with the documented strict contagion rules and integer-overflow-is-an- error policy.
- Core builtins and their contracts — arithmetic/comparison, list/vector/
string/blob ops, the sequence protocol,
map/filter/reduce, etc. - Truthiness —
nilis falsey, and so are the empty/zero values:0,0.0, the empty string"", the empty list, and the empty vector. Every non-empty, non-zero value is truthy. - The RESP keyspace commands and the on-disk dump format version (migrations are handled with explicit format-version bumps).
- Observability: error codes and logging —
error-code(the class symbols it returns),log!/log-debug/log-info/log-warn/log-error, andlog-level/set-log-level. The error-class symbols and the logfmt field set (ts/level/msg/ your kv pairs) are stable; logging is always compiled in. (Pinned with conformance asserts intest.alc.)
-
Metrics (
counter!/gauge!/metric/metricsand the RESP auto-countersresp.connections/.commands/.errors) — opt-in at compile time (-DALCOVE_METRICS,make alcove-with-metrics); absent from the default build. The builtin names are settled but the registry shape, capacity, and the exact auto-instrumented counter set may still change. -
--threads N(multi-reactor RESP) — EXPERIMENTAL. See the concurrency contract indocs/multithreading.md. Single-reactor (N=1) is stable. -
The C embedding API/ABI — usable, but not yet versioned for ABI compatibility (see
examples/embed/). Native modules must be built against the same source revision. -
JIT internals and
:typehints — the behavior is stable (results match the VM byte-for-byte, enforced bymake jit-fuzz); which shapes JIT and the hint syntax may evolve. -
Adder surface syntax — converging toward a 1.0 freeze; recent additions (infix, chained-call sugar) may still be refined.
-
The programmable-REPL hooks (
lib/repl.adr,*prompt-*,bind-key).
A feature slated for removal is first deprecated: it keeps working, is
marked Deprecated in the CHANGELOG, and (where practical) emits a one-time
notice. It is removed no sooner than the next minor release after the one
that deprecated it, and the removal is listed under Breaking. Aliases kept
for compatibility (e.g. band/bit-and) are documented as such.
Trust rests on differential gates that run in CI on every push:
- AST ≡ VM —
tools/equiv_sweep.alcplus the generativetools/eval_fuzz.py(random programs, byte-identical, under ASan). - VM ≡ JIT —
make jit-fuzz(byte-identical machine code vs bytecode). - Hot path under ASan+UBSan — the full
test.alc/test.adrsuite. - ThreadSanitizer on the concurrency primitive, libFuzzer on the reader / transpiler / msgpack / JSON, and a coverage signal.
See CHANGELOG.md for the per-release record.