Skip to content

v0.14.0

Latest

Choose a tag to compare

@ohdearquant ohdearquant released this 18 Oct 12:01
· 461 commits to main since this release
3a606e2

khive v0.14.0

Minor release. Public Rust types in khive-runtime, khive-types, khive-pack-code, khive-pack-brain and kkernel change in ways that break source compatibility for code that constructs them directly, matches them exhaustively or relies on their auto traits; they are listed under Upgrading with what to change.

The release adds apply_changeset and kkernel kg apply for canonical change-sets, operator-registered code maps with code.list, code.search and code.deps, schema() for the loaded vocabulary, strict schema handling for explicit KG imports, receipt of authenticated mail from outside senders, an email suppression mirror, outbox scan health in comm.health, and khive_types::app for declaring a khive app as data.

Each entry below links the pull request that made the change. Every pull request in the release is listed at the end.

Upgrading from 0.13.0

  • khive_runtime::KhiveConfig adds schema, code_map_root and code_maps, and khive_runtime::RuntimeConfig adds code_map_root, code_maps and code_map_protected_database_paths. Direct struct literals must set them. (#5128, #5612)
  • khive_pack_code::CodeSourceIngestReport adds source_reads, khive_types::ProposalAppliedPayload adds preimage, and kkernel::kg::ImportArgs adds config. Direct struct literals must set them. (#5128, #5426, #5514)
  • New enum variants: khive_runtime::AtomicOpFailure::{OwnerSnapshotConflict, PreimageMismatch}, khive_runtime::AtomicOpPlan::Canonical, khive_runtime::RuntimeError::CanonicalAdmission, khive_runtime::ConfigError::SchemaParse, khive_types::ProposalChangeset::Canonical and kkernel::kg::KgCommand::Apply. None of these enums is #[non_exhaustive], so downstream exhaustive matches must handle them. ProposalChangeset::Canonical precedes Compound, whose implicit discriminant moves from 6 to 7. (#5128, #5426)
  • khive_runtime::AtomicOpPlan is no longer UnwindSafe or RefUnwindSafe. (#5426)
  • khive_pack_brain::persist::PersistenceTracker no longer has the public increment_dirty and reset_dirty methods. (#5226)
  • khive-retrieval persistence and weight APIs take the backend's SQL access handle instead of a raw SQLite connection; see Changed. (#5185)

Added

  • NoteStore::try_patch_note_properties applies guarded partial property writes, forward-only expiry and a monotonic update timestamp in one storage operation. Its provided default returns Unsupported; existing implementations remain source-compatible. Comm duplicate-quarantine repair now uses this typed operation through a channel-ingest capability, preserving its property guards and writer admission while removing the pack's repair SQL. (#5080)
  • KHIVE_EMAIL_EXTERNAL_INBOUND=enabled receives authenticated mail from outside senders (delivered as untrusted external messages and routed as with external senders configured) without setting KHIVE_EMAIL_EXTERNAL_SENDERS, so outbound external sending stays disabled. Start-up fails while it is enabled and KHIVE_EMAIL_EXTERNAL_INBOUND_ACTOR is unset or empty, and on any other non-empty value. (#5442)
  • With KHIVE_EMAIL_SUPPRESSION_MIRROR_URL, KHIVE_EMAIL_SUPPRESSION_MIRROR_TOKEN and KHIVE_EMAIL_SUPPRESSION_MIRROR_MAX_AGE_SECS set, the email outbox reads the complete set of remote one-click suppressions and records every missing key in the local suppression list before an external message is sent (ADR-200 section 6, Amendment 4). A failed read keeps external messages pending, and external admission refuses with suppression mirror stale once the last successful read is older than the maximum age. Each outbox cycle also reads the mirror when its stamp is half the maximum age old, so an idle deployment stays fresh. (#5627)
  • Configured embedding engines may name custom pack providers. MCP, ingest and downstream host composition register providers before binding ordered peers and their declared dimensions, without loading models. Missing providers fail startup; explicit no-embedding runtimes keep no configured default while explicit manual named access remains available. (#5117)
  • khive-lion-core copies Apache-2.0 lion-core 0.4.0 and adds Kernel::with_key for caller-supplied seal keys. All-zero keys are refused; initialization starts at epoch zero with no previous key and the same empty, deny-all state. (#5111)
  • Add schema() for loaded vocabulary and attributed endpoint declarations, including entity subtypes, counts and a stable content hash. The proposed ADR-084 contract remains pending acceptance and conformance validation. (#5125)
  • apply_changeset applies a complete canonical NDJSON change-set as one bounded, ordered writer transaction. Staged create and link identifiers survive application, updates compare the captured values of the fields they touch, and deletes compare the whole captured record except updated_at. kkernel kg apply submits the delta through the daemon, and reviewed canonical proposals use the same path. Merge is refused. (#5426)
  • When a coordinated kg search hits its deadline, the backend search task timed out and backend search task completed after the shared request deadline warnings add in_flight_phase, phase_elapsed_ms, active_phases and completed_phases, naming what the backend search was doing. khive-storage gains request_context::SearchPhaseTrace. Deadlines, budgets, retries, ordering and results are unchanged. (#5616)
  • comm.health reports an outbox scan health snapshot for the email and Telegram transports: completion and success times of the pending-row query and observations of the bounded eligible page. A failed scan keeps the previous success time. (#5326)
  • Explicit KG imports honor [schema].strict, which defaults to true. Strict mode refuses an unknown entity kind before the destination is set up; relaxed mode keeps its spelling and warns once per distinct kind. Local VCS sync degrades unknown kinds to concept and records khive:degraded_kind. (#5128)
  • code_map_root and [[code_maps]] entries (name, path, source_root) in config.toml are validated entry by entry and loaded once into a runtime registry of code maps (ADR-139). A malformed entry is rejected by name without stopping the configuration from loading. (#5612)
  • code.list, code.search and code.deps read operator-registered code maps: list and search paginate deterministically with a cursor bound to the map registration and filters, search ranks exact, then prefix, then interior name matches, and dependency traversal returns nodes breadth-first with incoming normal, dev and build dependencies, accurate node-limit truncation and every dependency edge among the returned nodes. The three verbs are classified as reads. (#5635)
  • link responses disclose a dependency_kind the server inferred, with a hint for each inferred value; a caller-supplied dependency_kind suppresses it. Bulk hints keep the caller's input indices across skips and failures, and an atomic link response carries the hint captured while the plan was prepared. (#5436)
  • The code pack's source ingest records the literal source-file inputs a module names: include!, include_str! and include_bytes! arguments, #[path] attributes, #[doc = include_str!(...)], and filesystem read calls whose argument is a string literal. (#5514)
  • Guarded create-only edge insertion: khive-storage adds GraphStatementGuard, GraphStatementGuardFailure and EdgeInsertIfAbsentOutcome; khive-db evaluates each read-only guard statement inside the edge's writer transaction; khive-runtime adds link_if_absent_with_guards. (#5198)
  • khive_types::app declares a khive app as plain data (ADR-203): name, version, signer, the verb inventory with a rights class per handler, and the kinds it contributes. AppManifest::validate and AppManifest::admit refuse incomplete or conflicting manifests, naming the conflicting owner. (#5518)

Changed

  • RetrievalPersistence::new now accepts Arc<dyn SqlAccess>. Snapshot writes and namespace clears use the backend writer route; loads and statistics use its reader. Core migrations install the snapshot table and namespace index. The existing init_schema compatibility bootstrap now uses the admitted writer. (#5185)
  • khive-retrieval weight updates and batch reads now accept &dyn SqlAccess instead of a raw SQLite connection. Pass the migrated backend's SQL access handle; updates and audit rows commit together through its writer route, and read-only handles refuse updates. Storage failures use PersistError::Storage. Core migrations now install atom_weights and weight_events; the standalone init_weight_schema bootstrap remains available for compatibility. (#5185)
  • Edge-weight validators use the shared khive-types predicate, preserving numeric boundaries and validation diagnostics. (#5109)
  • With a configured runtime actor, a message the email channel quarantines, whatever its reason, is addressed to that actor (the maintainer) instead of the routed landing actor, so the mailbox recipient check keeps the quarantine record and its content reference out of every other actor's inbox, thread, read, get and search results. This applies to records ingested after the upgrade: a quarantine record already stored keeps the landing actor it was written with, and nothing re-addresses it. A runtime with no configured actor keeps the landing actor. (#5422)
  • The email opt-out label (ADR-200 Amendment 2) now reads the first non-quoted paragraph of a reply rather than its first line, so a phrase a mail client wrapped onto the second line still counts, and the phrase list gains the plain asks for no more email ("don't email me", "do not contact me", "no more emails" and their spellings). The bare words "email me" are not a phrase: a reply asking us to email the docs is delivered without the label. (#5524)
  • Email quarantine distinguishes auth-untrusted, a message whose authentication results headers were present but not trusted, from auth-absent. The record carries the anchor mode, the header family and the identifier as an escaped string of at most 128 bytes. (#5437)
  • Bulk link responses report inferred_count instead of repeating an inference explanation for every edge; verbose=true keeps the indexed hints and per-edge explanations. Singleton create edge results disclose inferred dependency kinds. (#5639)
  • context charges anchor-to-anchor edges against the response budget and returns an anchor edge only when both of its anchors were admitted (ADR-140 Amendment 1). (#5323)
  • A best-effort mark-read failure carries mark_error_details (typed code and stage, and the native SQLite write stage and result codes where present) beside mark_error. (#5359)
  • On Linux with glibc, the runtime returns the transient heap of a native embedding model load to the operating system once the built-in embedder has loaded. (#5474)

Fixed

  • SQLite volume-lock refusals name the directory or lock file that could not be used and the underlying I/O error, and name both ways to choose another directory: KHIVE_VOLUME_LOCK_DIR for the default directory resolver, or the caller-supplied lock directory setting. Headless and containerized deployments require a writable home directory or an absolute, writable lock directory shared by all cooperating khive processes of the deployment; an unusable directory still refuses the open rather than falling back to a database-specific directory. (#5435, #5528)
  • An authenticated opt-out in a message that screening quarantines as screened now records the reply-stop suppression for its sender before the quarantine is acknowledged, as a delivered opt-out already did. No other quarantine reason records an opt-out, and ingest refuses one claimed on them. (#5421)
  • A registered code map whose main database file has more than one link is refused at registration and on every read, and the guarded read-only file system checks the link count on the file SQLite reads before any row is read (ADR-139 Amendment 2). A wrong-typed code_maps or code_map_root value fails the configuration load with the key named. khive_db::file_identity::file_link_count reads the link count from an open file. (#5720)
  • db_diagnostics collects size_composition only when the read snapshot holds at most 8,192 pages and 32 MiB, checking both in the same snapshot; a larger store gets no composition and size_composition_error names the observed footprint and the limits. The limits bound the work admitted, not elapsed time. size_composition=false still skips the walk. (#5673)
  • The write-path secret gate treats head=<40-hex>, head <40-hex> and the equals form of the other revision markers (sha=, commit=, revision=, rev=) as revision labels instead of refusing them as credential tokens. (#5459)
  • The web pack's disk ingestion encodes each file name as a URL path segment, so #, ?, % and \ in a name no longer turn into a fragment or query and collapse two files onto one document. (#4458)
  • khive-pack-brain builds without the lattice-router feature no longer fail clippy with unused imports. (#5621)

All pull requests (173)

Features

  • feat(code): read registered maps and dependency graphs (#5635)
  • khive-db: read-only open of a registered code map (#5628)
  • feat(comm): pull the remote suppression mirror before external delivery (#5627)
  • feat(search): name the in-flight phase when a backend search hits its deadline (#5616)
  • feat(runtime): load registered code maps into a runtime registry (#5612)
  • feat(types): app manifest with install refusals (#5518)
  • feat(code): record literal source-file inputs (#5514)
  • feat(email): receive external mail without enabling external sending (#5442)
  • feat(kg): disclose inferred dependency kinds (#5436)
  • feat(kg): apply canonical changesets atomically (#5426)
  • feat(comm): report outbox scan health (#5326)
  • feat(storage): add guarded create-only graph composition (#5198)
  • feat(import): apply schema strictness without widening graph vocabulary (#5128)
  • feat(kg): expose loaded ontology through schema (#5125)
  • feat(runtime): bind configured embedding providers (#5117)
  • feat(core): add the keyed capability kernel (#5111)
  • feat(storage): support guarded partial note updates (#5080)

Fixes

  • fix(code-map): refuse registered map files with more than one link (#5720)
  • fix(db): admit size composition only for bounded snapshots (#5673)
  • fix(kg): bound and complete dependency inference hints (#5639)
  • fix(brain): compile the router module only with lattice-router (#5621)
  • fix(db): clarify volume-lock failure paths and configuration (#5528)
  • fix(email): read the opt-out window as the first paragraph and name asks for no more email (#5524)
  • fix(runtime): recognize Git head and equals revision labels (#5459)
  • fix(email): distinguish untrusted authentication headers (#5437)
  • fix(db): explain unusable volume-lock directories (#5435)
  • fix(comm): address quarantine records to the maintainer (#5422)
  • fix(comm): record an opt-out from a screened quarantine (#5421)
  • fix(comm): preserve typed mark-read failure details (#5359)
  • fix(kg): charge anchor edges to the context budget (#5323)
  • fix(retrieval): route index persistence through shared storage (#5185)
  • fix(web): encode disk filenames as URL path segments (#4458)

Performance

  • perf(runtime): release transient embedder load heap on Linux glibc (#5474)

Documentation

  • docs(adr): ADR-206 Amendment 2, measured references; first references for ten crates (#5725)
  • docs: correct stale facts in the developer guide (#5724)
  • docs(adr): ADR-139 Amendment 2, a registered map file has exactly one link (#5719)
  • docs(adr): ADR-200 amendment 5, occurrence-aware undo and complete mirror snapshots (#5716)
  • docs(adr): ADR-049 points at the events daemon supervisor in its new module (#5704)
  • docs(adr): ADR-040 archival, one membership parse at census and re-check (#5702)
  • docs(skills): state search score and comm.read contracts as served (#5679)
  • docs(adr): ADR-168 amendment, split event store and backfill version 1 (#5678)
  • docs(adr): ADR-206 crate performance guarantees (#5642)
  • docs(adr): ADR-040 amendment, comm message archival version 1 (#5633)
  • docs(adr): ADR-200 Amendment 4, the suppression mirror's credential, answer and idle refresh (#5626)
  • docs(adr): ADR-139 Amendment 1, registered maps are read in rollback mode (#5615)
  • docs(adr): name the code map's dependency fields in ADR-205 (#5606)
  • docs(adr): propose dependency-scoped pull-request CI from the code map (ADR-205) (#5601)
  • docs(retrieval): describe the crate without the retired HNSW default (#5600)
  • docs(adr): accept ADR-139, code-map read access (#5599)
  • docs(adr): propose automatic freelist reclamation with incremental auto-vacuum (ADR-204) (#5527)
  • docs(adr): point ADR-056 quarantine addressing at ADR-200 Amendment 1 (#5521)
  • docs(adr): propose restore and inversion-limit amendments to ADR-101 and ADR-102 (#5520)
  • docs(adr): propose khive apps on the base (ADR-203) (#5516)
  • docs(adr): propose read-only pack validation pipeline (#5400)
  • docs: require governing ADRs for verb contract changes (#5361)

Tests

  • test(runtime): resolve route acceptance references (#5641)
  • test(db): separate bootstrap and contention deadlines (#5636)
  • test(kg): compare full guarded event insert statements (#5634)
  • test(email): record screening outcomes for six outreach replies (#5515)
  • test(brain): group help and event value test concerns (#5513)
  • test(fold): group checkpoint and objective test concerns (#5511)
  • test(retrieval): group executor and query variant concerns (#5506)
  • test(git): group remote and dedup test concerns (#5504)
  • test(db): split event-store test concerns (#5503)
  • test(runtime): isolate demand-retirement worker assertions (#5438)
  • test(db): fix the walpin heartbeat boundary clock (#5432)
  • test(knowledge): instrument inline ANN runtime responsiveness (#5261)

Benchmarks

  • bench(channel): cover receipt verification and allocation bounds (#5686)
  • bench(bm25): cover reset, cache guards and tokenization (#5682)
  • bench(quant): cover affine distances and codec throughput (#5680)

Refactoring

  • refactor(runtime): split route_census.rs into submodules (#5613)
  • refactor(runtime): split events_split.rs into submodules (#5611)
  • refactor(email): split channel.rs into submodules (#5610)
  • refactor(brain): split handlers.rs into submodules (#5609)
  • refactor(git): split ingest.rs into submodules (#5608)
  • refactor(db): split stores/graph.rs into submodules (#5607)
  • refactor(memory): split ann.rs into state, bridge, loaded-index, warm, watermark, fresh-tail and checkpoint modules (#5554)
  • refactor(runtime): split daemon.rs into dispatch, connection, run loop, boot guard and process-file modules (#5531)
  • refactor(knowledge): split vamana.rs by concern and move search reranking out (#5530)
  • refactor(mcp): move daemon recovery into daemon/recovery.rs (#5529)
  • refactor(db): group S3 blob value tests by concern (#5512)
  • refactor(query): group parser tests by concern (#5510)
  • refactor(telegram): group channel and wire value tests (#5509)
  • refactor(brain-core): group state value tests by concern (#5508)
  • refactor(storage): group accessor and error classification tests (#5507)
  • refactor(schedule): share repeated recurrence parameter definitions (#5502)
  • refactor(gtd): share repeated lifecycle parameter definitions (#5501)
  • refactor(comm): share repeated parameter definitions (#5500)
  • refactor(knowledge): share repeated verb parameter definitions (#5499)
  • refactor(query): share ASCII digit-run scanning (#5498)
  • refactor(telemetry): share verb parameter definitions (#5497)
  • refactor(session): share string-parts extraction (#5496)
  • refactor(blob): share range validation and part decode errors (#5495)
  • refactor(fusion): validate borrowed weighted RRF parameters (#5494)
  • refactor(merge): share object-property value selection (#5493)
  • refactor(wire): share handshake sequence error construction (#5492)
  • refactor(request): share quoted-string owned-prefix construction (#5491)
  • refactor(channel-email): group backoff and unsubscribe value tests (#5490)
  • refactor(repo-showcase): share model bounds and ratio validation (#5489)
  • refactor(telegram): share Bot API response body handling (#5488)
  • refactor(vcs): lowercase snapshot IDs in place (#5487)
  • refactor(graph-diff): use a single entry lookup for parsed records (#5486)
  • refactor(rule-evaluator): share lazy NDJSON parsing for ID collectors (#5485)
  • refactor(text): reuse script character counts without collecting (#5484)
  • refactor(knowledge): group handler and compose member value tests (#5483)
  • refactor(db): group ordinary graph query tests (#5482)
  • refactor(memory): share calibrated relevance normalization (#5481)
  • refactor(runtime): delegate objective selection results directly (#5479)
  • refactor(db): group ordinary entity and note record tests (#5478)
  • refactor(runtime): group catalog metadata and help description tests (#5476)
  • refactor(memory): group configuration serialization and positive ranking tests (#5475)
  • refactor(hnsw): group dimension and metric contract tests (#5473)
  • refactor(runtime): organize presentation tests by concern (#5472)
  • refactor(db): group ordinary text and agent store tests (#5471)
  • refactor(gate): separate actor and value contract tests (#5470)
  • refactor(fold): split selector tests by concern (#5469)
  • refactor(channel): split adapter contract tests by concern (#5468)
  • refactor(kkernel): separate ranking and showcase CLI test concerns (#5467)
  • refactor(types): split general entity-type tests by concern (#5465)
  • refactor(merge): split three-way merge tests by concern (#5464)
  • refactor(quant): split codec tests by concern (#5463)
  • refactor(bm25): split unit tests by concern (#5462)
  • refactor(repo-showcase): split export contract tests by concern (#5461)
  • refactor(wire-protocol): split codec tests by concern (#5460)
  • refactor(telemetry): split integration tests by concern (#5458)
  • refactor(vcs-adapters): split JSON adapter tests by concern (#5457)
  • refactor(charter): split general schema admission tests by concern (#5456)
  • refactor(git): split cache and source tests by concern (#5455)
  • refactor(blob): split staged upload tests by concern (#5454)
  • refactor(brain): split general profile tests by concern (#5453)
  • refactor(runtime): split general integration tests by concern (#5452)
  • refactor(kkernel): split CLI validation and supervisor tests by concern (#5451)
  • refactor(knowledge): split general integration tests by concern (#5450)
  • refactor(kg): split message graph scope tests by concern (#5449)
  • refactor(memory): split general integration tests by concern (#5447)
  • refactor(mcp): split integration and attachment replay tests by concern (#5446)
  • refactor(rule-evaluator): split evaluation and tier tests by concern (#5445)
  • refactor(blob): split integration tests by concern (#5444)
  • refactor(session): split mirror and integration tests by concern (#5443)
  • refactor(request): group parser corpus tests by concern (#5441)
  • refactor(git): group acceptance and development tests by concern (#5440)
  • refactor(schedule): group integration tests by concern (#5439)
  • refactor(fs): group bounded walker tests by concern (#5434)
  • refactor(query): group SQL compiler tests by concern (#5433)
  • refactor(comm): group delivery and idempotency tests by concern (#5431)
  • refactor(types): group relation certificate tests by concern (#5430)
  • refactor(storage): group vector contract tests by concern (#5429)
  • refactor(retrieval): split materialization tests by concern (#5427)
  • refactor(vcs): partition hash tests by concern (#5423)
  • refactor(schedule): guard cancellation with note revisions (#5329)
  • refactor(kg): reuse guarded event bindings (#5328)
  • refactor(kkernel): use grouped counts for nullable entity census (#5327)
  • refactor(runtime): share pack relation collection (#5280)
  • refactor(runtime): consolidate identity and edge reads (#5260)
  • refactor(code): split source ingest into focused modules (#5231)
  • refactor(brain): share persistence and decay helpers (#5226)
  • refactor(knowledge): share import and prefix helpers (#5222)
  • refactor(score): share vector similarity and normalization (#5146)
  • refactor(git): consolidate typed entity row selectors (#5139)
  • refactor(runtime): share secure filesystem operations (#5138)
  • refactor(validation): adopt the shared edge-weight predicate (#5109)
  • refactor(mcp): extract daemon self-heal transport (#5064)
  • refactor(mcp): extract Telegram polling and outbound loops (#5028)
  • refactor(web): extract fetch and extraction unit tests (#4465)

Build, CI and release

  • chore(release): 0.14.0 (#5728)
  • ci(bench): run the dependents closure once per merge train (#5703)
  • ci: scope pull-request test runs to the changed crates and their dependents (#5638)
  • test(ci): turn off git auto-maintenance in fixture repositories (#5625)
  • ci: run split and docs pull requests on the Linux shards only (#5604)
  • ci: classify main pushes from main's history only (#5602)
  • ci: record benchmark trend points nightly and per release instead of per merge (#5542)
  • ci: cancel a superseded main push run so a merge burst leaves one run (#5532)
  • ci: integration lane for crate-source pull requests from the automation branch prefix (#5505)

Full list of changes: v0.13.0...v0.14.0