Skip to content

chore: carry release workflow fix (#1041) to main for next release - #1042

Merged
ajianaz merged 20 commits into
mainfrom
chore/carry-fix-1041-to-main
Aug 15, 2026
Merged

ajianaz merged 20 commits into
mainfrom
chore/carry-fix-1041-to-main

Conversation

@ajianaz

@ajianaz ajianaz commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

What

Carries fix release-workflow heredoc (PR #1041, merged to develop) to main so the next release (v0.14.4+) uses the safe template-based release notes generation.

Why

v0.14.3 GH Release had to be created manually because the workflow hung 48 min ×2 (heredoc executed installer + uteke-serve on the runner). Fix must reach main (tag build source) before next tag.

Changes

  • Auto-generate release notes: heredoc → scripts/release-notes-template.md + sed
  • .gitignore union resolution (same as v0.14.3 release merge)

Testing

ajianaz and others added 20 commits August 11, 2026 22:10
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>
@github-actions

Copy link
Copy Markdown

🔍 Cora AI Code Review

⚠️ Review could not complete. LLM API error after retries: Unknown error — check workflow logs


Review powered by cora-code · BYOK · MIT

@ajianaz
ajianaz merged commit a496321 into main Aug 15, 2026
16 checks passed
@ajianaz
ajianaz deleted the chore/carry-fix-1041-to-main branch August 15, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant