Changelog

What changed.

Version-by-version. Newest first. For the story behind releases, see Announcements.

2026.10.16 — v2.5.4

v2.5.4

asanagidb-mcp works on Windows and over the network, Gremlin's P. and TextP. predicates match, and the document memory holds every assistant to its reading rules.

Added

  • asanagidb-mcp --config. All settings, including the document folders, in one JSON file; flags still win. Docs.

Changed

  • Reading Rules Enforced. The server now checks what the extraction instructions ask: sections read before they're reported, 2 to 6 questions for longer sections, listed concept kinds, and the reader's model name.

Fixed

  • asanagidb-mcp on Windows. The HTTP transport and --remote failed on the first request; document folders rejected every file.
  • Large Memories over --remote. Results above 5,000 items failed with EndOfStream; MCP connections now get whole results. Listings are dozens of times faster (2,003 notes: 6 s instead of 13 minutes). A dropped connection reconnects, and a failed tool call names its error instead of returning an unreadable reply.
  • P. and TextP. Predicates. has('age', P.gte(30)) silently matched nothing; it now means gte(30).
  • g.V([1, 2]) and g.V(1, 2).count(). A list of ids returned every vertex, and counting given ids counted the whole graph.
  • addE().from() without to(). No edge was created and a following property() wrote onto the vertex.
  • limit() above the page size. Over the network it scanned the whole label and could fail with QueryResultTooLarge.
  • Forgetting Documents of a Removed Folder. They can now be forgotten, and missing files are listed as gone.

2026.10.16 — v2.5.3

v2.5.3

Memory notes become documents your assistant can read and search, and the index repair tools from 2.5.2 are withdrawn.

Added

  • Memory Notes as Documents. asanagidb-mcp --rag-memory decision,design,... makes every memory note with one of those words in its name a document the RAG tools read, as memory:<name>, with nothing exported to files. A note saved with new text lists as changed, so it is read again; a deleted one lists as gone. Docs.
  • Index Invariant Test. A seeded random run of creates, value changes, deletes and transaction boundaries, after which every index entry must belong to a live vertex and match its value.

Changed

  • Index Repair Withdrawn. Indexes are written in the same transaction as the data, so an index out of step with it is an engine bug to fix at the source, not maintenance. repair_index and asanagidb-admin index-check / index-repair are gone; asanagidb-admin check still reports such entries as an integrity error.
  • A Dead Index Entry Is Reported as a Bug. Queries still skip it and succeed, and the server logs an error asking for a report.

2026.10.15 — v2.5.2

v2.5.2

Indexes stay clean when old boolean values are deleted or changed, and an index can now be checked and repaired.

Fixed

  • Stale Index Entries from Old true Values. Engines before 2.5.0 stored true in a form that reads back as an empty string while indexing it as a boolean. Deleting such a vertex, or changing the value, left the true index entry behind, and indexed queries that reached it failed with NotFound. Both now remove it.
  • Indexed Queries Skip Dead Entries. An index entry whose vertex is gone is skipped, and the server logs one warning naming the property and the repair command.

Added

  • Index Repair. The repair_index admin command counts (with dry_run) or removes index entries whose vertex no longer exists. With the engine stopped, asanagidb-admin index-check / index-repair does the same, and asanagidb-admin check now reports them.

2026.10.15 — v2.5.1

v2.5.1

Fixes found running 2.5.0 on a Raspberry Pi.

Fixed

  • Unix Socket Connections on Linux. asna --socket and asanagidb-mcp --remote <socket> failed with ConnectFailed on Linux: the Unix socket address was only fully set up on macOS. TCP connections were not affected.
  • asna Named the Wrong Database. Without --db, asna uses the server's default database (local unless the instance configures another), but said default. It now says so. asanagidb-mcp uses the database default, so use asna --db default to see what it stored.
  • Clean Linux Archives. The Linux ARM archive carried macOS metadata files that GNU tar warns about. Release archives no longer include them.

2026.10.15 — v2.5.0

v2.5.0

Document memory comes to asanagidb-mcp, AsanagiDB runs on the Raspberry Pi, and booleans and arrays are stored correctly.

Added

  • Document Memory (RAG) in asanagidb-mcp. Start asanagidb-mcp with --rag-folder and an assistant can read the documents in that folder into memory and search them before it answers. The graph keeps each document's sections, the concepts they mention, the facts and questions they answer and how the concepts relate, and where each section is in its file: never the text. memory_save takes about, the document concepts a memory is about. Markdown, plain text, reStructuredText, Org, AsciiDoc and TeX. See the docs.
  • Linux on 64-bit ARM. A new linux-aarch64 archive for the Raspberry Pi 3, 4 and 5 and ARM servers, and Homebrew installs on ARM Linux. Statically linked like the x86_64 build, so any distribution works.
  • An Embeddable Engine. The C API runs the database and MCP servers inside a host app, runs admin commands and document requests on the engine's own databases, and talks to other AsanagiDB servers. It is what AsanagiDB Desktop is built on.

Fixed

  • true Read Back as an Empty String. A stored true collided with the string marker and read back as "". Booleans now have their own marker. Values written by earlier versions read as before, so an old true still reads as "" until you write it again.
  • Arrays of Plain Values Became Vertices. A document property like "tags": ["a", "b"] became one vertex per item. It is now stored as one value and read back as the same array; arrays of objects are stored as before. An array mixing objects and plain values is refused with MixedArrayItems.
  • Dangling Edges After a Drop. Dropping a vertex could skip some of its edges and leave them dangling.

Compatibility

  • Data written by 2.5.0 (booleans, arrays of plain values) is not read correctly by 2.4.x. Keep a backup before upgrading if you might go back.

2026.10.06 — v2.4.3

v2.4.3

Step labels now survive a V() in the middle of a traversal, so addE().from().to() connects the vertices you named.

Fixed

  • Step Labels Lost After a Mid-Traversal V(). A V() (or E()) in the middle of a traversal dropped every as() label set before it. select('a') returned nothing, and addE().from('a').to('b') wrote the edge from the wrong vertex, or not at all, while reporting success. If you ran queries of this shape on 2.4.2 or earlier, check the edges they wrote.

Changed

  • Unknown Step Labels Are Errors. addE().from() and to() with a label that was never set, or that names something other than a vertex, now fail with UnresolvedStepLabel and write nothing. Before, a typo silently started the edge at the current vertex or created no edge at all.

2026.10.06 — v2.4.2

v2.4.2

limit() and range() now stop vertex scans early, so queries over large labels no longer read the whole graph into memory.

Fixed

  • limit(n) Didn't Stop Vertex Scans Early. Only range(a, b) was folded into index and label scans, causing limit() queries on large labels to fail with QueryResultTooLarge. limit(n) now folds like range(0, n).
  • Plain V().limit(n) and V().range(a, b) Scanned the Whole Graph. The unfiltered V() scan had no range fold at all; it now stops after the bound.
  • No Range or Limit Fold Over ASNA or WebSocket. Every non-aggregating network query runs with a paging cursor, and an active cursor disabled the fold. A fold now also applies on a fresh cursor when the bound fits in one page (ASANAGIDB_PAGE_SIZE, default 5000). A larger bound still scans, as before.
  • valueMap(true) Ignored the true. It now includes the element's id and label, under the same t.id / t.label keys as elementMap().
  • asanagidb --help Failed With FileNotFound. On a machine without a local configuration, the configuration was loaded before the options were read. Server help is now printed before anything else is loaded.
  • LmdbPutFailed Didn't Say Why. A failed write logged only the key and value it tried to store, not LMDB's error. Every failed write now logs mdb_put failed: rc=<code> (<LMDB message>) with the table and the key and value sizes, and a failed delete logs mdb_del failed the same way.
  • Relabeling a Vertex Logged Errors When It Worked. Every relabel wrote three error-level trace lines ending in relabelVertex: SUCCESS. They are debug-level now; real failures still log as errors.

Changed

  • Folds Only Apply When V() Starts the Traversal. A mid-traversal V() runs once per incoming traverser, so a range() or limit() after it bounds the whole stream, not each V() call.
  • limit(n) Without order() Can Return Different Vertices. A folded scan stops after the first n vertices in index order instead of queueing the whole label. Gremlin doesn't define an order without order(); add order().by(...) where it matters.
  • Scoped Forms Never Fold. limit(local, n) and range(local, a, b) bound each traverser's collection, not the stream.

2026.09.29 — v2.4.1

v2.4.1

One way to start the server: asanagidb [options]. Its options now always apply, and an unknown option is an error instead of being silently skipped.

Removed

  • The server Command. The server is what asanagidb runs when given no command, which is how every packaged service starts it. asanagidb server now exits with an error saying to drop the word.

Fixed

  • Server Options Ignored Without server. --no-wal, --no-uds, --uds-path, --tls-cert and --tls-key were read only after an explicit server, so a service started with --config … --no-wal ran with the WAL on.
  • --help Started the Server. It now prints the options and the list of commands.
  • --tls-cert Path Taken for a Command. When it was the first argument.

Upgrade Notes

  • macOS daemons created with asanagidb service install ran asanagidb server …. The 2.4.1 installer package fixes them automatically. If you upgrade another way (Homebrew, a tarball), delete the <string>server</string> line from /Library/LaunchDaemons/com.asanagi.asanagidb.<instance>.plist and reload it. The package's own daemon and the Linux systemd units need nothing.

2026.09.29 — v2.4.0

v2.4.0

Every write is now logged exactly as it happened, so replicas are byte-for-byte copies of the primary, and batches of documents commit in a single transaction. On a spinning disk, AsanagiIDX's listing sync went from 9 to ~760 listings per second.

Added

  • store_many. Store a batch of documents in one transaction, with optional upsert on a key field you name: a matching document is updated with the fields sent, otherwise one is created. A document missing the key rejects the whole batch. An unindexed key still works (a full scan per document, warned about once), so index your key fields. Available in the Go client as StoreMany and advertised in server_info.

Changed

  • Write-Ahead Log v2. The WAL used to record Gremlin steps worked out from the query before it ran, so writes whose targets were found at runtime (has(...).property(...), mergeV/mergeE) never replayed or replicated, and document writes weren't logged at all. It now records every change each transaction actually made. Recovery and replicas re-apply exactly those changes, and replay is safe to repeat.
  • Bounded WAL. The log is emptied once it passes 64 MB (everything in it is already durable in the database); connected replicas re-snapshot automatically.
  • Replication Protocol v2. Upgrade the primary and its replicas together; a v1 peer is refused. An old WAL is replayed once at startup, then migrated.

Fixed

  • Memory Leak on Document Updates. Every update of an existing document leaked a small allocation.
  • Crash After a Failed Commit. A write whose commit failed could roll back an already-freed transaction and crash the engine.

2026.09.24 — v2.3.0

v2.3.0

Found by stress-testing AsanagiIDX against a copy of production data. Filtered searches went from ~1.2 s to 15–40 ms, and a 4-core box now serves ~1,000 concurrent visitors (it previously collapsed at ~40), shedding load gracefully beyond that.

Fixed

  • Numeric Indexes Compared by Type, Not Value. An integer predicate never matched a double-stored value, and range seeks could run past the numbers into other types. Index keys now use a single order-preserving encoding for every numeric type, and range seeks stay within the query value's type. Existing databases upgrade once at open; string-only indexes migrate instantly.
  • Scalar has(k, v) Numeric Equality. has(k, 3) now matches a stored 3.0, and long/double values compare by value.
  • Partial Indexes After Late Registration. Registering an index on a populated database now backfills it, so seeks no longer silently miss vertices written before registration.
  • Whole-Graph Scans for Unindexed Filters. An unindexed has() alongside a hasLabel() now scans only that label's vertices.
  • Per-Traverser Index Walks. A mid-traversal has() step read the property index once per traverser and logged a warning each time. It now reads the property directly and warns once per key per query.
  • Filter Sub-Traversal Memory Growth. or, and, not, where, filter, and choose probes now run in a scratch arena freed immediately, instead of accumulating (up to ~1.6 GB per query on large candidate sets).
  • Orphaned Traversals After Disconnect. A client disconnecting no longer leaves its traversal running to the timeout. A per-connection cancel token aborts in-flight work when the connection closes, and at shutdown.
  • Sockets Stuck in CLOSE_WAIT Under Load. A race between job completion and connection close could leave a socket unclosed. Closes now retry themselves, and the reaper drains any stragglers. Verified with 0 leaked sockets across ~434K connections.

Added

  • server_info reports the engine version and behavior feature flags; the Go document SDK exposes it as Client.ServerInfo().
  • ASANAGIDB_TRAVERSAL_TIMEOUT_MS (default 30000) sets the per-traversal wall-clock budget.
  • asanagidb-admin list index -d <db> lists every registered index with its entry count.

2026.09.22 — v2.2.2

v2.2.2

Fixed

  • Paged Queries Materializing the Whole Match Set First. A has()/hasLabel() search followed by range() or limit() — the standard shape of a paged query — was scanning and staging every matching vertex before the page boundary ever got a chance to trim it, instead of stopping once the requested page was filled. On a large enough label this could exceed the engine's pending-state safety ceiling and fail the query outright, even for a small page size. Found in production once a label crossed roughly 100K vertices. All five affected scan paths (indexed, label-index, and unindexed-property fallbacks) now stop scanning the instant a page is satisfied.

2026.09.14 — v2.2.1

v2.2.1

Fixed

  • Connection Teardown File Descriptor Leak. Every closed connection leaked one file descriptor, stuck permanently in CLOSE_WAIT. Found in production after sustained short-lived-connection load approached the process's file-descriptor ceiling. Fixed by closing the socket directly instead of through libxev's async close path, which silently required a thread pool the reactor doesn't run. Verified with multi-thousand-connection churn tests on both Linux and macOS with zero leaks.
  • Silent Accept Failures. A connection failing at the file-descriptor ceiling now logs a rate-limited warning with the live connection count, instead of failing with no diagnostic trail.

2026.09.14 — v2.2.0

v2.2.0

Fixed

  • Gremlin Response Write-Lock Contention. Read-only Gremlin responses were taking the database's exclusive write-transaction lock purely to serialize an already-computed result, contending against real writers on every single response. Under sustained write load this could block a read indefinitely, which a client experiences as a timeout-and-reconnect loop. Now uses a read-only transaction, matching every other read path.
  • Compository/Kotlin Reconciliation. Internal document ID and array-property class handling reconciled against the original reference implementation for exact semantic parity.

2026.09.07 — v2.0.0

v2.0.0

Changed

  • Event-Loop Reactor Architecture. Replaced the OS thread-per-connection model and 256-connection ceiling with a libxev event-loop reactor. A single loop thread multiplexes all incoming connections and dispatches framed requests to a bounded worker pool.
  • Platform-Specific I/O Backends. Uses epoll on Linux (verified for 4,000–6,000 concurrent connections and ~72,000 open/close cycles with flat memory and zero file descriptor leaks) and kqueue on macOS. Windows runs a blocking Winsock fallback sharing the same framing and dispatch code so behaviour is identical.
  • Unified Transport Engine. Three protocol formats (WebSocket GraphSON/GraphBinary, ASNA binary, and JSON-line) across both TCP and Unix domain socket (UDS) transports run through the reactor pipeline (or the Winsock fallback on Windows sharing identical framing and dispatch code).
  • Cross-Platform REPL (asna). Moved the asna Gremlin REPL line editor to a vendored library, enabling native Windows builds and cross-compilation across platforms.

Added

  • TLS 1.3 Encryption. Native TLS 1.3 server authentication on the TCP listener via --tls-cert / --tls-key flags or ASANAGIDB_TLS_CERT / ASANAGIDB_TLS_KEY environment variables. (Unix domain sockets remain plaintext; unavailable on Windows fallback).
  • Bounded Worker Queue & Backpressure. Added configurable worker pool sizing (EXECUTION_POOL_SIZE, default 64) and queue capacity (EXECUTION_QUEUE_MAX, default 1024). Overflow requests return a standard Gremlin 597 ("too busy") status response instead of dropping socket connections.
  • WebSocket SASL PLAIN Auth. End-to-end SASL PLAIN authentication over WebSockets. The server buffers pre-authentication requests and replays them under the original request ID upon successful authentication.

Fixed

  • Write-Load Connection Drop Cascades. Resolved socket drops ("write: broken pipe") and client reconnect stampedes under sustained write load that previously exhausted the connection ceiling.
  • LMDB Reader Table Fixes. Bundled fixes for LMDB reader-table allocation and read-transaction handling.

2026.08.31 — v1.2.0

v1.2.0

Added

  • Multi-predicate index-seek intersection. A structured query with several has() filters now seeks every indexed predicate and intersects the matching id sets, instead of seeking one and scanning every seeded vertex for the rest. Filtered searches that ran for multiple seconds return in <100 ms on a 70k-vertex graph. The optimization is order-independent — it fires whether hasLabel() or a has() comes first — and any predicate on a non-indexed key falls back to a per-survivor residual check. Single-predicate and bare hasLabel() paths are unchanged.

Fixed

  • has(key, lt(x)) and has(key, lte(x)) on an indexed property returned no rows — the index cursor was positioned past every matching entry before the scan began. It now walks the property's key range from the start and stops at the boundary; lte includes the boundary value. gt/gte/between/inside were already correct.

2026.08.29 — v1.1.0

v1.1.0

Added

  • explodeSymbolic() Gremlin step — materializes a stored SymbolicExpr into first-class SymbolicOp/Var/Lit/Call vertices and left/right/operand/arg_N edges, so formal logic is traversable with Gremlin — not just an opaque blob handed to Z3. It is an explicit, opt-in write; proving never mutates the graph.
  • smtProve() now accepts a logic-root vertex directly (g.V().hasLabel('SymbolicOp').smtProve()), rebuilding the assertion from the tree and deriving each variable's SMT sort from its SymbolicVar node — the manual typeMap argument is now optional.

Fixed

  • Variable sorts (Int/Real/Bool/String) now survive a graph round-trip instead of collapsing to Int.
  • Multi-argument logic calls keep their positional argument order through serialization and reconstruction.

2026.08.26 — v1.0.4

v1.0.4

Fixed

  • asanagidb could crash with "reached unreachable code" the moment a client (including the Admin UI) requested list_databases against a server started with no explicit data-path configuration — the default relative data path was never resolved to an absolute one before an internal directory check that requires it. Only the completely flag-free invocation was affected; any server started with --config or an explicit data-path override was never at risk.
  • Shipped release binaries no longer embed the build machine's absolute filesystem paths in debug info or compiled-in assertion strings.

2026.08.12 — v1.0.2

v1.0.2

Fixed

  • Resolved an issue in asanagidb where the server failed to populate uds_path from YAML instance configuration files (--config), causing instances to fall back to /tmp/asanagidb.sock instead of respecting custom socket paths.

2026.08.12 — v1.0.1

v1.0.1

Fixed

  • Web Admin UI <base href="/admin/" /> routing fixes for seamless standalone dashboard execution.

2026.08.09 — v1.0.0

v1.0.0

Added

  • Thirty-one new Gremlin steps, taking AsanagiDB from roughly a third of the TinkerPop traversal vocabulary to about two thirds.
  • match() — declarative pattern matching with variable binding, using the same greedy pattern-selection algorithm TinkerPop ships.
  • branch()/option(), plus choose()'s value-matching switch form.
  • Set operations — combine(), conjoin(), difference(), disjunct(), intersect(), product(), merge().
  • Path filters (simplePath(), cyclicPath()), tree(), sack(), math(), local(), sideEffect(), propertyMap(), index(), loops(), timeLimit(), coin(), fail().
  • Date and formatting steps — asDate(), dateAdd(), dateDiff(), format() — plus asBool()/asNumber() and the all()/any() collection predicates.

Fixed

  • otherV() wasn't implemented at all, despite being a standard edge-traversal step — any query ending in it errored out.
  • element() silently dropped every traverser that was already a vertex or edge, instead of passing it through.
  • group()/groupCount() with .by(propertyKey) ignored any key other than the vertex label, silently grouping by vertex identity instead.

Security

  • Fixed an SMT-LIB injection in the logic_prove tool. Type names supplied by the caller were written verbatim into the generated solver script, so a crafted value could close the enclosing expression and append its own assertions — making the solver answer a different question and report a false "proven" result. Identifiers are now validated against the SMT-LIB symbol grammar.
  • The solver subprocess now enforces a wall-clock timeout, an output-size cap and an input-size bound. Previously a hard or hostile query could hang the caller indefinitely or buffer unbounded output.

2026.08.08 — v0.25.3

v0.25.3

Added

  • Text/string manipulation step family: asString(), substring(), trim()/lTrim()/rTrim(), toUpper()/toLower(), replace(), split(), length(), reverse(), and concat().
  • sample() — both global (a true reducing barrier) and Scope.local forms.
  • cap() to read back named side-effects from store()/aggregate().
  • Date and Timestamp GraphBinary values now decode correctly over the wire.
  • group() now supports multi-step .by() reducers, not just single-step ones.
  • TextP predicates (containing(), startingWith(), endingWith(), etc.) now decode and evaluate correctly.
  • filter(), and(), map(), flatMap(), and choose() for the standard predicate/traversal forms.

Fixed

  • order().by(key) used to keep elements missing that key, just unordered; it now drops them, matching real TinkerPop semantics. String-keyed sorts (order().by("name")) also work correctly now — string comparison was never actually implemented before, only numeric.
  • group()/groupCount() with .by(propertyKey) ignored any key other than the vertex label — grouping by an arbitrary property silently used the vertex's own identity as the key instead, making group().by("name")-style queries completely non-functional. Fixed.

2026.08.05 — v0.25.0

v0.25.0

Added

  • asna — a new interactive Gremlin console (macOS and Linux). Connect over a Unix socket, plain TCP, or WebSocket (ws:///wss://), with line editing, history, and named connection profiles for switching between instances. Run a single script and exit, or drop into a REPL.
  • --central/--public federation (memory_share/memory_fetch) is now fully functional end to end for the first time — publishing and fetching entities between two MCP instances now actually moves data, not just establishes a connection.

Fixed

  • elementMap() only ever handled edges — g.V().elementMap() silently returned nothing for every vertex. It now returns t.id/t.label/properties for vertices too.
  • A wire-protocol offset bug in the MCP server's --remote/--central client corrupted any response carrying real data, and a related bug caused a single matching result to be returned in the wrong shape. Both fixed.
  • An unrecognized Gremlin step name (e.g. a typo) used to fail silently, returning zero results with no indication anything was wrong. It now returns a clear error.
  • --public mTLS certificate provisioning could crash outright on first use; certificate generation now uses a key type the TLS layer actually supports.

2026.08.01 — v0.24.4

v0.24.4

Fixed

  • valueMap(key1, key2, ...) ignored the requested key list and always returned every property on the vertex or edge. It now filters to just the requested keys, matching standard TinkerPop behavior; valueMap() with no arguments still returns everything.
  • The MCP memory_context tool returned neighbor entries with their body text still base64-encoded, while the entity's own body and every other memory tool already returned plain text. Neighbor bodies are now decoded consistently.
  • Every Gremlin valueMap()/values() call against an edge leaked a small internal iterator allocation. Found via a new regression test while fixing the key-filter issue above.

2026.07.31 — v0.24.3

v0.24.3

Fixed

  • A long-running server could eventually reject new connections with an internal MDB_BAD_RSLOT error after many client connect/disconnect cycles over time. The server now reclaims stale internal reader state on every new connection.

2026.07.30 — v0.24.2

v0.24.2

Fixed

  • valueMap() on edges could silently drop a custom property when it was the only one an edge had — has() and values() were unaffected and always returned it correctly.

2026.07.30 — v0.24.1

v0.24.1

Fixed

  • A Gremlin wire-protocol gap where results of a bytecode-submitted traversal (the standard way any real gremlin-driver client talks to AsanagiDB, as opposed to Gremlin Console's string-script mode) weren't wrapped in the Traverser envelope the wire protocol requires — causing driver clients to throw a cast exception on writes such as addV()/property()/.next(). Console and script-eval usage were unaffected.

2026.07.24 — v0.24.0

v0.24.0

Added

  • AsanagiLIS: --mcp-url flag to point tool calls at any AsanagiDB MCP server instead of a hardcoded local address.

Fixed

  • A GraphBinary type-handling gap where clients with no native integer type (like gremlin-javascript) serialize numeric IDs and counts as Double instead of Int/Long — silently broke V(id), E(id), hasId(), addE().to()/.from(), mergeE's endpoints, limit(), range(), skip(), tail(), and repeat().times(). Java and Go clients were unaffected.
  • containing(), startingWith(), endingWith(), and their not* variants were case-sensitive despite memory_search's own tool description promising fuzzy matching. Now case-insensitive (ASCII).

2026.07.20 — v0.23.0

v0.23.0

Added

  • Gremlin: range, skip, tail, hasKey/hasValue/hasNot, mergeV/mergeE, subgraph(), explain(), and profile().
  • Gremlin: map and list literal syntax ([key: value, ...], [a, b, c]).
  • asanagidb-admin shutdown-mcp / shutdown-lis — stop a running MCP or AsanagiLIS instance from the command line.

Fixed

  • A Gremlin injection vulnerability in the MCP server, closed across every affected call site.
  • addE().to(V(...)) silently not creating the edge for certain nested-call forms.
  • The MCP server could crash on an oversized single line over stdio; it now recovers instead of taking the whole process down.
  • memory_search / memory_list now return decoded text directly instead of raw base64.
  • Very large individual memory bodies could fail on import in rare cases; large values now chunk automatically.
  • Windows builds were broken by an in-progress graceful-shutdown change; fixed.
  • License activation now binds to the activating machine, closing an unauthenticated-downgrade path.