All notable changes to this project are documented here, newest first. Format follows Keep a Changelog; versioning is not yet SemVer-stable (0.x — breaking changes land in minor series with a migration guide).
Predictormoved to core asknot::Predictor(ADR-006 rule 6): the inference-side contract now lives besideSystemOneRequest/Engine, so a future nqlite adapter crate can depend onknotwithout pullingknot-serve— which would otherwise form a package cycle through the single binary (ADR-004).knot_serve::Predictorkeeps working via a re-export; no behavior change, parity fixtures untouched. Gated with the engine (onnx/candle), so a no-runtime build stays clean.knot-nqliteadapter crate (ADR-006 seam B): an opt-inPredictordecorator that appends one nqlite transaction per decision after the response —state -[:decided]-> decision -[:used_checkpoint]-> checkpointplus a hash-only decision row (length-limited excerpt; full state is never stored). Off by default: enable per deployment with theauditfeature ofknot-serve+KNOT_AUDIT_DB=<store-file>(capacity/excerpt viaKNOT_AUDIT_CAPACITY/KNOT_AUDIT_EXCERPT). Bounded queue with counted overflow (never blocks the hot path, never silent), dedicated writer thread owning the single store handle,PRUNE HISTORYon boot.
- Renamed the decision engine
oio→ knot: cratesoio/oio-serveare nowknot/knot-serve, the installed binary isknot, config movedOIO_*→KNOT_*(hard cut, no shims), MCP tools areknot_*, and the default cache dir is~/.cache/knot. See docs/MIGRATION.md and docs/ADR/007-knot-naming.md. - Repository moved
devstroop/oio→devstroop/knot(redirect preserved);oiostays as the parent initiative name. - Training data-plane identifiers renamed off
oio(the ADR-007 freeze of these strings is revoked): the synthetic score source is nowknot-authored/score-smoke(revisionknot-training-v1), internal row keys are_knot_row_index, and the prepared-data manifest note reads "knot-authored". Corpora and feature caches issued under the old IDs no longer validate — re-runpython -m training.prepare_data+python -m training.validate_data, then rebuild the feature cache. Recorded evidence (demo/results.json) keeps its original names as history.
Behavior, wire protocol (/v1/systemone), checkpoint formats, and eval
semantics are unchanged — parity fixtures pass byte-identical across the
rename.
- Routing to an unconfigured checkpoint no longer 500s (#37): on a
single-checkpoint deploy, a non-Latin/mixed-language state routed to
multilingualand failed with the generic 500inference failed— which broke MCP tool calls (VS Code chat turns) and HTTP requests alike. The request now serves from a configured checkpoint (router default / first loaded) with the substitution recorded inrouting.fallback: {requested, served}and a warn log — Laya's "ignore unavailable", made auditable instead of silent. When the deployment configured no checkpoint at all, the request fails loud asCheckpointUnavailable→ 503 with the real reason and aKNOT_MODEL_DIR/KNOT_DEFAULT_MODELhint. Configured routes and parity fixtures stay byte-identical (fallbackis omitted when absent). - MCP stdio no longer answers notifications: unknown notifications
(e.g.
notifications/roots/list_changed) were replied to with anid: nullerror response — JSON-RPC 2.0 forbids answering a notification, and strict clients logged protocol errors for it.
Earlier work is recorded in git history and the decision
records: Laya-compatible decision engine (ONNX + Candle
runtimes), frozen-head training pipeline with predeclared quality gates and a
passing held-out verdict, Gita retrieval/decision demos, and the
frozen-encoder feature cache. No changelog was kept before this file; see
git log for the full record.