Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Dates are the release tag’s date (sdk-v* in KumihoIO/kumiho-SDKs). Entries are in descending version order, which is also descending date order.

../../RELEASE_NOTES.md is the release record: the same releases with the narrative — why a change mattered and what you have to do about it. This file is its terse companion. Entries belong in both.

[0.15.0] - 2026-10-29

Fixed

  • Item krefs in nested spaces and with dotted names (kref://p/a/b/x.k, kref://p/s/my.file.v2.k) are looked up as the kref names them by get_item_by_kref, get_item_from_revision, get_bundle_by_kref, kumiho.get_item, kumiho.get_bundle, Project.get_item, Project.get_bundle and Space.get_bundle: the parent path is everything before the last /, the item name everything before the last ..

  • get_bundle_by_kref re-fetches the bundle the kref names. It re-fetched under the text before the first dot (my.set.bundle came back as my.bundle).

Changed

  • Kref.get_kind() is the text after the last . (kref://p/s/my.file.v2.k is kind k, was file.v2.k).

  • An item kref with no kind raises ValueError before sending (kref://p/s.v1/x names a space), and so does a kind that contains / (Project.get_item("x", "image/png")): kinds containing / are not valid.

  • Requests built from a server-returned item kref whose space ends in whitespace, or that holds an empty trailing segment, keep the shape they had.

Added

  • parse_kref() and KrefParts — one parser for the kumiho-db kernel’s verdict and parts of a kref, and KrefParts.get_item_request() for the GetItem request. It never raises. The shared grammar and conformance corpus are in spec/kref/.

Upgrading

  • Code that derives an item name or kind from a kref: get_kind() of a dotted item name changed; take the stored kind from Item.kind, and the name without its kind from parse_kref(uri).item_name. See RELEASE_NOTES.md.

[0.14.4] - 2026-10-29

Changed

  • The mcp extra’s floor is raised from mcp>=1.10.0,<3 to mcp>=1.21.1,<3. pydantic 2.14.0 removed the private pydantic._internal._typing_extra.eval_type_backport, which every mcp from 1.2.0 through 1.21.0 imports at import mcp; with the newest pydantic those releases fail with ImportError and kumiho-mcp cannot start. mcp 1.21.1 dropped the import. The CI and publish floor legs now pin mcp==1.21.1. Installs pinned to mcp 1.10.0 through 1.21.0 will be upgraded.

Fixed

  • tool_memory_store_batch no longer loses the whole batch to one bad space hint. A hint the server refuses with INVALID_ARGUMENT (edge whitespace such as "alpha / beta", an empty segment such as "a//b") used to raise out of the per-capture space step and fail the call. It now becomes {"error": ...} for that capture alone and the other captures are written in the same batch. Every other failure there still raises, and hints that worked are sent unchanged: the batch path still does not slugify.

[0.14.3] - 2026-09-23

Changed

  • tool_memory_store batches direct provenance revision reads in windows of eight before creating their edges. Multiple direct revision references use batch_get_revisions; selectors, batch failures, and missing revisions retain the per-reference lookup fallback. Store calls without provenance are unchanged.

[0.14.2] - 2026-09-21

Added

  • memory_project and memory_revision_limit on kumiho.search() and Client.search() — additive Search request fields. A supporting server validates the named project (exact, non-deprecated, under the authenticated tenant) and attaches each leading hit’s current revision — published, else latest — to the result. SearchResult gains memory_revision and memory_revision_resolved, and the returned page carries memory_project_validated. memory_revision_limit (default 100) is sent only when memory_project is set.

  • Client.close() — releases the client’s gRPC channel once every borrower is finished, so a pool that retires clients can close their channels.

Changed

  • tool_memory_retrieve(..., include_resolved_metadata=True) uses search packets for a query in search and latest mode without unroll_revisions. When the server acknowledges memory_project_validated, the separate project lookup is skipped, and only hits whose packet was not hydrated go through the 0.14.1 batch resolution. A hit the server resolved to no accessible revision is not fetched again. An older server ignores the new fields and sends no acknowledgement, so the project check and the batch path run as before; a missing project returns the same error either way. Ranking, metadata, type/space filters, latest ordering and the pattern fallback are unchanged.

  • python/proto is pinned to the kumiho-proto commit that adds the Search fields, and the Python stubs are regenerated with the same protobuf 6.31.1 toolchain as 0.14.0.

Notes

  • Deploy a server that supports the packets before clients rely on them. Search and Evaluate stay separate in the memory layer: graph and sibling processing still runs between them, so evaluation never sees a partial candidate set.

[0.14.1] - 2026-09-21

Added

  • include_resolved_metadata on tool_memory_retrieve — internal and opt-in; the kumiho_memory_retrieve MCP schema is unchanged. The response gains resolved_metadata, keyed by the exact revision kref and limited to the final results, each entry carrying metadata, created_at and tags, so the memory layer does not fetch the same revisions again.

  • Batched tag resolution on that path. In-scope search hits are resolved with batch_get_revisions in chunks of at most 100 items: published first, then latest only for items that have no published revision. It does not apply with unroll_revisions. If the batch call fails, the per-item resolution runs instead and batch attempts are suppressed for 60 seconds on that client.

  • MCP annotations for six kumiho-memory tools: kumiho_memory_record_experience, kumiho_memory_record_outcome, kumiho_memory_prepare_patterns, kumiho_memory_store_pattern, kumiho_memory_check_pattern and kumiho_memory_validate_insight_response. The hosted connector’s tool allowlist is unchanged.

Notes

  • A caller that does not pass the flag gets the same ranking, filters and response shape as 0.14.0.

  • The batched path needs a server with the current-tag batch resolution fix.

[0.14.0] - 2026-09-19

Added

  • kumiho.evaluate(query, fragments, questions, ...) and Client.evaluate(...) — judge prepared text fragments against caller-supplied questions using a server-managed evaluation provider. It is a ranking step over candidates the caller already holds, not a search: it takes no kref and it never reads, writes or tags the graph. Keyword arguments are extra_context, mode ("", "batched", "per_fragment"), rubric_version, timeout_ms and allow_cache. timeout_ms sets both the server’s deadline hint and this call’s gRPC deadline, the latter with a two-second margin so the server’s own answer — including a non-OK status — wins the race against DEADLINE_EXCEEDED.

  • Value types in kumiho.evaluation, re-exported from kumiho — EvaluationFragment, EvaluationQuestion, EvaluationResult, FragmentEvaluation, EvaluationUsage, the EvaluationAnswer union and its members NoulAnswer, ChoiceAnswer and ScoreAnswer, all frozen dataclasses. Fragments and questions are accepted as these types or as plain mappings; both build the same request. EvaluationResult.by_id() keys the per-fragment results by the caller’s own fragment id.

  • Fragment ids stay on this side of the wire. What leaves the server for the provider is the query, extra_context, each question’s instructions and criteria, and each fragment’s text and metadata. Ids are replaced with the server’s own private labels, and the literal {fragment} placeholder in instructions passes through untouched for the server to render.

  • Client-side validation stops an obviously bad call before it costs tokens: a non-empty query, non-empty unique fragment ids, a known question type, and no __ in a question id, which the server reserves for its per-fragment ids. Shape and size limits are left to the server, the only side that can judge them. Mode and question type are translated here rather than passed through, because a typo in either would otherwise reach the server as the zero value and silently change what the call does. Statuses are derived from the enum name in the other direction, so a status this SDK predates reports "unspecified" rather than raising.

  • Evaluate in the generated Python stubs, regenerated from kumiho-proto with the same grpcio-tools 1.76.0 / protobuf 6.31.1 the checked-in gencode headers name.

Notes

  • Evaluation is a Kumiho Cloud feature on paid tiers. A self-hosted CE server does not implement the RPC and answers UNIMPLEMENTED; a tenant without the entitlement gets PERMISSION_DENIED, or a "not_entitled" result when the server answers in-band. Both surface as grpc.RpcError, the way every other RPC’s failures do.

  • There is no MCP tool for evaluate. The memory layer is its caller, not an end user.

[0.13.2] - 2026-09-18

Added

  • item_kref on tool_memory_store, and "item_kref" per capture on tool_memory_store_batch — the memory this store revises, given as an item kref or a revision kref (selectors are stripped). A correction knows what it corrects, so nothing is inferred: the similarity search is skipped, the new revision is created on that item, space_path/space_hint no longer decide placement (the item’s own space does, and it is what metadata["space"] records), and the item’s existing bundle membership is left alone. An unresolvable kref is an error — never a fall back to stacking or to a new item. The result has the shape of a stacked store: stacked true and previous_revision_kref pointing at the item’s published revision, or its latest one when it had never been published. Batch rows gain previous_revision_kref on this path; they had no such field.

  • The published tag moves with the correction, and only then. When the named item already had a published revision, the caller’s tags are applied first and published last — the server freezes a published revision and rejects tags applied after it. An item with no published revision is not published. A failing published call is returned as an error on this path (it is the operation the caller asked for), while the default path keeps swallowing tag failures as before. item_kref is not in the kumiho_memory_store MCP schema; kumiho-memory’s reflect is its caller.

Fixed

  • space_paths leaked items from same-prefixed spaces. The server’s context_filter is a plain string prefix, so space_paths=["9miho"] returned project-root items whose name begins 9miho-, and ["work"] returned items from work-infra. tool_memory_retrieve now checks each result’s own space path-segment-wise against the requested contexts — on the search, bundle, listing and latest paths alike — keeping genuine sub-spaces and dropping the lookalikes. The same check guards the stacking search, so a store can no longer displace a published revision in a space the caller never addressed.

  • mode="latest" could starve the item it exists to find. The walk treated Item.modified_at as an upper bound on revision dates and stopped early once limit results were newer than the next item’s bound. That is only sound if the bound holds for the items it never resolves — and a server whose modified_at does not track revisions hides exactly those: an item below the stop point is never resolved, so it never disproves the bound, so it never comes back. There is no early stop now. The bounded window is unchanged: the max(limit * 4, 20) items with the newest modified_at (falling back to item created_at) are resolved, and the results are ordered by their revision’s own created_at.

  • mode="first" could resolve the whole project. When the memory_types filter matched nothing, the listing fallback walked every scoped item at 1-2 RPCs each (2,157 resolutions measured). It is bounded by the same max(limit * 4, 20) window as the other modes.

  • Mode spellings with spaces or hyphens fell through to search. mode is now lowercased, stripped, and runs of spaces and hyphens folded to _ before the alias lookup, so "most recent" and "Most-Recent" select latest.

  • _most_recent_items dropped tzinfo instead of converting. It now uses the same _ordering_timestamp normalization as the other ordering paths, so mixed UTC offsets compare correctly.

Removed

  • An unreachable widen-to-the-whole-project fallback in tool_memory_retrieve (not results and contexts != [project_name] and not spaces). contexts differs from [project_name] exactly when spaces is non-empty, so the two conditions could never both hold. The scoped listing above it already covers the unscoped case.

Notes

  • Nothing is published on the store’s own initiative. published moves only when a caller names a specific item to revise and that item already had a published revision; the tag is carried forward onto the replacement, never created. A store with no item_kref behaves exactly as in 0.13.1, including the long-standing tags or ["published"] default for an untagged new memory.

  • Downstream: kumiho-memory’s kumiho_memory_reflect gains a revises capture field that passes item_kref through (separate PR). The hosted connector picks both up when its pins move.

[0.13.1] - 2026-09-17

Fixed

  • kumiho_memory_retrieve mode="latest" behaved as search. The schema advertised it, but tool_memory_retrieve had no branch for it: with a query results came back relevance-ranked, and without one in item-creation order, so a memory updated by a newer stacked revision never moved forward. It now orders newest first by the created_at of the revision returned for each item. With a query, relevance search picks the candidates (the top max(limit * 4, 20) hits) and date orders them; scores are kept, unsorted. Without a query, items are walked by modified_at with an early stop and a cap of the same size on revision resolutions. space_paths, memory_types, bundles and unroll_revisions are honoured. "newest", "recent" and "most_recent" are accepted as aliases.

  • mode="first" ignored the query and space_paths. It listed the whole project and returned its oldest item, although auto-detect selects it only when a query is present. It now searches the scope contexts with no cross-space fallback. With a query, it returns the oldest by item created_at among the top max(limit * 4, 20) relevance hits that pass memory_types, falling back to the scoped listing as the other modes do. Without a query, it walks the scoped items oldest first as before. It still returns at most one result with the same keys. A revision-less item no longer satisfies a memory_types filter.

  • spaces_used was never filled from search hits. The search loop read item.space.path; Item.space is a str, and the swallowed AttributeError left the list empty. Returned search hits now report their space in project-prefixed form ("CognitiveMemory/personal", or the project name for a root item), deduped. First mode reports the returned item’s space instead of the project name.

Added

  • created_at on mode="latest" results — a list aligned with revision_krefs (ISO strings, null when a revision has none). Other modes’ results are unchanged.

  • Item.modified_at, from the ItemResponse field of the same name the SDK never read. None when the server does not report it.

Changed

  • The kumiho_memory_retrieve description and its mode description now say what each mode does.

Notes

  • spaces_used is a deduped list, not aligned with revision_krefs. Clients that read spaces_used[i] as the i-th result’s space were relying on an accident: the list was empty for search hits. They should derive the space from each result’s kref. The openclaw client in kumiho-plugins is being fixed.

[0.13.0] - 2026-09-04

Added

  • kumiho.request_context — RequestContext, current_request(), request_context() and hosted_mode(). A contextvars-carried per-request identity (tenant, user, token, session) for deployments where one process serves many tenants. asyncio.to_thread copies the context, so it follows a request across the async/sync boundary without being threaded through every call site. RequestContext, current_request and hosted_mode are re-exported from kumiho; the context manager is reachable as from kumiho.request_context import request_context or as kumiho.use_request_context — re-exporting it under its own name would shadow the submodule, since a submodule and a package attribute share one namespace and import kumiho.request_context as rc resolves through getattr, not sys.modules.

  • create_mcp_server(profile=..., instructions=...) — profile="connector" exposes a curated 18-tool surface for the hosted Claude connector; None or "full" keeps today’s whole tool list, which is what the stdio plugin gets. Falls back to KUMIHO_MCP_TOOL_PROFILE. An unrecognized name raises ValueError naming the valid profiles rather than silently serving everything — a typo in a deployment’s environment would otherwise publish every destructive tool to a public connector.

  • kumiho.mcp_server.TOOL_ANNOTATIONS — MCP tool annotations (title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint) for all 63 tools, the kumiho-memory ones included. Applied on both the mcp 1.x decorator path and the 2.x on_* path, with Tool.title and ToolAnnotations detected by introspection so an older SDK degrades to unannotated tools instead of failing to construct.

  • kumiho.mcp_server.ToolNotInProfileError — raised by call_tool when a client asks for a tool the active profile withholds, so the refusal reaches the client as a real MCP tool error (isError: true) rather than a successful result whose text merely contains the word “error”. Clients and models branch on isError; a refusal that reports success reads as “the call went through”. mcp 1.x turns the raise into an error result on its own, and the 2.x branch catches the type and builds the same one.

  • kumiho.mcp_server.CONNECTOR_INSTRUCTIONS — the engage/reflect protocol as server instructions, returned in the MCP initialize result for the connector profile. A remote connector has no skill and no hooks, so this is the only channel the protocol has.

  • KUMIHO_STACK_MIDDLE_BAND — set to 0 to run the revision-stacking gate in strong-only mode, where a capture stacks only when its score clears the 0.75 strong threshold and the lexical floor; the 0.55 type-match band is withheld. Default is unchanged (two-band). Every kumiho_memory_store and kumiho_memory_store_batch result also reports stack_mode ("two-band" or "strong-only") next to stack_score / stack_runner_up / stack_overlap, so per-tenant telemetry can say which gate produced the number.

Changed

  • The MCP server’s process-global caches are keyed by tenant. _project_cache, _known_spaces, _bundle_cache and _space_registry_cache were keyed by project name alone. Two tenants routinely have a project called CognitiveMemory, and the cached value is a live handle bound to one tenant’s client and credentials.

  • Hosted mode never mutates os.environ. The auth_token argument to kumiho_search_items / kumiho_fulltext_search used to be published into KUMIHO_AUTH_TOKEN; hosted, that is a credential swap visible to every other in-flight request, and a persistent one. It is now ignored (with a warning) when a request context is active or KUMIHO_MCP_HOSTED=1. Unchanged locally.

  • Hosted mode never reads ~/.kumiho. _ensure_configured() raises instead of falling back to auto_configure_from_discovery() when no request-scoped client is bound: the fallback would serve the operator’s own graph to a remote caller. Local memory-artifact writes are likewise a no-op when hosted — the root is on the server’s shared disk and the recorded path resolves for nobody.

Notes

  • Hosted deployments run with KUMIHO_STACK_MIDDLE_BAND=0. The two-band gate was calibrated on one corpus. A shared multi-tenant server has not measured its own score distribution, and a middle-band false positive moves the published tag onto an unrelated item — which every recall path then resolves first, so the displaced memory disappears from the default retrieval surface without anything reporting it. Strong-only keeps stacking for near-duplicates and withholds the contested band until the stack_mode / stack_score telemetry says a tenant’s distribution supports turning it back on. The stdio plugin keeps the two-band default.

  • The stdio plugin path is unchanged in behavior: the default create_mcp_server() still exposes every tool, with the same names and schemas. Tools now additionally carry title and annotations, which the plugin benefits from as much as the directory does.

  • Two annotations deliberately disagree with the connector plan’s §2.2 hint columns, because the tools disagree with them: kumiho_memory_space_profile persists versioned profile items unless dry_run is set (so it is not read-only), and kumiho_memory_dream_state applies deprecation (so it is destructive). space_profile keeps its place in the connector profile; only the honesty of its hints changed.

  • kumiho_memory_dream_state is annotated but withheld from the connector profile for v1. Its assessment pass needs an LLM key and hosted tenants are keyless (plan §1.10), so listing it would publish a tool that fails at call time — which directory review catches head-on, since it asks the submitter to confirm every listed tool has been run. The full profile still serves it.

[0.12.2] - 2026-09-02

Fixed

  • Revision stacking in kumiho_memory_store never fired. The 0.92 fuzzy threshold sat above the scorer’s ceiling: an item scores 0.72-0.83 against its own exact title, so no input could ever stack and every capture minted a new item. The gate is now a lexical-overlap floor (token Jaccard >= 0.17 over Latin words and CJK bigrams, refusing texts under 8 tokens) combined with two score bands (>= 0.75 alone, or >= 0.55 with matching memory_type), calibrated on 17 labelled pairs from a live graph that are pinned as tests. The search now uses title and summary, is capped at 180 characters with a title-only retry (long CJK queries hit Lucene’s 1024-clause limit), and logs failures at warning instead of debug.

  • Dart EdgeType.isValid rejected valid types. It checked membership in a seven-item list rather than the regex every other SDK uses, so SUPPORTS, PRODUCED_BY and MIGRATED_FROM returned false. Constants added; isValid now delegates to isValidEdgeType.

Added

  • stack_score, stack_runner_up and stack_overlap on every kumiho_memory_store and kumiho_memory_store_batch result, reported whether or not the capture stacked, so a caller can tell a broken search from a near-miss.

  • The 21-file python/tests/ suite is now collected by CI (moved under python/python/tests/), together with the kumiho-cli tests; a layout guard fails the build if a test directory under python/ is not run by any job.

Removed

  • python/.github/workflows/: dead copies that GitHub never read and that documented a stale version gate.

[0.12.1] - 2026-09-02

Added

  • SUPPORTS is reachable from kumiho_create_edge — the tool’s edge_type enum listed 8 of the 10 EdgeType members. The enum is enforced by jsonschema.validate in the MCP dispatcher, so the omitted types could not be written through this tool at all, even though EdgeType defines them, __init__ re-exports them, validate_edge_type accepts them, and the proto field is a plain string.

  • SUPERSEDES and SUPPORTS are now listed in kumiho.__all__, matching the aliases that were already defined.

Changed

  • The kumiho_create_edge description and the MCP docs now state the direction of each type rather than naming only the four creative-provenance ones.

Notes

  • SUPERSEDES is deliberately still withheld from both edge tools. Belief revision is a protocol rather than a lone edge: its producers also demote the superseded revision and ripple grounding staleness to dependents. A bare edge write performs only part of that, so explicit belief revision belongs in the memory layer. kumiho_delete_edge keeps the vocabulary it shipped with, since edge deletion has no repair path.

[0.12.0] - 2026-08-13

Added

  • Creative Project lifecycle APIs — Projects now expose metadata, archived listing and restoration, deletion-impact analysis, deletion guards, external reference resolution, Item moves, and snapshot-bound permanent deletion.

  • Space metadata support — Space creation and metadata updates can carry application-defined display labels without changing canonical identity.

  • Additive hard-delete RPC — hard_delete_project() uses the new confirmation and impact-snapshot contract while the established delete_project(project_id, force=False) signature remains available.

Changed

  • Generated protobuf and gRPC bindings now target the Project lifecycle contract shipped by kumiho-server 1.7.0.

  • Archived canonical Project names are reserved for identity-safe restoration. Creating another Project with the same canonical name returns a conflict.

[0.11.0] - 2026-08-01

Added

  • mcp 2.x support — kumiho[mcp] now runs on both mcp 1.x and mcp 2.x. mcp 2.0.0 removed the low-level Server handler decorators and replaced them with on_* constructor keywords; the six handlers are registered through whichever shape the installed SDK provides, selected by capability detection rather than a version number so editable installs, forks and vendored copies resolve correctly. Capabilities, wire format and tool behavior are identical on both majors.

  • Tool input validation on the 2.x path — mcp 1.x validated tool arguments against each tool’s inputSchema before dispatch and mcp 2.0’s low-level path does not, so the SDK now performs that check itself. A schema-violating call is still rejected with Input validation error: ... rather than reaching the handler.

Fixed

  • kumiho[mcp] installed a server that could not start. The mcp extra declared mcp>=1.0.0 with no upper bound, so once mcp 2.0.0 published, every fresh install resolved to it and create_mcp_server() raised AttributeError: 'Server' object has no attribute 'list_tools' at construction (KumihoIO/kumiho-SDKs#145).

  • resources/read had never worked, on any version: the handler assumed a str URI but MCP passes a pydantic AnyUrl, so every read raised AttributeError on its first line (#146). Resource bodies now also keep their declared application/json content type instead of being served as text/plain, and the project name is percent-decoded — mcp 1.x escapes non-ASCII when an AnyUrl is stringified and mcp 2.x does not, so without decoding a Hangul or spaced project name resolved on one major only.

  • serverInfo.version reported the mcp SDK’s version as kumiho’s under mcp 1.x, and would have reported an empty string under 2.0 (#147). It now reports kumiho’s own version.

Changed

  • The mcp extra is now bounded at both ends: mcp>=1.10.0,<3. The floor is the oldest release where every assumption in the code actually holds — mcp.server.lowlevel.helper_types landed in 1.3.0 and the call_tool decorator’s validate_input in 1.10.0, below which the 1.x path would silently skip tool-argument validation. Installs pinned below mcp 1.10.0 will be upgraded. CI now runs the suite against the declared floor and both majors, so a future major bump fails the build rather than reaching users.

  • jsonschema is declared directly in the mcp extra, since the SDK now imports it rather than relying on it transitively.

[0.10.8] - 2026-07-15

Fixed

  • MCP server orphan hardening — kumiho.mcp_server now exits when its launching ancestor chain dies: event-driven on Windows (a watchdog thread blocks on the ancestor process handles via WaitForMultipleObjects), ppid-reparent polling on POSIX. On Windows, MCP clients restart sessions by terminating the launcher process, which does not kill its children — and because a venv’s Scripts\python.exe is a redirector stub that runs the base interpreter as a separate child, the real server is a grandchild or deeper, so the whole contiguous python-named ancestor chain plus the client is watched, not just the direct parent. The stranded python -m kumiho.mcp_server processes previously accumulated without bound (KumihoIO/kumiho-plugins#25). Additionally, main() now hard-exits once the stdio transport closes, so lingering non-daemon threads (thread pools, gRPC channels) can never keep a dead server alive. Opt out with KUMIHO_MCP_DISABLE_ORPHAN_WATCHDOG=1.

[0.10.7] - 2026-07-15

Added

  • tool_memory_store_batch — the bulk counterpart of tool_memory_store for the MCP write path. N captures land in one batch_create_revisions transaction (removing the neo4j relationship-group deadlock that per-capture concurrency triggers, and collapsing the heaviest create/revision writes) while preserving every per-capture semantic of the single path: credential screening, space resolution, fuzzy-stack, event_date/metadata, tags, topic bundle, and DERIVED_FROM edges (tag/bundle/edge stay per-item — the server has no batch RPC for them). kumiho_memory_reflect routes ≥2-capture writes through it; a single capture keeps the byte-identical per-capture path.

[0.10.6] - 2026-07-15

Added

  • Batch revision creation — batch_create_revisions(revisions, idempotency_prefix=...) writes up to 200 captures (item + revision + optional artifacts) in a single server transaction, returning positional (results, failures). Missing items are auto-created from each row’s item_kref; rows targeting the same item stack in order (last becomes latest); per-row artifacts can mark one "default": True so the chain resolves straight from the item kref; a stable idempotency_prefix makes re-submission a safe no-op. Requires kumiho-server >= 1.6.3.

[0.10.5] - 2026-07-11

Added

  • kumiho._text.slugify() — one canonical slug helper shared by the SDK and kumiho-memory, so a fix (Unicode handling in particular) cannot land in one copy and silently miss another. \w is Unicode-aware, so Hangul, CJK and Cyrillic names slug to themselves rather than to the empty string, matching the kref path segments the server accepts. Optional hash_on_truncate appends a short digest of the full normalized string so two long names sharing a prefix keep distinct slugs.

  • MCP space registry — the MCP server records space aliases and resolves space hints against a short-lived per-project registry of existing space paths, with stem matching, so a near-miss space name resolves to the existing space instead of creating a near-duplicate.

[0.10.4] - 2026-07-03

Fixed

  • memory_type never round-tripped — the server reserves the type metadata key, which made the memory_types filter dead code (#21).

  • Interactive login prompt inside headless processes — the SDK could open a login prompt in a process with no console, hanging the MCP server indefinitely (#22). Both fixed in #23.

[0.10.3] - 2026-07-03

Fixed

  • Memory-retrieve RPC storm (#20) — search now retries shallow when include_revision_metadata=True returns nothing, and the pattern-fallback and bundle-expansion loops are bounded at limit * 2. This removes the ~185s MCP timeout on unscoped recall against large cloud projects.

[0.10.2] - 2026-07-03

Fixed

  • __version__ drift left over from 0.10.1 — kumiho/__init__.py was never bumped when pyproject.toml went to 0.10.1, so the published wheel’s metadata correctly said 0.10.1 while kumiho.__version__ still read "0.10.0" at runtime.

Added

  • tests/test_version.py asserts kumiho.__version__ matches pyproject.toml, so this class of drift fails a test instead of silently shipping again.

[0.10.1] - 2026-07-03

Fixed

  • tool_memory_store never applied tags — it called a nonexistent module-level kumiho.tag_revision(...) instead of the revision.tag(...) method, and a bare except swallowed the failure. No tag, including the default published tag, was ever actually applied through this path, which broke Dream State’s published-revision deprecation protection for every consumer relying on the default store backend.

[0.10.0] - 2026-06-17

Added

  • Full-text fuzzy search — search(query, ...) returns ranked items (SearchResult with item, score, matched_in), with automatic typo tolerance.

  • Semantic revision scoring — score_revisions(query, revision_krefs) scores revisions against a query using server-side embeddings and/or fulltext.

  • Batch revision fetch — batch_get_revisions(revision_krefs=..., item_krefs=..., tag=...) fetches many revisions in a single call, returning (revisions, not_found).

  • By-kref accessors — get_artifact_by_kref(), get_bundle_by_kref(), and client.get_item_from_revision().

Changed

  • The advanced event_stream() parameters (cursor, consumer_group, from_beginning) and get_event_capabilities() are now generally available.

  • The C++ and Dart SDKs now have full feature parity with the Python SDK.

[0.9.24] - 2026-04-17

Fixed

  • Unicode kref path segments — Kref rejected non-ASCII letters in path segments even though the server accepts them, so a Hangul or CJK space or item name could not be addressed from the SDK.

[0.9.23] - 2026-04-17

Changed

  • gRPC reliability hardening — a per-RPC default deadline, so a call can no longer hang indefinitely against an unresponsive gateway.

  • Recall defaults to summarized mode, and summarized recall skips sibling unrolling.

[0.9.22] - 2026-04-02

Fixed

  • tool_memory_retrieve accepts a memory_types parameter, which the tool schema had omitted.

[0.9.21] - 2026-04-02

Added

  • kumiho_batch_get_revisions MCP tool — exposes the SDK’s batch revision fetch to MCP clients, replacing N serial get_revision calls.

[0.9.20] - 2026-03-15

Fixed

  • Dream State consolidation returned data the ingest path could not use. The consolidation and Dream State responses are now shaped correctly for ingest, and the OpenAI response object is parsed as JSON rather than passed through as an object.

[0.9.19] - 2026-03-10

Added

  • Per-call auth_token on the search tools, enabling cross-project search without rebuilding the client.

[0.9.18] - 2026-03-10

Fixed

  • assistant_text removed from required in the kumiho_memory_store schema; it was never mandatory to the handler, so the schema rejected valid calls.

[0.9.17] - 2026-03-09

Added

  • TransientRetryInterceptor — retries transient gRPC failures, so a gateway restart no longer surfaces as a hard error to the caller.

[0.9.16] - 2026-03-08

Fixed

  • Dream State replaced its event-stream collection with a revision query, decoupled its collection window from the gRPC deadline, and handles DEADLINE_EXCEEDED gracefully instead of aborting the pass.

[0.9.15] - 2026-03-07

Fixed

  • The chat tool handlers respect the client’s project parameter, and the replay tier gate was removed.

[0.4.0] - 2025-12-03

Added

  • Event streaming cursor support: Event.cursor attribute for resumable streaming

  • EventCapabilities API: get_event_capabilities() to query tier-based streaming features

  • New event_stream() parameters:

    • cursor: Resume from last position (Creator+ tiers, Coming Soon)

    • consumer_group: Load-balanced consumption (Enterprise tier, Coming Soon)

    • from_beginning: Replay entire buffer (Creator+ tiers, Coming Soon)

  • Tier capability documentation with Coming Soon markers

Changed

  • Updated event streaming documentation with tier matrix

  • Event object now includes cursor attribute (None for Free tier)

Notes

  • Creator tier and above streaming features are planned but not yet deployed

  • Free tier provides real-time streaming without persistence

[0.3.0] - 2024-XX-XX

Added

  • Comprehensive Google-style docstrings for all public APIs

  • Sphinx documentation with ReadTheDocs theme

  • get_artifact() top-level function for fetching artifacts by Kref

  • get_artifact_by_kref() method in Client class

  • Type hints throughout the codebase

Changed

  • Updated pyproject.toml with full PyPI metadata

  • Improved error messages with more context

Fixed

  • Kref parsing for artifact URIs with special characters

[0.2.0] - 2024-XX-XX

Added

  • Event streaming support with stream_events()

  • Link traversal for lineage tracking

  • Batch operations for multiple artifacts

Changed

  • Switched to context-variable-based client management

  • Improved connection pooling for gRPC channels

[0.1.0] - 2024-XX-XX

Added

  • Initial release

  • Core entity classes: Project, Space, Item, Revision, Artifact, Edge

  • Kref URI parsing and generation

  • Discovery-based authentication

  • CLI authentication tool (kumiho-auth)