Skip to content

Releases: wandercom/kindex

v0.36.1

Choose a tag to compare

@blast-hardcheese blast-hardcheese released this 10 Sep 22:40
8fe3225

What's Changed

New Contributors

Full Changelog: v0.36.0...v0.36.1

Kindex v0.36.0

Choose a tag to compare

@jmcentire jmcentire released this 03 Sep 03:07

Kindex v0.36.0 closes the session-lifecycle and Dream-safety work from #19/#20 and hardens the schema transition around it.

Highlights:

  • Paused sessions can be reactivated for the exact canonical project; completed, unlinked sessions become eligible for reversible slow-graph archival after 60 days.
  • Semantic metrics exclude lifecycle nodes and legacy Dream domain-clique edges and advertise metrics_schema: 2.
  • Dream stages bounded, reviewable domain links and suppresses repeated resolved pairs and redundant deep summaries.
  • Schema v12 creates and validates an owner-private recovery snapshot before migration, serializes concurrent migrators through a cross-platform SQLite lock, preserves duplicate sessions as paused history, and exposes the recovery path through kin status.
  • Suggestions persist title-versus-node-ID identity and refuse ambiguous title resolution.
  • Archive cycles report IDs found in both fast and slow stores after an interrupted move without guessing which copy is disposable.
  • Release metadata and docs/site mirrors are mechanically checked for drift.

Upgrade warning: stop every Kindex daemon, MCP server, and older CLI process before upgrading. Do not open a migrated schema-v12 database with v0.35.x; restore the recovery snapshot (moving the live -wal and -shm sidecars aside) before running older code.

Verification: 2,012 tests, wheel/sdist build, clean-room wheel/CLI/MCP installation, official MCP Registry metadata validation, a migration proof from the published kindex==0.35.0 package, Simulacrum review, and multiple seven-persona Advocate passes.

Full details: https://github.com/jmcentire/kindex/blob/v0.36.0/CHANGELOG.md

v0.35.0 — OpenCode hooks, alignment-aware Sim, git-root .kin paths

Choose a tag to compare

@jmcentire jmcentire released this 02 Sep 22:17

Added

  • OpenCode SessionStart hook parity. OpenCode sessions had the Kindex MCP tools but no hooks, so nothing primed automatically. kin setup-opencode-hooks now installs an auto-loaded OpenCode plugin that runs kin prime in the working directory each session and injects the result into the system prompt (the OpenCode analog of Claude's SessionStart context), plus compaction context. New --adapter opencode on the hook commands.

Changed

  • Sim supervisory review now weighs alignment and trajectory, with graduated effort. Beyond "is the work sound", Sim now asks whether the work still serves what the user actually asked (spirit over letter) and where the course leads (side-effects, whether the strategy should change). Effort self-calibrates: banter is skipped; ordinary work gets the grounded single-persona review; a high-stakes, hard-to-reverse move is a reversibility trip-wire that can recommend — or, opt-in, run and verify — a deeper Advocate/Helland review. Notes are considerations, not verdicts.

Fixed

  • .kin artifacts anchor at the git root with repo-relative paths. kin export code-map auto-detects the git root and recovers in-repo absolute provenance as a repo-relative path instead of dropping or leaking it; kin index writes .kin/ at the git root, not the cwd.

Full changelog: CHANGELOG.md

v0.34.0 — Grounded retrieval, bounded multi-hop, co-activation

Choose a tag to compare

@jmcentire jmcentire released this 31 Aug 23:04

Kindex can now tell you it doesn't know.

Added

Retrieval grounding. vector_search returned the top-k nearest neighbours for any query however nonsensical, and ask() could only reach its "no relevant knowledge" branch when the result list was empty — which vector search made unreachable. So a near-null question still pulled real nodes into an agent's context, and the graph had no way to say it knows nothing.

hybrid_search now reports a RetrievalVerdictgrounded / weak / ungrounded / uncalibrated — and format_context_block stamps it onto the block. That is the single place rows become context text, so the verdict is a gate rather than something every caller must remember to honour.

The similarity floor is an immutable versioned calibration record keyed by provider:model, carrying the corpus it was measured against. Config holds the percentile policy, never the number — a floor calibrated at low embedding coverage is detected as stale rather than quietly trusted.

kin embed calibrate          # measure the null-query distribution
kin embed calibrate --show   # read the current record

Shadow mode is the default. Enforcing turns a visible, self-correcting problem (irrelevant results in context) into a silent one (an agent proceeding without knowledge that was there). Run it in shadow, see what it would have dropped, then opt in.

Bounded multi-hop expansion. hybrid_search ignored graph_hops and walked exactly one hop from five FTS hits. Store.expand_multihop honours the requested depth with per-hop decay and a mandatory beam whose ordering is total and stable — an unspecified beam makes traversal nondeterministic, which in a provenance-first graph is worse than a slow one. Measured on a 113k-edge graph: 3 hops in 0.7 ms, 4.8× the reach of 1 hop.

Learned pair co-activation (schema v11). A third ranking channel with its own table and auto-ramp, a bounded update that saturates instead of running away, and deposits gated on confirmed use rather than co-retrieval. Never folded into edges.weight, which is asserted topology — merging a learned correction there would destroy the told/inferred distinction.

Extraction engines and an eval gate. Engine output is staged into the capture_candidates quarantine and never writes nodes or edges. kin extract eval scores engines against your own corpus behind a two-part gate: grounding precision as a hallucination floor, title recall as the discriminator — either alone is gameable. New optional kindex[talon] extra, excluded from kindex[all].

kin doctor now reports column-level schema drift, oversized nodes, and silently-recovered failure counters.

Fixed

The stigmergic pheromone channel was dead on every upgraded install. The missed column was added to the v7 CREATE TABLE IF NOT EXISTS after v7 shipped, so any store that had already run v7 never received it and never would — while schema_version still read current. deposit_pheromone raised, the attention hook swallowed it with except Exception: pass, and session state recorded the deposit as successful anyway. Fixed by schema v10, a column-level drift check (a table-existence check is blind to this class), a logged and counted failure in place of the silent swallow, and a caller that records only what the store accepted.

Unbounded dream-cycle merge growth. merge_nodes appended with no cap, and content_overlap compares only the first 500 chars — where machine-generated files are identical. Minified symbols, one class defined in twenty files, a vendored LICENSE: all mutually similar by construction, so every merge was a false positive that grew the target. Caps now refuse rather than truncate.

LLM extraction was silently disabled on multi-key configs. extract.py did a bare os.environ.get on a field llm.py correctly parses as a comma-separated list, and hardcoded the Anthropic SDK while ignoring llm.provider. Both now delegate to llm.py.

similarity_from_distance uses the L2 identity cos = 1 - d²/2. sqlite-vec's vec0 returns L2 distance, not cosine; the naive 1 - d collapses the useful range to zero and calibrates a floor that can never fire.

Not adopted

The VSA/hypervector reservoir. Traversal is already free at this scale, and superposition loses the path — fatal for a graph whose value is auditable provenance. The reasoning is recorded in docs/prd-hillock-adoption-2026-08.md so it doesn't have to be re-derived.

Upgrading

SQLite schema v9 → v11, applied automatically on open. Both migrations are additive, atomic, and column-verified. Run kin doctor afterwards to confirm no drift.

1927 tests passing.

v0.33.0 — Referent binding, pre-merge snapshots, .kin schema v2

Choose a tag to compare

@jmcentire jmcentire released this 24 Aug 08:22

Added

  • Referent binding + two clocks (R0). Nodes can bind the external thing their claim describes — {path|url, content_digest, digest_scope} — plus asserted_at (claim time) and true_of (referent observation time). kin add --referent / MCP add(referent=...) bind at capture; kin stale / MCP stale_check re-hash file-scope referents, demote moved-or-missing referents from trusted_only recall (stale_referent), mark them [stale-referent] in search/context, and list re-verification candidates; --rebind re-verifies without re-dating the claim. Export/import and the .kin index carry the binding.
  • Pre-merge DB snapshots. Every automated destructive merge (graph_merge, dream-cycle auto-merges) first copies the SQLite store via the backup API to $XDG_STATE_HOME/kindex/snapshots/ (ten kept per database) and logs a db_snapshot changelog entry with a restore hint. Fail-closed: no snapshot, no merge.
  • .kin schema versioning. .kin/index.json advances to schema v2: unknown top-level fields pass through the kin merge-kin driver via 3-way field merge, and a side declaring a newer schema version makes the driver decline (normal git conflict) instead of silently rewriting it.

Changed

  • SQLite schema v8 → v9 (atomic, rollback-safe): nodes gain nullable referent, asserted_at, true_of.

Fixed

  • _migrate_v8 stamped the code's current SCHEMA_VERSION instead of the literal 8, which would have marked v9+ migrations applied before they ran on any multi-step upgrade.

Documentation

  • docs/spec-contradiction-check.md: reviewed v1 contract for the contradiction_check tool (spec only). docs/prd-lineage-grounding-2026-08.md: the reviewed PRD behind this work. Human/MCP guides and README cover referent binding, staleness, and snapshot restore.

61 MCP tools · 1830 tests · full changelog: https://github.com/jmcentire/kindex/blob/main/CHANGELOG.md

Kindex v0.32.0

Choose a tag to compare

@jmcentire jmcentire released this 18 Aug 20:59

Reviewed memory and trusted state: automatic hook capture is quarantined for explicit freshness-checked review; nodes support verification, valid-time, and invalidation; trusted-only search/context and bounded trusted resume keep unverified or stale state out of admission. Includes atomic schema v8 migration, CLI/MCP parity, public documentation, and release-gate hardening. Validation: 1797 tests passed plus clean isolated wheel installs for base and all extras.

v0.31.0 — config test seam, schedule-independent decay, honest search disclosure

Choose a tag to compare

@jmcentire jmcentire released this 12 Aug 23:04

What's in it

V1 — config resolution has a test seam. bind_root / unbind_root / bound_root / active_root let a test point kindex at a temp root after import, and every resolution follows: data_dir, the config-file search, the project-root walk, the MCP store accessor. Previously the only lever was $HOME before first import, so an in-process test resolved to the developer's live graph. Containment covers reads and writes, survives symlinks (checked after resolution, not before), and blocks the scheduler/daemon installers, which otherwise rewrite the real crontab and ~/Library/LaunchAgents.

V2 — weight decay is schedule-independent. Weight depends only on elapsed time, not on how often the job ran. At the shipped 5-minute cron over 90 days the old behaviour drifted 5.8e-4 from the closed form, past its stated tolerance; it is now exact. Per-row accounting keeps sub-threshold intervals from being discarded, detects external weight changes so reinforcement is not overwritten, and the checkpoint is monotonic against a backwards clock.

V3 — the fence note names exactly what --include-archived reveals, derived from the actual withheld set rather than a fixed string.

V4 — the degraded ledger does not lose events. The lock is non-blocking, so an error path can never hang a hook or an MCP turn, and a size-cap that races an append recovers it.

V5 — the backfill bound is honest in both directions. The candidate-window disclosure appears when the window truncated the candidates and stays silent when the corpus was simply exhausted. In --json mode it goes to stderr, keeping stdout parseable.

V6 — the MCP failure surface is testable in isolation: a broken store yields the typed memory-unavailable result without touching a real graph.

Also fixed

  • --include-archived silently lost the FTS index — malformed SQL was swallowed by a LIKE fallback, so the flag returned fewer rows than the default, unranked.
  • Git-tracked .kin/index.json and .kin/code-map.json no longer churn on every decay cycle.

No schema change; SCHEMA_VERSION stays 7.

v0.30.1 — pin mcp below 2.0 in the all extra

Choose a tag to compare

@jmcentire jmcentire released this 11 Aug 18:35

Patch on top of 0.30.0.

0.30.0 pinned mcp[cli]<2.0 for the mcp extra, but the all extra still carried the unbounded requirement — so pip install kindex[all] continued to resolve mcp 2.0.0 and produce an MCP server that could not start. Both extras are pinned now.

Found by an adversarial review of the 0.30.0 doneness claim: the release evidence covered the [mcp] extra and the bare wheel, and never exercised [all]. The release isolation gate now installs the [all] extra and imports the MCP server, so a public install path cannot regress unnoticed again.

Everything in the 0.30.0 notes applies.

v0.30.0 — reliability batch

Choose a tag to compare

@jmcentire jmcentire released this 11 Aug 18:30

Reliability batch — four defects that were silently degrading kindex, each found by audit and verified by an independently-authored acceptance suite.

Fixed

End-of-session capture actually runs. The installed Stop hook passed --text "Session ended", which preempted the hook envelope on stdin — so kin compact-hook extracted knowledge from a 13-character literal instead of your session transcript, and could spend an LLM call doing it. Stdin envelopes now take precedence, kin setup installs the Stop entry without --text, and re-running setup migrates broken entries.

Memory failure degrades the turn instead of crashing it. Hook commands tracebacked with a nonzero exit on any store failure, visible only in transient hook stderr — sessions silently started blind. They now emit a shaped degraded output, exit 0, and append one JSON event per failed invocation to degraded.jsonl in the base data directory (a plain file append that works when SQLite is what broke). kin status and kin doctor surface the 7-day count. Every MCP tool returns Error: memory unavailable (…) instead of a protocol error.

Archived and superseded nodes stay out of retrieval. Search fenced only superseded nodes, so archived content remained a first-class candidate in FTS, vector, and hybrid results, in context formatters, and in topicless MCP pulls. All default paths now fence both; --include-archived restores the old behavior, and a short result set tells you how many results were fenced. hybrid_search backfills after drop-filtering instead of quietly returning fewer results than requested.

Weight decay is cadence-independent. Each cron pass re-applied a factor computed from a node's full age to its already-decayed weight, so the effective half-life depended on how often cron ran — at a five-minute cadence, weights collapsed roughly fifty times faster than the documented 90 days. Decay now folds only the interval since the last recorded run.

Changed

The mcp extra is pinned to mcp[cli]>=1.26.0,<2.0. The unbounded pin resolved to mcp 2.0.0, which the MCP server module cannot run against — fresh pip install kindex[mcp] installs were producing a server that would not start.

Provenance

Built with the Validator/Coder/Tester discipline: the tests were authored by a lane that never saw the implementation, and failed against the unfixed code before passing against the fix. Signed specifications, review dispositions, incidents, and declared gaps are in .factory/runs/batch0/.

v0.29.0 — Unity support, unlimited code ingest, hook & scheduler fixes

Choose a tag to compare

@jmcentire jmcentire released this 16 Jul 05:20

Resolves all four open issues (#14#17), hardened by adversarial review.

Features

  • Opt-in Unity asset ingestion (#17): kin ingest code --unity (or code_ingest: {unity: true} in the project's .kin/config) indexes .unity/.prefab/.asset/.mat/.controller/.anim files. Text-vs-binary serialization is sniffed via the %YAML header; Library/, Temp/, Logs/, obj/, Build/, UserSettings/ are excluded at any depth. Each ingested file's .meta GUID is attached to its node (extra.unity_guid) and exported in the code-map as languageNotes.unityGuid, giving models the GUID→path mapping Unity references need — without indexing .meta files as nodes. Generic escape hatch: code_ingest.include_extensions (e.g. .shader: Unity Shader). The opt-in resolves from the target directory's .kin/config, and the explicit flag wins in both directions.

Fixes

  • Compact hook no longer mints blank nodes (#14): the PreCompact hook extracted from the hook's JSON envelope instead of the conversation, creating one empty node per envelope field at every compaction. It now parses the transcript file the envelope points at. _extract_session_text also understands the modern nested transcript format ({"type": "assistant", "message": {...}}) — the cron capture path was silently extracting nothing from current transcripts. Neither hook path will ever mint a content-empty concept again.
  • Ingest limits make sense (#16): kin ingest code is unlimited by default (fully local analysis, no LLM); network/LLM adapters keep their 50 cap. --limit 0 genuinely means unlimited (it was silently coerced to 50; negative values ingested nothing). Truncation is loudly reported on CLI and MCP paths. Unlimited is clamped at external API boundaries (Linear 250/page, GitHub per_page 100).
  • Scheduler logs are profile-independent (#15): cron/launchd logs always land in the base data dir's logs/, never a cwd-resolved profile folder; the adaptive repack and per-profile daemon passes are anchored to the same base dir. Re-running kin setup-cron migrates stale entries in place (preserving adaptively repacked intervals) and now creates the log dir — a >> redirect into a missing dir silently kills the job. The crontab matcher matches kindex command shapes only, so user cron lines that merely mention a kindex path (e.g. a ~/.kindex backup) are never touched.

Internal

  • IngestResult gained a warnings list surfaced through __str__.
  • Shared is_kindex_cron_line() keeps install/uninstall/repack matchers from diverging.
  • 100 new tests (1659 total).