Repository navigation
chore: release v0.19.1 to main - #1315
Merged
Merged
Conversation
3 files still referenced ~30ms (stale from early benchmarks). Actual measured P50 at 1K-10K memories is ~45ms per benchmarks.md. Updated: architecture.md, mcp.md, index.md
…-to-45ms fix(docs): standardize recall latency to ~45ms
- Add internal/ to .gitignore (prevents future strategy/launch doc leaks) - Add benchmarks/longmemeval/results_*/ to .gitignore (ephemeral data) - Add docs/package-lock.json to .gitignore (VitePress build artifact) - Move blog/comparison-2026.md → docs/comparison-2026.md (consolidate docs) - Remove stale benchmarks/longmemeval/results_diverse/ (raw output, not summary) - Remove docs/package-lock.json from tracking Audit confirms: zero internal/ files in entire git history after filter-repo scrub.
…#1015) * feat(bench): batch import + strategy flag + API embedding auto-config - Replace 53x individual remember calls with single JSONL batch import (10x speedup) - Add --strategy flag to pass vector|hybrid to uteke recall - Auto-configure embedding API from EMBED_API_KEY/EMBED_API_BASE env vars - Add --chunk-sessions flag for session chunking (Tier 2 prep) - Dedup recall results by session_id (first occurrence = highest rank) - Raise subprocess timeout 120s -> 600s for large imports Initial 5Q results: hybrid R@5=1.000 vs vector R@5=0.800 (+20pp) * fix(bench): only mark sessions inserted after import succeeds Address Cora findings: - Move inserted_sids population to after batch import success - Parse import response to verify imported_count > 0 - Log warning if import returns 0 inserted * fix(bench): resolve uteke binary by absolute path to avoid x86_64 PATH clash Background subprocess calls were resolving to /opt/data/.cargo/bin/uteke (x86_64) instead of target/release/uteke (AArch64). Now resolves relative to repo root with shutil.which fallback. * docs(bench): add 50Q hybrid results — R@5 98.0%, R@10 100% Strategy comparison (uteke only): - Vector 500Q: R@5=85.4%, R@10=88.5%, NDCG@5=0.810 - Hybrid 50Q: R@5=98.0%, R@10=100%, NDCG@5=0.960 - Improvement: +12.6pp R@5 Hybrid uses RRF (k=60) fusion of vector + FTS5 search. 1 miss at R@5 (single-session-user), recovered at R@10. run_eval.py changes: - Add --strategy flag (vector|hybrid) - Throttle: taskset -c 0-1 + nice -n 19 - Absolute binary path resolution - Timeout: 900s per question * fix(core): add dedup, retry, and auto_link to import path (#1005) Import pipeline was missing 3 features that remember() has: 1. Dedup check — cosine >= 0.95 skips duplicate entries 2. Retry on embedding failure — 3 retries with backoff 3. Auto-link cosine edges — graph edges for imported memories Changes: - import_export.rs: call check_duplicate() before insert, use retry_embed() instead of single-attempt embed(), call auto_link_cosine() after successful insert - operations.rs: make retry_embed() and check_duplicate() pub(crate) so they're accessible from import_export.rs Import path is now semantically consistent with remember() path. * fix(core): cross-compile ORT_LIB_NAME for Android/iOS (#1014) Add target_os = "android" to Linux .so branch and target_os = "ios" to macOS .dylib branch. Without these, uteke-core fails to compile for mobile targets with E0425 (cannot find value ORT_LIB_NAME). Android uses libonnxruntime.so (same as Linux, loaded via jniLibs). iOS uses libonnxruntime.dylib (same as macOS, framework embedded). This unblocks uteke-mobile cross-compilation. * feat(core): hybrid as default recall strategy Change default_strategy from vector to hybrid (RRF: vector + FTS5). Benchmark justification (LongMemEval-S): - Vector 500Q: R@5=85.4%, R@10=88.5% - Hybrid 50Q: R@5=98.0%, R@10=100.0% - Improvement: +12.6pp R@5 Changes: - config.rs: default_strategy = hybrid + assert in test - cli.rs: update help text default to hybrid - recall.rs: update comment to reflect new default - configuration.md: update all references - cli-reference.md: reorder examples, hybrid first as default Users who want vector-only: set default_strategy = vector in config or use --strategy vector flag. * fix(bench): guard taskset/nice with sys.platform check Cora finding: taskset is Linux-only, would FileNotFoundError on macOS. Now conditionally applied only when sys.platform == 'linux'. --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…ng text (#1006, #1002) (#1016) #1006: CLI update check skipped when UTEKE_NO_UPDATE_CHECK env var is set. Benchmark script sets this automatically, saving ~500ms per subprocess call. #1002: Pre-truncate text before tokenizer to avoid wasted CPU on tokens beyond MAX_SEQ_LEN (2048). Uses 4 chars/token heuristic with char-boundary safety. #1003: Already resolved — idx_memories_namespace index exists in SCHEMA_INDEXES. #1004: Already resolved — compute_graph_signals uses single batched SQL query. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…enance (#1007, #1010, #1012, #1013) (#1017) * feat: Phase 3 — lifecycle/deprecated endpoint, memory tools guide, source provenance (#1007, #1010, #1012, #1013) #1007: GET /lifecycle/deprecated — list deprecated memories with sunset info - list_deprecated() in aging.rs with DeprecatedMemoryInfo struct - Handler + route + API registry entry #1010: Memory tools guide injection - guide.rs module with default_guide() for system prompt injection - CLI: uteke guide command - API: GET /guide endpoint #1012: Implicit memory hierarchy docs - docs/organizing-memories.md — type + importance pattern - VitePress nav entry #1013: Auto-populate source provenance - CLI extraction: set source_label from input filename, source_type='extract' - Server extraction: set_source on each extracted fact - CLI output: display source_type alongside source in verbose mode * docs: regenerate api-reference.md for new endpoints (#1007, #1010) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
SYSTEM_PROMPT now requests scene-segmented JSON output with type and priority per fact. parse_facts handles three formats: scene-segmented nested JSON, flat object array with type/priority, and legacy flat string array (backward compatible). ExtractedFact struct carries content, scene, fact_type, priority. CLI and server callers use remember_typed + set_importance + scene tag. Offline mode unaffected — ExtractedFact::flat wraps existing strings. 9 new tests cover nested parsing, backward compat, dedup, priority range validation. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
- Version bump to 0.14.0 - CHANGELOG entry for v0.14.0 - Docs: cli-reference scene-segmented extraction section - Docs: memory-lifecycle deprecated endpoint Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
- Add 60s/30s/30s delay between crate publishes for index propagation - Add repository, rust-version, documentation, homepage to uteke-mcp - Fixes: uteke-mcp/cli/server fail because uteke-core not yet in index - Fixes: 'manifest has no documentation, homepage or repository' warning Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Root cause: commit 0b5cad3 removed docs/package-lock.json from git tracking and added it to .gitignore. The deploy-website workflow still referenced it via cache-dependency-path, causing setup-node to fail: 'Some specified paths were not resolved, unable to cache dependencies.' Fix: - Replace actions/setup-node with oven-sh/setup-bun - Replace npm ci with bun install --frozen-lockfile - Replace npm run build with bun run build - Add docs/bun.lock as tracked lockfile - Remove docs/package-lock.json from .gitignore (no longer relevant) Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Add mutation testing infrastructure to validate test quality across critical pure-logic modules. 11 new mutation-killing tests improve salience_recency.rs score from 76% to 96%. Changes: - Add cargo-mutants config (mutants.toml) with exclusions for modules requiring external services - Add mutation-testing CI workflow (develop→main PRs only, pre-release quality gate) - Add .gitignore entries for mutants output directories - Add mutation-testing.md developer documentation - Write 9 mutation-killing tests for salience_recency.rs - Write 2 mutation-killing tests for recall_cache.rs Results (cargo-mutants v27.1.0): jaccard.rs: 12 mutants, 9 caught, 0 missed (100%) salience_recency: 53 mutants, 48 caught, 3 missed (96%) recall_cache: 25 mutants, 18 caught, 5 missed (80%) Refs: nginjen mutation testing pattern (#mutation-testing) Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…ion-killing tests (score 50%→97%) (#1024) Two production bugs found by mutation testing: 1. Heading duplication: oversized markdown sections had their heading prepended twice in the first sub-chunk (once by split_by_headings, once more by the sub-chunk loop), corrupting downstream embeddings. Fixed by removing the dead heading_prefix re-prepend path entirely. 2. Multibyte infinite loop: split_long_text's zero-progress guard advanced by raw byte offsets that could land inside multi-byte UTF-8 characters (CJK/emoji), flooring back to start forever. chunk_markdown("日本語", 2) would hang. Fixed with a proper forward-char-boundary advance in the guard. Also: - 40 new mutation-killing tests (chunker: 20 → 60 tests) - cargo-mutants config moved to .cargo/mutants.toml (v27 schema: exclude_globs/exclude_re, valid keys only); glob paths fixed to match from workspace root; CLI update_check also excluded - 3 proven-equivalent mutants excluded with documented reasoning - docs/mutation-testing.md: final scores, bug postmortem, timeout notes Verify run: 164 mutants, 149 caught, 0 missed, 5 timeout, 10 unviable (97%) Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Patch release: chunker heading duplication fix, multibyte infinite loop fix, mutation testing hardening (PR #1024). - Bump workspace version 0.14.0 -> 0.14.1 - Bump intra-workspace deps (cli/mcp/server -> core 0.14.1) - CHANGELOG entry for 0.14.1 Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…1030) * fix(cli): embed bundled assets inside crate root for crates.io publish include_str! paths pointed outside the package root (../../../.agents, ../../../extensions). cargo publish cannot bundle files outside the package, so uteke-cli has failed to publish since June (stuck at 0.4.3) while the release workflow hid the failure with continue-on-error. Assets now live in crates/uteke-cli/assets/ and ship inside the .crate. Verified locally: cargo package -p uteke-cli passes with full verify. * ci(release): verify crates.io versions after publish The continue-on-error on publish steps (added for the tag race fix) also hides genuine publish failures. Verify all four crates report the tagged version on crates.io; fail the job if any crate lags behind. * style: cargo fmt --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
The v0.14.2 release reused the v0.13.0 notes because a committed RELEASE_NOTES.md is preferred over auto-generation and nothing checked which version it was for. The release shipped with wrong notes until manually fixed. The guard now requires the file to mention the tagged version. Also remove the stale v0.13.0 file so the next release auto-generates from the CHANGELOG unless someone writes fresh notes. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
, #1035) (#1038) * fix(server,mcp): default recall strategy to hybrid, validate strategy at boundary (#1034, #1035) HTTP: resolve strategy once (request > [recall] default_strategy config > hybrid). Invalid strategy returns 400 on all paths (bare recall, unified search, v1). The eager legacy recall that ran before strategy resolution is removed. Memory-only recall path routes through recall_hybrid with the same 3x over-fetch post-filter pattern used by recall_unified_memories (entity/category filters). MCP: uteke_recall schema exposes strategy (vector|fts5|hybrid|graph). Default resolves to hybrid, invalid values return a loud JSON-RPC error (-32603) instead of silently falling back to vector. Server startup: sanitize [recall] default_strategy from uteke.toml — invalid value warns and falls back to hybrid so a config typo cannot 400 every request with a message blaming the request. Docs: api-reference.md and mcp.md now describe the hybrid default, HTTP 400 on invalid, and the config fallback chain. Verified empirically against a scratch store: HTTP matrix 10/10, MCP harness 8/8 including engine parity (default == hybrid, warm cache) and loud bogus rejection. * docs: regenerate api-reference via docgen (strategy hybrid default, 400 on invalid) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…plate file (#1041) * fix(ci): replace unquoted heredoc in release notes generation with template file The unquoted heredoc << RELEASEEOF underwent shell expansion: markdown backticks became command substitutions and executed on the runner. v0.14.3 release: installer curl|sh ran, uteke-serve --port 8767 started and blocked the job for 48 minutes (2 runs, deterministic). Move the static tail (downloads table + quick start) to scripts/release-notes-template.md and substitute __VER__ via sed. Zero shell expansion over markdown content. Validated locally: generate completes instantly, output byte-correct. Fixes the release pipeline for all future releases. * ci: re-trigger review bots (LLM API transient error) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…pages, fix release-notes asset names (#1055) * docs: sync stale version refs, roadmap v0.13–v0.14, merge comparison pages, fix release-notes asset names (#1043) - README/README.id/AGENT.md/install.md: version + test-count updates (0.14.3, 530+ tests); AGENT.md now lists all 5 workspace crates incl. docgen - docs/roadmap.md: add v0.13.0–v0.13.2 and v0.14.0–v0.14.3 entries from CHANGELOG - comparison: merge comparison-2026.md (canonical long-form) into comparison.md, keep at-a-glance matrix + extraction table from the old page, drop dead /blog link - extensions/hermes-memory-provider → extensions/hermes-uteke-memory (+ embedded assets copy and all path refs) — dir name no longer references the removed Mode B provider - scripts/release-notes-template.md: download table filenames get v prefix to match actual release assets (#1043) * fix(release): keep v prefix on pinned-install example in release notes template Co-authored-by: VIVAAN-DHAWAN <VIVAAN-DHAWAN@users.noreply.github.com> Same fix as #1046 — UTEKE_VERSION is used verbatim as the release tag by install.sh, so the pin example needs the v prefix too. Picking it up here so #1043 closes fully through this PR once the rest of the audit lands. * Revert "fix(release): keep v prefix on pinned-install example in release notes template" This reverts commit 222d067.
…1056) Agents are advisory-mode by default: audit/check requests are not authorization to mutate. Gate push/merge/cherry-pick from others' PRs, comments/edits on others' PRs/issues, PR retargeting, and anything irreversible or externally visible behind explicit maintainer approval. Correct flow: analyze → present options → wait → execute approved scope → report. Real incident 2026-08-17 documented as cautionary example.
All id call sites across uteke-core (remember, chunks, graph, edges, timeline, orphans, import) now mint UUIDv7. Storage and wire format unchanged (TEXT uuid); v4/v7 coexist — existing stores open unchanged. Adds two tests: v7 version nibble + ascending order for consecutive mints, and v4/v7 parse coexistence.
#1047) (#1061) Root cause was NOT a partial delete — soft_forget() correctly marks the row deprecated and removes the vector. The leak was read-side: - list()/search_content() never filtered deprecated rows → ghosts in 'uteke list' after forget - store.count(None) counted deprecated rows → doctor/verify reported permanent DB/Index MISMATCH after any soft-forget - load_all() (repair/verify source) included deprecated rows → repair() re-added soft-deleted vectors to the index, resurrecting them in recall Fix, uniform active-only contract: - list() (all 4 branches) + search_content(): AND deprecated = 0 - load_all(): AND deprecated = 0 (recompute_importance also stops wasting cycles on hidden rows) - count(): active-only for both None and Some(ns) paths — directly comparable to index.len() in doctor/verify - new count_all(): explicit include-deprecated totals for reporting Regression test: isolated temp-dir store (':memory:' stores resolve the vector index to a CWD file and cross-contaminate parallel test runs — that shared uteke_index.usearch pollution is also why this bug hid). Asserts soft-forgotten id absent from list/list-ns/load_all and doctor reports no MISMATCH.
…ace keyword misses (#1051) (#1062) uteke_search / CLI search go through store.search_content() (LIKE substring), which mapped namespace=None to the 'default' namespace instead of searching across all namespaces like list(None) does (#526). Memories stored in any other namespace were invisible to keyword search unless the caller explicitly passed that namespace. - namespace=None now searches across all namespaces (deprecated rows still excluded) - hyphenated identifiers keep working as literal substrings on the LIKE path (pinned by test), and the FTS5 phrase path already handles them (unicode61 adjacency) — probed both in-test Regression test: cross-namespace hit via None, scoped hit via Some(ns), full and partial hyphenated identifier matching.
… parity (#1037) (#1063) recall_hybrid() applied salience/recency boosts only on the cache-miss path; the cache-hit early return handed back raw cached scores. Same query + strategy returned different scores cold vs warm (delta ~0.13). Three-part fix: - Cache-hit read path now re-applies boosts (boost → sort → truncate → min_score), identical post-processing to the miss path via shared apply_salience_recency_boosts() helper. Cache intentionally stores RAW scores — boosts are time-dependent and re-applied per read. - Boost window: cache stores limit*4+16 candidates computed with min_score=0, so boosts can lift a memory from outside the raw top-N into the final top-N on warm reads too (cora finding — cached top-limit-only set would permanently exclude boostable candidates). - min_score thresholding now happens AFTER boosts on BOTH paths (previously miss-path Vector/Fts5 filtered raw scores while hit-path filtered boosted scores). Tests: cold/warm score parity (fails with max delta 0.125 pre-fix); boost-reorder-across-limit; noop-config warm hits respect limit.
…umented (#1036) (#1064) ExportEntry had no namespace field — every exported row lost its namespace, so export→import collapsed multi-namespace stores into one. Also root-caused the reporter's 36-row delta: export() reads load_all() which filters deprecated=0 (soft-deleted rows excluded by design, but undocumented). - ExportEntry gains 'namespace' (serde default 'default' keeps old export files importable) - export() serializes m.namespace on every row - import(): caller-supplied namespace = explicit override for all rows; without it, per-row namespace wins → round-trips reconstruct namespaces - docgen/api-reference regenerated (no route change, freshness check) Test: 3-namespace × 2-row export shape (every row carries its ns), parse-side attribution preservation, legacy-row default fallback.
…confirm to apply (#1050) (#1065) A no-args uteke_dream call ran the maintenance pipeline with dry_run=false against ALL namespaces while the tool description said 'Safe to run periodically'. Real incident: single exploratory call mutated 4,067 rows store-wide. - dry_run defaults to TRUE — a no-args call can only preview - Applying requires explicit dry_run=false - Unscoped applying runs refused unless confirm_large=true (two-flag decision for whole-store maintenance) - Large-batch guard: applying runs projecting >100 changes refuse without confirm_large=true; preview computed first, so the refusal reports the projected count - Output announces scope ([SCOPE: ALL NAMESPACES]) on both preview and apply paths - Description rewritten: states destructive nature + dry-run-first guidance instead of 'Safe to run periodically' - docs/mcp.md tool table updated
…doc_search scores, room ids (#1052) (#1066) - uteke_stats: multi-line output — tiers (hot/warm/cold), pinned + deprecated split, recall cache hits/misses, and per-namespace breakdown when unscoped (was: single 'Total | Tags | DB' line) - uteke_doc_search: per-result score, matched chunk heading + 120-char snippet (ranking was invisible; results were bare slug — title) - uteke_room_memories: lines now include 8-char short id so the next tool call (pin/forget/graph edges) can act on the row - uteke_room_recall description states the existing-room_id precondition instead of failing only at call time - core: Store::count_pinned() + Uteke::{count_pinned, count_deprecated, namespace_counts} accessors (store field is private; MCP uses the public API surface)
…l ID-taking tools (#1048, #1049) (#1067) MCP printed 8-char short ids in recall/list but every ID-consuming tool required the full UUID (exact SQL match) — the basic loop recall → act silently no-opped. resolve_id_prefix() existed in core (#794); MCP never wired it. - resolve_id() helper: full UUID passes through; any shorter prefix resolves via resolve_id_prefix(); ambiguous prefixes error loudly; unknown prefixes error instead of silent not-found - Wired into uteke_forget, uteke_pin, uteke_unpin, uteke_graph_add_edge, uteke_graph_remove_edge - NEW uteke_get {id} — full record by id/prefix, no truncation (fills the read-by-id gap; recall/search return ranked excerpts) - NEW uteke_update {id, content?, tags?, metadata?, importance?, pinned?, memory_type?} — partial-update semantics matching HTTP PUT /memory (#659); content change re-embeds - Tool schemas + docs/mcp.md: id params documented as UUID-or-prefix Tests (5, scratch temp-dir stores): prefix + full + unknown resolution; uteke_get full record via short id; pin via short id; forget short id happy path + bogus prefix errors loudly; update partial fields leave content untouched.
* chore(release): complete v0.18.2 metadata lost in #1278 squash The #1278 squash carried AGENT.md and CHANGELOG (staged correctly) but lost the in-place edits applied after staging: Cargo.toml/Cargo.lock stayed 0.18.1 and the README version strings kept v0.18.1. This restores them on top of develop so the release line is consistent again. Also moves the #1273 Unreleased changelog entry into [0.18.2] with a note: both #1270/#1271 (this backport) and #1273 land on main together when the release is tagged, so the shipped version section must list both. * fix(release): 0.18.2 version lockstep — bundled skill asset + core contract Follows #1274 (skill parity test) and #1276 (tiered api_registry / core contract generation): both artifacts embed the workspace version and went stale when the 0.18.2 bump was reapplied on top of develop. Bumps the bundled uteke-memory-skill.md version line and regenerates docs/core-contract.json via docgen. * fix(release): sync .agents uteke-memory skill copy to 0.18.2 The skill_bundled_matches_repo_copy parity test requires the bundled asset (crates/uteke-cli/assets/uteke-memory-skill.md) and the repo wiki copy (.agents/skills/uteke-memory/SKILL.md) to be byte-identical; only the bundled side was bumped in the previous commit. --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…d events, MCP tool (schema v20) (#1280) * feat(core): audit-grade timeline — history survives forget, deprecated events, MCP tool (schema v20) Owner decision 2026-09-18 (contract doc kontrak-core-cloud/03): timeline is the audit layer and must survive memory deletion. - migration v19->v20: rebuild timeline_events WITHOUT the FK ON DELETE CASCADE (defensive: creates the table if an old store never materialized it) + backfill `created` events (actor=backfill) for memories lacking one (~9.7k in PROD) - deprecate_with_reason now records a `deprecated` event with reason (the fleet's dominant delete traffic — 1.4k deprecations — was previously unwired); idempotent re-deprecation writes no duplicate - hard forget() writes a `forgot` tombstone BEFORE the delete so the audit trail exists even on pre-v20 stores - new TimelineEventType::Deprecated variant (append-only enum rule) - new MCP tool uteke_timeline (id + limit, mirrors uteke_provenance) - tests: migration preserves rows/drops FK/backfills once; soft and hard forget event assertions (7 timeline tests + 567 lib tests green) Next up (separate PR): actor plumbing from caller identity (CLI/MCP/ HTTP) — Created events still default to a NULL actor. * fix(core): cora review — forget tombstone only for existing memories; v20 atomicity documented --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…1283) * chore(docs): evergreen README hero banner + install URL consistency (#1282) The hero banner baked stale figures (v0.4.2, star count 16, 312 tests, wrong org slug codecora/uteke, wrong install URL) and is the image embedded in the launch tweet that new visitors see. - Add docs/assets/uteke-banner.svg as the source of truth. Evergreen by design: no version/star/test numbers (those live in the shields badges); install URL codecora.dev/uteke/install; ~45ms claim per the conservative-claim decision. - scripts/regen-banner.py renders the PNG at 2x via cairosvg; the generated PNG is committed because GitHub renders README images from the repo. - Fix docs/comparison.md install URL (codecora.dev/install -> codecora.dev/uteke/install). - Checklist note for AGENTS.md release rules is proposed in the PR body (agent-instruction file needs owner consent). * chore(docs): use the official Uteke icon (uteke-mobile) as the banner mascot Replaces the hand-drawn SVG mascot with the real product icon (docs/assets/uteke-icon.png, from uteke-mobile website/icon-512.png): the teal brainy-owl with the exposed brain and idea spark. cairosvg cannot embed raster images, so scripts/regen-banner.py now composites the icon into the avatar slot (rounded corners, PIL) after the SVG render; the SVG carries a comment pinning the avatar slot coordinates. Pillow >=10 resampling API. * chore(docs): teal accent banner with mobile footer link Adopt the winning dev-banner pattern (Turso/Neon league): bottom teal glow, keyword highlighting in the headline, single teal accent across install command and meta rows. Footer links the mobile app (https://uteke.app) with a local-first privacy line. Still fully evergreen: no version/star/test numbers baked in.
…1281 Phase 1) (#1284) * feat(recall): budgeted context pack — --pack on CLI, HTTP, and MCP (#1281 Phase 1) Adds a selection primitive over unified recall: rank-order preserving greedy fill of a caller-supplied character budget. - uteke-core: new pack_mode module (pack_context + ContextPack envelope {selected, skipped, budget_used, budget_chars}); Uteke:: recall_unified_packed wraps recall_unified. Skip reasons: excluded (caller-supplied memory IDs already injected this turn) and budget (no longer fits). Char-counted (multibyte-safe), per-item overhead constant. Ranking untouched — fusion stays the default strategy; deterministic, LLM-free. 5 unit tests. - CLI: recall --pack / --budget <chars> / --exclude-ids <ids> with human + --json output. Entity/category filters are honoured; the packed path loudly rejects --at/--related/--where instead of silently dropping them. - HTTP: POST /recall accepts pack, budget_chars, exclude_ids; pack honours the caller's search_type with the same 400 validation as the plain path; integration test covers envelope shape, exclusion reporting, and an impossible budget. - MCP: uteke_recall accepts pack/budget_chars/exclude_ids; tool schema updated. - Docs: cli-reference.md flags + examples, mcp.md tool description, CHANGELOG [Unreleased]. Phase 2 (MMR diversity) intentionally NOT included — experiment gated on LongMemEval + redundancy benchmarks per #1281. Testing: pack_mode 5/5; uteke-server 37 live tests green incl. the new pack API test; workspace suite green before test additions. Live E2E against a scratch UTEKE_HOME with real ONNX embeddings: remember x3, --pack human + JSON envelope (3 selected, 235/4000 chars), --exclude-ids reports reason=excluded for the right IDs, --budget 120 fills 1 item at 60 chars and skips 2 as budget. * fix(server): pack recall loudly rejects at/after/before + regen api docs CodeCora review on #1284 flagged that the pack branch validated only search_type: a request with pack+at silently returned non-time-travel results while the plain path honours the filters (and the CLI pack path already rejects --at loudly). - POST /recall with pack + at/after/before now returns the same 400 as the CLI contract; integration test extended. - docs/api-reference.md regenerated via docgen for the new public recall_unified_packed surface (API Docs Fresh gate).
Bumps [clap_complete](https://github.com/clap-rs/clap) from 4.6.9 to 4.6.11. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/main/CHANGELOG.md) - [Commits](clap-rs/clap@clap_complete-v4.6.9...clap_complete-v4.6.11) --- updated-dependencies: - dependency-name: clap_complete dependency-version: 4.6.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [vecq-core](https://github.com/codecoradev/vecq) from 0.3.0 to 0.3.1. - [Release notes](https://github.com/codecoradev/vecq/releases) - [Changelog](https://github.com/codecoradev/vecq/blob/develop/CHANGELOG.md) - [Commits](codecoradev/vecq@v0.3.0...v0.3.1) --- updated-dependencies: - dependency-name: vecq-core dependency-version: 0.3.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [clap](https://github.com/clap-rs/clap) from 4.6.6 to 4.6.7. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/main/CHANGELOG.md) - [Commits](clap-rs/clap@clap_complete-v4.6.6...clap_complete-v4.6.7) --- updated-dependencies: - dependency-name: clap dependency-version: 4.6.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* fix(api): honor namespace filter on GET /room/memories (#1288) GET /room/memories parsed only room_id, limit, and author; any namespace query param was silently ignored, so callers asking for their own namespace in a cross-namespace room got a 200 with the full unfiltered list (issue reports a 6-namespace room returning 72 entries instead of 19). Core: recall_room becomes a compatibility wrapper delegating to a new recall_room_scoped(room_id, author, namespace, limit). The duplicate 4-variant SQL collapses into one dynamically composed WHERE clause — literal fragments stay in SQL text, every value is bound as a parameter (same owned Box<dyn ToSql> pattern as bulk.rs), so no string interpolation of inputs. Server: parse the namespace query param and pass it through; usage string and /tools endpoint-registry description updated (docs regenerated). Tests: core multi-namespace room test (scoped, combined author+namespace, legacy signature unchanged, nonexistent ns yields empty) and an HTTP-level server test. Validation: cargo fmt --check, clippy -D warnings, full workspace tests EXIT=0, feature-matrix checks, docgen fresh. * docs(changelog): add #1288 fix entry to Unreleased
…#1291) uteke-serve now serves the endpoint registry as JSON — method, path, tier, description, request/response types, and issues per route — serialized straight from api_registry::ENDPOINTS, the same single source of truth that generates docs/api-reference.md, so consumers can validate against the real contract instead of stale notes (GET vs POST, room_id vs room, body-vs-query params). mod api_registry is un-gated from the docgen feature (it is runtime data now); the registry entry is LAB tier so the CORE contract list is untouched; usage text, docgen grouping, and CHANGELOG updated; 3 new server tests cover payload shape, auth roles, and the 404 catch-all.
* chore(release): v0.19.0 — version bump, CHANGELOG, skill lockstep * chore(release): regenerate core-contract.json for 0.19.0
The tap codecoradev/homebrew-tap does not exist (404), so the brew command in the install table was a dead claim. Remove it from both README.md and README.id.md. Valid paths remain: shell installer, Cargo, Docker, GitHub Releases binaries, and the Windows PowerShell installer.
…ree-release stability tables (#1296) Headline follows the latest release basis per owner decision 2026-09-29; README table header drift (v0.18.2) retired. All numbers recomputed from committed raw + dataset.
#1297) Owner review feedback: tick row hugged the last bar; add hairline divider above footer. Data unchanged.
- mcp.md: 46 -> 49 tools; add uteke_timeline, uteke_verify, uteke_repair rows (shipped in #1280/#1272, tool table had not caught up) - architecture.md: schema history v15 -> v20 (v16 author_type #1083, v17 deprecated_at #1086, v18 provenance #1172, v19 rooms.description #1202, v20 audit-grade timeline #1280) Co-authored-by: CMO <cmo@codecora.dev>
) * feat(integrations): committed Hermes plugin package + drift guard (refs #1300) Render integrations/hermes/ from the embedded hermes-uteke-memory templates so repo-scanning installers (Hermes Desktop install dialog, plugin catalog) detect Uteke. Guard tests in init.rs keep the package byte-identical to the templates; scripts/render-hermes-integration.sh regenerates it. * fix(integrations): falsy get_hermes_home fallback in Hermes plugin templates (refs #1300) CodeCora flagged (via the newly committed rendered package) that the ImportError fallback `get_hermes_home = lambda: None` is truthy, so $HERMES_HOME/uteke.json was never discovered when hermes_constants is absent. Use None and let the existing truthiness check take the env-var branch. Applied to all three template copies and the rendered integration package; guard tests keep them in lockstep.
…-release resolution (#1308) reqwest follows redirects by default, so the HEAD probe to /releases/latest landed on the tag page (200, no location header) and every invocation fell through to the unauthenticated GitHub API fallback (60 req/h per IP). Under rate limiting users got 'Failed to determine latest version' from uteke upgrade and the startup update check (#1307). Disable redirect following for the probe so the location header is observable, validate the extracted tag (v-prefix, numeric major.minor.patch, optional pre-release suffix, query strings stripped), and give the API fallback an explicit rate-limit error message instead of a generic one. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
The rate-limit error told users to set GITHUB_TOKEN, but the fallback request never sent it. Attach it as a bearer token when present (raises the cap to 5k req/h) and make the 403/429 message distinguish whether a token was in play (#1307). Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
… update-check opt-out (#1310) Findings from the post-merge cora scan of the commands surface (#1307 thread): - upgrade: replace the predictable shared temp dir (/tmp/uteke-update-{version}, symlink-attack + collision-prone) with a private tempfile::TempDir (random suffix, 0700) that also removes leftovers on every early-return path — the five manual fs::remove_dir_all cleanup lines are gone with it. - upgrade: bound the archive/checksums download client (10s connect, 300s overall) so a stalled connection cannot hang the upgrade. - upgrade: parse_checksum now requires an exact filename match instead of a substring, so a companion artifact (e.g. .sig) can never satisfy the lookup; unit test included. - update_check: the update_check = false opt-out in uteke.toml is now honored on the fresh-cache fast path too — previously it was only checked inside the background thread, so opt-out users still saw the banner whenever the 24h cache was fresh. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
* release: add update-tap job — auto-PR homebrew-tap formula on new release * ci(release): pass repo/tag via env, not inline interpolation --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
* release: add update-tap job — auto-PR homebrew-tap formula on new release * docs: add Homebrew install option (codecoradev/tap/uteke) * chore: refresh CI (stale PR Description check from pre-edit body) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
* chore(release): v0.19.1 - version bump, changelog, docs sync - Workspace + internal dependency versions 0.19.0 -> 0.19.1 (Cargo.lock synced) - CHANGELOG: [0.19.1] entry - upgrade-path reliability (#1307 via #1308/#1309/#1310), plain /remember explicit-type fix (#1303), committed Hermes plugin package (#1301) - Bundled uteke-memory skill + .agents canonical copy bumped in lockstep - README/README.id current-version line synced * chore(release): regenerate core-contract.json for 0.19.1 docgen embeds the workspace version; the API Docs Fresh gate caught the stale generated artifact. --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…-main # Conflicts: # .agents/skills/uteke-memory/SKILL.md # CHANGELOG.md # Cargo.lock # Cargo.toml # README.id.md # README.md # benchmarks/longmemeval/.gitignore # benchmarks/longmemeval/REPRODUCING.md # benchmarks/longmemeval/RESULTS.md # crates/uteke-cli/Cargo.toml # crates/uteke-cli/assets/hermes-uteke-memory/__init__.py.tmpl # crates/uteke-cli/assets/uteke-memory-skill.md # crates/uteke-cli/src/commands/upgrade.rs # crates/uteke-mcp/Cargo.toml # crates/uteke-server/Cargo.toml # crates/uteke-server/src/api_registry.rs # crates/uteke-server/src/handlers.rs # docs/assets/uteke-banner.png # docs/assets/uteke-banner.svg # docs/benchmarks.md # docs/core-contract.json # docs/mcp.md # extensions/hermes-uteke-memory/__init__.py.tmpl
🔍 Cora AI Code ReviewReview powered by cora-code · BYOK · MIT |
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Promote the v0.19.1 content to
mainso the release tag lands onmain(release workflow gate: "Verify tag is on main").Tree is identical to
developatf416076(verified: zero diff) plus a merge commit that pre-resolves conflicts against currentmain(same pattern as #1262 / "conflicts pre-resolved" release merges).Contents since v0.19.0: upgrade version-resolution fix (#1308/#1309/#1310), plain
/rememberexplicit-type fix (#1303), committed Hermes plugin package (#1301), homebrew tap CI + install option (#1311/#1312), docs branding (#1306), deps bump (#1299). Full release-prep validation in #1313.Why
First
develop→mainPR (#1314) came back CONFLICTING becausemainreceived release-merge commits that never flow back todevelopas a whole. Pre-resolving on a release branch is the established repo pattern.Testing
git diff origin/develop HEAD— empty (content-identical to validated develop)