Skip to content

0.13.3 - 2026-08-22

Choose a tag to compare

@github-actions github-actions released this 22 Aug 00:49
09bdf2c

Release Notes

A patch release closing the upgrade-path regression 0.13.2 introduced, scoping the last two
ontology-driven maintenance operations to a single group, and adding per-group ontologies. The group
boundary work that began in 0.13.0 is now consistent across reads, writes, deletes and maintenance:
an operation names the group it acts on, and touches nothing else.

Fixed

  • migrate_wal_root_if_needed now stamps a generation for the legacy flat WAL it migrates. A
    legacy flat WAL (.lcg/wal/*.jsonl, pre-0.13.0) predates generation identity (#387) entirely,
    and migration now assumes it is locally owned (an assumption, not a proof — see #431's
    Assumptions section), minting one for the destination group as part of the same relocation —
    the same act WalWriter::new performs for any other stream
    created with no prior content. This closes the gap without weakening #414's refusal for any
    other reason a stream might arrive with no generation (e.g. a publish step that dropped the
    dot-namespace): the new call is scoped strictly to the exact directory this migration just
    relocated content into, never a general sweep over every group. knowledge_status now reports
    a non-null generation and generation_status: "known" for a freshly migrated group. See
    ADR-0414's amendment note. (#431)

  • knowledge_rebuild_from_wal's unknown-generation refusal message now names both possible
    remedies.
    The two situations that produce this refusal — a received stream whose sidecar was
    stripped, and a workspace migrated by a binary older than this fix — are indistinguishable on
    disk, so the message can no longer assume which one applies. It now states both: republish the
    stream's full directory if it came from a publisher, or hand-create .wal-generation.json for a
    local workspace with no publisher. (#431)

  • knowledge_canonicalize_relations and knowledge_backfill_relation_types now require a
    group_id and are fully group-scoped.
    Both previously selected RelatesToNode_ candidates
    database-wide with no group filter and flushed every mutation to the default group's WAL
    stream, regardless of which group's data they actually touched. On a multi-group workspace, the
    correct, intended use of either operation — canonicalizing the one group a node owns — rewrote
    every co-resident group's edges as a side effect and misattributed the resulting mutations to
    the default group's stream. This is the same failure class as #368/#406 (cross-group mutation)
    and #385 (WAL misattribution), previously left as a documented exception for these two
    operations. group_id is now required from the outset — omitted, null, or empty is rejected
    rather than falling back to a database-wide rewrite or the default group. No known deployment
    invoked either operation before this fix, so the required parameter breaks no existing caller.
    See ADR-0378's FR-004 section and ADR-0385's Context section, both amended by this issue. (#447)

  • The legacy .graphiti → .lcg workspace migration now honours LCG_WAL_DIR /
    GRAPHITI_WAL_DIR.
    It always moved .graphiti/wal to a hardcoded .lcg/wal, so a workspace
    configured with a custom WAL root had its legacy content land somewhere the service would never
    read — the WAL was intact on disk and invisible to the process. The move now targets the resolved
    WAL root, handles a destination on a different filesystem (a custom root often is), and merges into
    a root that already has content rather than failing. (#442)

Changed

  • BREAKING: group_id is now a required, non-empty parameter on
    knowledge_canonicalize_relations and knowledge_backfill_relation_types, on both the MCP and
    IPC surfaces.
    The MCP tool schemas for both methods move group_id from optional into
    required. A caller that previously omitted group_id (absent, null, or empty) got a
    successful — and, per the ### Fixed entry above, cross-group — rewrite; it now receives an
    error naming the missing parameter instead, and no rows are read or written. The remedy is to
    pass the caller's own group explicitly; there is no default to fall back to, because a silent
    default (the default group) is the defect this release fixes. Unlike #406's equivalent change,
    no known deployment invokes either operation today, so this breaks no existing caller in
    practice — see the issue's Release timing discussion. (#447)

Added

  • Per-group ontology support. A group_id can now have its own extraction/validation
    vocabulary, independent of every other co-resident group in the same workspace. Place a
    group-specific ontology at {workspace}/.lcg/ontology/<group_id>.yaml (using the existing
    ontology YAML format); a group_id unsafe as a bare filesystem path component is
    percent-encoded with the same bijective scheme already used for per-group WAL directory names.
    A group with no per-group file falls back to the existing workspace-wide .lcg/ontology.yaml,
    exactly as before this feature — a workspace that hasn't adopted per-group ontologies behaves
    identically to pre-0.14.0. The resolved per-group ontology governs, for that group only,
    extraction guidance, mode: strict validation, canonicalization, and reprocessing
    (knowledge_reprocess_entity_types, knowledge_reprocess_relation_types). A malformed or
    unreadable per-group file falls back to the workspace-wide ontology when one exists, or to no
    ontology otherwise (logged either way), rather than failing the group's extraction outright.
    Direct-assert
    (knowledge_assert_entity/knowledge_assert_relationship) is unaffected, as before. When a
    group's stream is published, the ontology that guided its extraction now travels alongside it
    as .wal-ontology.json — a new, purely informational addition to the publish contract (see
    Operations): a consumer can inspect it as documentation, but it is never
    applied to the consumer's own extraction, validation, canonicalization, or reprocessing, and its
    absence never affects replay or correctness. See Ontology
    for the full resolution/fallback contract. (#446)
  • knowledge_status reports a new hydration_status field, alongside the existing
    applied_seq/max_seq values, in both the flat wal object and every wal_groups[*] entry:
    "hydrated" (the database is caught up with its WAL), "wal_ahead" (the WAL holds content the
    database has not applied — e.g. a wiped or fresh database beside a populated WAL directory), or
    "not_applicable" (the group has no WAL content at all). Previously, a genuinely empty group and
    a group whose WAL was simply ahead of the DB were indistinguishable unless a caller manually
    compared applied_seq against max_seq itself. Purely additive — applied_seq/max_seq are
    unchanged, and health_check's healthy/degraded determination is unaffected. (#456)

Internal

  • The required CI test gate could not fail. The test job piped cargo test through tee
    without pipefail, so the pipeline reported tee's status and a failing suite still went green.
    (#430)
  • Four tests that had been failing behind that masked gate were fixed once it started reporting
    honestly — stale fixtures and drifted assertions, not new breakage. (#429)
  • Startup migration ordering is documented and regression-tested. The .graphiti → .lcg move
    must precede the per-group WAL relocation, or a .graphiti-era workspace leaves its WAL files
    loose and invisible. The ordering was already correct via the call graph — it was diagnosed as
    broken from textual line order — so this hardens an implicit dependency with explicit
    preconditions and un-quarantines the regression test #430 had parked. (#437)
  • Socket-connectability is documented as not a readiness signal. The socket binds before the
    database opens, deliberately, so recovery IPC stays reachable in degraded mode (ADR-0009); the
    correct signal is a health_check round-trip reporting healthy, which cannot be true until
    after migration. (#436)
  • wal_root_migration's legacy-upgrade acceptance test now runs in CI. It drives the real
    74MB/12,481-seq fixture through migration and asserts parity with 0.13.1's rebuild, and had run
    only when invoked by hand — while five defects accumulated on the path it guards. (#460)
  • The real-corpus fixture's group_id now matches the WAL directory it migrates into. It was
    captured under a non-default group while committed in the flat pre-0.13.0 layout, so its content
    and directory disagreed — a shape no deployment has, which was nonetheless read as a product
    defect. (#469)

lcg-eval 0.13.3

Install lcg-eval 0.13.3

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/verveguy/liminis-context-graph/releases/download/v0.13.3/lcg-eval-installer.sh | sh

Download lcg-eval 0.13.3

File Platform Checksum
lcg-eval-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
lcg-eval-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
lcg-eval-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

lcg-service 0.13.3

Install lcg-service 0.13.3

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/verveguy/liminis-context-graph/releases/download/v0.13.3/lcg-service-installer.sh | sh

Download lcg-service 0.13.3

File Platform Checksum
lcg-service-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
lcg-service-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
lcg-service-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum