You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
v0.3.1 — 2026-08-13
Added
HTTP API authentication & TLS (integrations/euclid_api.py): opt-in EUCLID_API_KEY (or --api-key) requires Authorization: Bearer <key> on every POST (constant-time check, 401 otherwise, /health stays open for load balancers), and EUCLID_TLS_CERT / EUCLID_TLS_KEY (or --certfile / --keyfile) serve HTTPS directly. Setup and posture documented in docs/PRODUCTION.md → "Authentication & TLS".
Python 3.13 and 3.14 support: verified end-to-end (lint, mypy, full test suite) on CPython 3.13 and 3.14; CI matrix now runs on Python 3.10–3.14.
Stress & soak benchmark (benchmarks/euclid_bench.py): detects response mixing, KB pollution, and engine errors across periodic restarts; regression detector for the load+query atomicity and the periodic-restart policy.
Benchmark documentation: one detail page per benchmark plus a catalog of results and implementation choices (benchmarks/BENCHMARKS.md).
SWI-Prolog compatibility matrix: full suite passes on SWI-Prolog 8.4.2, 9.0.4, 9.2.9, and 10.0.2 (benchmarks/docs/06-swi-prolog-versions.md).
Performance
KB preload optimization: repeated loads of the same knowledge base skip re-parsing and re-asserting. Python-side parse+translate results are cached per KB source (_translate_cached), and the engine skips the workspace rebuild when the load carries the same kb_hash (reply skipped:true). A repeated identical 20 000-fact KB drops from ~196 ms to ~18 ms per load. assert/retract invalidate the fingerprint.
Fixed
Engine workspace sweep is SWI-Prolog 9.x-safe: clear_workspace/0 now retracts only the registered workspace predicates (workspace_predicate/1) instead of every dynamic predicate. On SWI-Prolog 9.x the broad sweep corrupted the autoloader (domain_error(file_type, prolog)); the registry fix is ~19% faster (513 vs ~429 req/s).
Periodic engine restart: now fires before the next load, never after a crossing request, so a relaunched engine always receives its workspace first.
Load+query atomicity gap: PrologServer.load_and_query holds the lock across both steps — a single atomic exchange; the workers=4 benchmark flips from FAIL to PASS.