Skip to content

chore: prepare v0.0.4 release#91

Merged
ajianaz merged 2 commits into
developfrom
chore/prepare-v0.0.4
May 31, 2026
Merged

chore: prepare v0.0.4 release#91
ajianaz merged 2 commits into
developfrom
chore/prepare-v0.0.4

Conversation

@ajianaz

@ajianaz ajianaz commented May 31, 2026

Copy link
Copy Markdown
Collaborator

Changes for v0.0.4 Release

Version & Docs

  • Bump version 0.0.3 β†’ 0.0.4 in Cargo.toml, README badges
  • CHANGELOG: full v0.0.4 entry with all new features + stress test results
  • README: server mode, consolidate, prune, namespace switch, fix 256d embedding
  • Website docs: CLI reference, configuration, roadmap, multi-agent all updated
  • Release workflow: builds both uteke + uteke-serve binaries
  • Config migration docs added

Code Quality

  • Fix all clippy warnings across workspace (0 errors, 0 warnings)
  • Fix rustfmt issues across workspace
  • Remove unused Arc in uteke-server (single-threaded, no data race)
  • Fix cosine_similarity placement in uteke-core
  • Fix config loop indexing clippy warning

Tooling

  • Add .cora.yaml for cora AI code review (custom provider: glm-5.1)
  • Cora pre-commit hook installed (warn mode)
  • Release workflow strip fallback (|| true)

Validation

  • 22/22 tests pass
  • cargo clippy -D warnings clean
  • cargo fmt --check clean
  • cargo build --release clean
  • Cora review: 2 non-blocking findings (URL encoding, false positive data race)
  • Full functional retest: 15 phases all pass

Summary by CodeRabbit

  • New Features

    • Added server mode (uteke-serve) for daemon-like operation with persistent warm recall
    • CLI commands now auto-route to running server for faster performance when available
    • Added namespace switching capability to manage isolated memory spaces
    • Added consolidation and deduplication operations for memory optimization
    • Enhanced forget command with bulk deletion options
    • Added contradiction detection during memory creation
  • Documentation

    • Updated CLI reference with all new commands and options
    • Revised configuration documentation with improved TOML structure
    • Added server mode and namespace management guides
    • Updated roadmap reflecting v0.0.4 completion
  • Chores

    • Version bumped to 0.0.4
    • Integrated AI code review system

- Bump version 0.0.3 β†’ 0.0.4
- CHANGELOG: add v0.0.4 with all new features
- README: add server mode, consolidate, prune, namespace switch, fix 256d embedding
- CLI reference docs: add forget bulk, consolidate, prune, namespace, server mode
- Configuration docs: add server section, namespace resolution
- Roadmap: add v0.0.4 completed items, update next/future
- Multi-agent docs: add namespace switching section
- Release workflow: build both uteke + uteke-serve, updated release notes
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ajianaz, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 21 minutes and 3 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

βŒ› How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e8ffc2ce-1858-4cb1-8fc3-cff7745a5865

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 1b716af and dd820c1.

β›” Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
πŸ“’ Files selected for processing (10)
  • .cora.yaml
  • .github/workflows/release.yml
  • README.md
  • crates/uteke-cli/Cargo.toml
  • crates/uteke-cli/src/config.rs
  • crates/uteke-cli/src/main.rs
  • crates/uteke-core/src/lib.rs
  • crates/uteke-core/src/memory/store.rs
  • crates/uteke-server/src/main.rs
  • website/src/routes/docs/configuration/+page.svelte
πŸ“ Walkthrough

Walkthrough

This PR releases version 0.0.4 with dual-binary packaging, server mode documentation, configuration updates, and refactored server store lifetime management. The workflow now packages both uteke and uteke-serve into release archives, documentation comprehensively describes the new server mode and namespace switching, and the server code removes Arc wrapping to simplify store ownership.

Changes

v0.0.4 Release

Layer / File(s) Summary
Release configuration and versioning
.cora.yaml, Cargo.toml
Adds code review config for custom LLM provider and bumps workspace version to 0.0.4.
Release workflow and artifact packaging
.github/workflows/release.yml
Builds, strips, and packages both binaries (uteke and uteke-serve) into Unix tarball and Windows 7z archives; updates release notes generation to describe server mode, namespace switching, and bulk operations.
Changelog for 0.0.4 release
CHANGELOG.md
Documents new server mode, namespace switching, temporal facts, consolidation, bulk operations, CI code review, and embedding/threshold calibration updates.
User-facing documentation
README.md, website/src/routes/docs/cli-reference/+page.svelte, website/src/routes/docs/configuration/+page.svelte, website/src/routes/docs/multi-agent/+page.svelte, website/src/routes/docs/roadmap/+page.svelte
Updates README with version badge, expanded commands table, new server mode section, updated architecture diagram, and embedding dimension change from 768d to 256d; expands website documentation with CLI reference for new commands (forget variants, consolidate, prune, namespace, server-mode), sectioned config format examples, namespace switching guide, and marks v0.0.4 as completed.
CLI command handling refactoring
crates/uteke-cli/src/config.rs, crates/uteke-cli/src/main.rs
Refactors namespace configuration to use mutable iterator; simplifies server health-check request logic; rewrites server-routed command dispatch into explicit multiline match arms for Remember/Recall/Search/List/Stats/Forget; reformats local command handlers for contradiction detection, prune output, consolidate ID listing.
Core and store formatting
crates/uteke-core/src/lib.rs, crates/uteke-core/src/memory/store.rs
Reformats algorithm implementations (find_duplicates, consolidate, cosine_similarity) and store schema migrations (deprecated/memory_type columns) from compact to multiline form without behavior changes.
Server store lifetime and shutdown refactor
crates/uteke-server/src/main.rs
Removes Arc wrapping and import; store is now opened directly as Uteke value instead of Arc::new(uteke). Replaces Arc::try_unwrap-based shutdown with direct uteke.shutdown() call that logs errors. Refactors helpers, route signature, tags filtering, and host parsing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ajianaz/uteke#61: Both PRs modify .github/workflows/release.yml's GitHub Release notes and version-handling logic.
  • ajianaz/uteke#56: Both PRs update website/src/routes/docs/roadmap/+page.svelte to reflect completed and upcoming work.

Poem

🐰 A new release hops into townβ€”
Dual binaries bundled, namespaces switched around,
Arc unwraps its grip with grace,
Server mode runs at a faster pace,
v0.0.4 takes its place! πŸš€

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title 'chore: prepare v0.0.4 release' clearly and specifically describes the main purpose of the PRβ€”preparing a release for version 0.0.4β€”which aligns with the extensive changes across version bumping, changelog, documentation, and release workflow updates.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/prepare-v0.0.4

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 31, 2026

Copy link
Copy Markdown

πŸ” Cora AI Code Review

βœ… No issues found. Code looks good!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/uteke-cli/src/main.rs (1)

951-998: ⚠️ Potential issue | 🟠 Major | ⚑ Quick win

--type is ignored on the normal remember path.

The contradiction branch persists r#type, but the ordinary branch still calls Uteke::remember, which hardcodes "fact". uteke remember ... --type decision therefore loses the requested type whenever --detect-contradiction is not set.

πŸ›  Proposed fix
-                let id = uteke
-                    .remember(content, &tag_refs, None, ns)
-                    .map_err(|e| format!("Failed to store memory: {e}"))?;
+                let (id, _) = uteke
+                    .remember_with_contradiction(
+                        content,
+                        &tag_refs,
+                        ns,
+                        Some(r#type.as_str()),
+                        false,
+                    )
+                    .map_err(|e| format!("Failed to store memory: {e}"))?;
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/uteke-cli/src/main.rs` around lines 951 - 998, The normal remember
path in the Commands::Remember handler ignores the user-specified r#type because
it calls uteke.remember which currently uses a hardcoded "fact"; update the
ordinary branch to forward the chosen type the same way the contradiction branch
doesβ€”pass Some(r#type.as_str()) (or equivalent) into uteke.remember instead of
leaving it as None/hardcoded, so both remember_with_contradiction and remember
consistently respect the r#type argument.
crates/uteke-cli/src/config.rs (1)

440-450: ⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Escape namespace before writing it into TOML.

This writes raw user input into a quoted TOML string. A namespace containing ", \, or a newline will corrupt the config file on the next save/load cycle. Please serialize the value instead of interpolating it directly here and in the two insertion paths below.

πŸ›  Proposed fix
-            *line = format!("namespace = \"{namespace}\"");
+            *line = format!(
+                "namespace = {}",
+                toml::Value::String(namespace.to_string())
+            );
@@
-            lines.insert(pos + 1, format!("namespace = \"{namespace}\""));
+            lines.insert(
+                pos + 1,
+                format!("namespace = {}", toml::Value::String(namespace.to_string())),
+            );
@@
-            lines.push(format!("namespace = \"{namespace}\""));
+            lines.push(format!(
+                "namespace = {}",
+                toml::Value::String(namespace.to_string())
+            ));
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/uteke-cli/src/config.rs` around lines 440 - 450, The code writes raw
user input into a TOML string by directly interpolating namespace into *line =
format!("namespace = \"{namespace}\""), which will break for quotes, backslashes
or newlines; fix by serializing/escaping the namespace when composing the
assignment (e.g. use toml::to_string or
toml::Value::String(namespace.clone()).to_string() to produce a properly
quoted/escaped TOML string) and replace the direct format call in the loop (the
lines/in_store_section branch that does *line = ...) and the two insertion paths
mentioned below so they all use the serialized value when writing "namespace = "
into the config.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 72-73: The tar packaging invocation uses unquoted shell
interpolation for the output filename (the expression using matrix.artifact,
steps.version.outputs.VERSION, and matrix.ext) which allows command injection;
update the tar command (tar czf ...) and the corresponding Windows packaging
commands to wrap the entire filename expression in quotes (e.g., quote "${{
matrix.artifact }}-${{ steps.version.outputs.VERSION }}.${{ matrix.ext }}") so
the expanded value is treated as a single argument and cannot break out into
additional commands.

In `@crates/uteke-cli/src/main.rs`:
- Around line 776-791: The Commands::Remember match arm currently drops the
r#type and detect_contradiction options when sending to the server; update the
request handling in that arm so the JSON body sent by
client.post(...).json(&body) includes the "type" (r#type) and
"detect_contradiction" fields (or, if the server does not support them yet,
return an Err/early failure indicating the server mode does not accept these
options). Locate the Remember arm in main.rs and modify the construction of body
(and any error handling around client/post) to forward r#type and
detect_contradiction end-to-end, or explicitly fail fast when those options are
present to avoid silent data loss.

In `@README.md`:
- Around line 108-111: The table in README contains duplicated global flags
`--json` and `--verbose`; remove the duplicate rows so each flag appears only
once, leaving a single row for `--json` ("Output as JSON (all commands)") and a
single row for `--verbose` ("Enable debug logging"), and ensure the table
formatting/alignment remains consistent after removing the extra lines.

In `@website/src/routes/docs/cli-reference/`+page.svelte:
- Around line 191-193: The code sample in the Pre/Code block in +page.svelte
uses a raw "<uuid>" which is parsed as an HTML tag and won't render; update the
code example inside the <pre> / <code> snippet to escape angle brackets (use
&lt;uuid&gt; instead of <uuid>) so the placeholder displays correctly in the CLI
docs; locate the example text in the component (the pre/code block containing
"uteke forget <uuid> --confirm") and replace the angle-bracketed placeholder
with the escaped HTML entities.

In `@website/src/routes/docs/configuration/`+page.svelte:
- Around line 100-103: The migration example uses the key name "path" but the
rest of the docs and config use "store_path"; update the migration snippet to
use "store_path" instead of "path" so the migrated key name is consistent.
Locate the code block that currently shows [store] with path = "~/.uteke" and
change that line to store_path = "~/.uteke" (ensure only the key name is
changed, preserving the namespace = "default" line and surrounding formatting).

---

Outside diff comments:
In `@crates/uteke-cli/src/config.rs`:
- Around line 440-450: The code writes raw user input into a TOML string by
directly interpolating namespace into *line = format!("namespace =
\"{namespace}\""), which will break for quotes, backslashes or newlines; fix by
serializing/escaping the namespace when composing the assignment (e.g. use
toml::to_string or toml::Value::String(namespace.clone()).to_string() to produce
a properly quoted/escaped TOML string) and replace the direct format call in the
loop (the lines/in_store_section branch that does *line = ...) and the two
insertion paths mentioned below so they all use the serialized value when
writing "namespace = " into the config.

In `@crates/uteke-cli/src/main.rs`:
- Around line 951-998: The normal remember path in the Commands::Remember
handler ignores the user-specified r#type because it calls uteke.remember which
currently uses a hardcoded "fact"; update the ordinary branch to forward the
chosen type the same way the contradiction branch doesβ€”pass
Some(r#type.as_str()) (or equivalent) into uteke.remember instead of leaving it
as None/hardcoded, so both remember_with_contradiction and remember consistently
respect the r#type argument.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 13702b13-b61b-4cdc-9fd2-e0e3439fc0d4

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between c2eeff0 and 1b716af.

β›” Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
πŸ“’ Files selected for processing (14)
  • .cora.yaml
  • .github/workflows/release.yml
  • CHANGELOG.md
  • Cargo.toml
  • README.md
  • crates/uteke-cli/src/config.rs
  • crates/uteke-cli/src/main.rs
  • crates/uteke-core/src/lib.rs
  • crates/uteke-core/src/memory/store.rs
  • crates/uteke-server/src/main.rs
  • website/src/routes/docs/cli-reference/+page.svelte
  • website/src/routes/docs/configuration/+page.svelte
  • website/src/routes/docs/multi-agent/+page.svelte
  • website/src/routes/docs/roadmap/+page.svelte

Comment thread .github/workflows/release.yml Outdated
Comment thread crates/uteke-cli/src/main.rs
Comment thread README.md Outdated
Comment on lines +191 to +193
<pre class="px-4 py-3 rounded-lg bg-[var(--color-surface)] border border-[var(--color-border)] text-sm font-mono overflow-x-auto"><code># Delete single memory
uteke forget <uuid> --confirm

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify unescaped placeholder tags inside docs code blocks
rg -nP '^\s*uteke\s+forget\s+<[^>]+>' website/src/routes/docs/cli-reference/+page.svelte
# Expected: current line with <uuid>; replace with escaped form to avoid HTML parsing issues.

Repository: ajianaz/uteke

Length of output: 91


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the exact Svelte markup around the reported lines
sed -n '170,210p' website/src/routes/docs/cli-reference/+page.svelte | cat -n

Repository: ajianaz/uteke

Length of output: 2575


Escape angle brackets in the CLI docs code example placeholder.

website/src/routes/docs/cli-reference/+page.svelte contains uteke forget <uuid> --confirm inside a <code> block; <uuid> gets treated as an HTML tag and won’t render correctly. Use &lt;uuid&gt;.

βœ… Suggested fix
-uteke forget <uuid> --confirm
+uteke forget &lt;uuid&gt; --confirm
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<pre class="px-4 py-3 rounded-lg bg-[var(--color-surface)] border border-[var(--color-border)] text-sm font-mono overflow-x-auto"><code># Delete single memory
uteke forget <uuid> --confirm
<pre class="px-4 py-3 rounded-lg bg-[var(--color-surface)] border border-[var(--color-border)] text-sm font-mono overflow-x-auto"><code># Delete single memory
uteke forget &lt;uuid&gt; --confirm
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@website/src/routes/docs/cli-reference/`+page.svelte around lines 191 - 193,
The code sample in the Pre/Code block in +page.svelte uses a raw "<uuid>" which
is parsed as an HTML tag and won't render; update the code example inside the
<pre> / <code> snippet to escape angle brackets (use &lt;uuid&gt; instead of
<uuid>) so the placeholder displays correctly in the CLI docs; locate the
example text in the component (the pre/code block containing "uteke forget
<uuid> --confirm") and replace the angle-bracketed placeholder with the escaped
HTML entities.

Comment on lines +100 to +103
[store]
path = "~/.uteke"
namespace = "default"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Fix migrated key name inconsistency in config migration example.

The migration snippet uses path, while the rest of this page documents store_path. Keep the migrated example aligned with the actual key.

πŸ“ Proposed fix
 [store]
-path = "~/.uteke"
+store_path = "~/.uteke"
 namespace = "default"
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[store]
path = "~/.uteke"
namespace = "default"
[store]
store_path = "~/.uteke"
namespace = "default"
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@website/src/routes/docs/configuration/`+page.svelte around lines 100 - 103,
The migration example uses the key name "path" but the rest of the docs and
config use "store_path"; update the migration snippet to use "store_path"
instead of "path" so the migrated key name is consistent. Locate the code block
that currently shows [store] with path = "~/.uteke" and change that line to
store_path = "~/.uteke" (ensure only the key name is changed, preserving the
namespace = "default" line and surrounding formatting).

@ajianaz
ajianaz force-pushed the chore/prepare-v0.0.4 branch 2 times, most recently from 2668a25 to 00b86d1 Compare May 31, 2026 14:42
- Fix all clippy warnings across workspace (uteke-cli, uteke-core, uteke-server)
- Fix rustfmt issues across workspace
- Remove unused Arc import in uteke-server
- Fix cosine_similarity placement after test module in uteke-core
- Fix config loop indexing in uteke-cli
- Add .cora.yaml with custom provider (glm-5.1)
- Install cora pre-commit hook (warn mode)
- Fix strip fallback in release workflow
- Add config migration docs to website
@ajianaz
ajianaz force-pushed the chore/prepare-v0.0.4 branch from 00b86d1 to dd820c1 Compare May 31, 2026 15:10
@ajianaz
ajianaz merged commit f8fae91 into develop May 31, 2026
7 of 8 checks passed
@ajianaz
ajianaz deleted the chore/prepare-v0.0.4 branch May 31, 2026 15:23
ajianaz added a commit that referenced this pull request Jun 4, 2026
* feat: add uteke-status pi extension

Pi extension that shows uteke memory stats in the footer status bar:
- 🧠 uteke: πŸ”₯3 hot | 🟑0 warm | ❄️0 cold (65 total)
- Auto-refreshes after memory operations (remember, forget, import, cleanup)
- Registers /uteke-stats command to manually refresh
- Registers /uteke command for quick stats/aging/doctor/tags

Install: copy to ~/.pi/agent/extensions/uteke-status/ or use pi install

* feat(uteke-status): v2 β€” cross-namespace stats + system prompt injection

- Query SQLite directly for cross-namespace totals (was only showing
  default namespace before)
- Add proper spacing between icons and numbers
- Inject system prompt via before_agent_start to remind agent to use
  uteke actively (remember, recall, search, save summaries)
- Simplified: removed /uteke command, kept /uteke-stats
- Uses sqlite3 CLI (pre-installed on macOS/Linux)

* feat: bulk memory operations (#43)

- forget <id> β€” now prompts for confirmation [y/N]
- forget --tag <tag> β€” delete all memories with a tag
- forget --cold β€” delete all cold (>30d or never accessed) memories
- forget --all β€” delete ALL memories in namespace
- All bulk ops require --confirm flag to execute
- Added BulkDeleteResult type with deleted count + IDs
- Added store methods: bulk_delete_by_tag, bulk_delete_cold,
  bulk_delete_all, count_by_tag
- Added Uteke methods: bulk_forget_by_tag, bulk_forget_cold,
  bulk_forget_all, store()

* ci: add cora AI code review composite action (#86)

- Add .github/actions/cora-review composite action (downloads cora-cli
  from GitHub Releases, fetches LLM secrets via Infisical OIDC, runs
  review on PR diff, uploads SARIF to Code Scanning, posts PR comment)
- Add cora-review job to CI workflow (runs after check/fmt/clippy/test
  pass, only on pull_request events)
- Add required permissions (security-events, pull-requests, id-token)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(ci): comment default, SARIF upload optional (#87)

- Post PR comment: always runs (default behavior)
- SARIF upload: opt-in via upload-sarif: 'true' input
- SARIF upload failure: continue-on-error (never blocks)
- Blocking: only error-level findings block merge

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(ci): resolve latest version via API before download (#89)

GitHub release download URL doesn't support 'latest' tag.
Resolve to actual tag via GitHub API first.

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat: smooth namespace switching and defaults (#82)

* feat: add uteke-status pi extension

Pi extension that shows uteke memory stats in the footer status bar:
- 🧠 uteke: πŸ”₯3 hot | 🟑0 warm | ❄️0 cold (65 total)
- Auto-refreshes after memory operations (remember, forget, import, cleanup)
- Registers /uteke-stats command to manually refresh
- Registers /uteke command for quick stats/aging/doctor/tags

Install: copy to ~/.pi/agent/extensions/uteke-status/ or use pi install

* feat(uteke-status): v2 β€” cross-namespace stats + system prompt injection

- Query SQLite directly for cross-namespace totals (was only showing
  default namespace before)
- Add proper spacing between icons and numbers
- Inject system prompt via before_agent_start to remind agent to use
  uteke actively (remember, recall, search, save summaries)
- Simplified: removed /uteke command, kept /uteke-stats
- Uses sqlite3 CLI (pre-installed on macOS/Linux)

* feat: bulk memory operations (#43)

- forget <id> β€” now prompts for confirmation [y/N]
- forget --tag <tag> β€” delete all memories with a tag
- forget --cold β€” delete all cold (>30d or never accessed) memories
- forget --all β€” delete ALL memories in namespace
- All bulk ops require --confirm flag to execute
- Added BulkDeleteResult type with deleted count + IDs
- Added store methods: bulk_delete_by_tag, bulk_delete_cold,
  bulk_delete_all, count_by_tag
- Added Uteke methods: bulk_forget_by_tag, bulk_forget_cold,
  bulk_forget_all, store()

* feat: smooth namespace switching and defaults (#45)

- Add `uteke namespace list` β€” list all namespaces with memory counts
- Add `uteke namespace stats <name>` β€” show stats for a namespace
- Add `uteke namespace switch <name>` β€” set default namespace in config
- Implement layered namespace resolution: CLI flag > env > config > default
- Fix broken `resolve_namespace` that referenced undefined variable
- Support UTEKE_NAMESPACE env var for per-session defaults
- Config file default_namespace persists across sessions

* feat: daemon/server mode for warm recall <50ms (#83)

* feat: add uteke-status pi extension

Pi extension that shows uteke memory stats in the footer status bar:
- 🧠 uteke: πŸ”₯3 hot | 🟑0 warm | ❄️0 cold (65 total)
- Auto-refreshes after memory operations (remember, forget, import, cleanup)
- Registers /uteke-stats command to manually refresh
- Registers /uteke command for quick stats/aging/doctor/tags

Install: copy to ~/.pi/agent/extensions/uteke-status/ or use pi install

* feat(uteke-status): v2 β€” cross-namespace stats + system prompt injection

- Query SQLite directly for cross-namespace totals (was only showing
  default namespace before)
- Add proper spacing between icons and numbers
- Inject system prompt via before_agent_start to remind agent to use
  uteke actively (remember, recall, search, save summaries)
- Simplified: removed /uteke command, kept /uteke-stats
- Uses sqlite3 CLI (pre-installed on macOS/Linux)

* feat: bulk memory operations (#43)

- forget <id> β€” now prompts for confirmation [y/N]
- forget --tag <tag> β€” delete all memories with a tag
- forget --cold β€” delete all cold (>30d or never accessed) memories
- forget --all β€” delete ALL memories in namespace
- All bulk ops require --confirm flag to execute
- Added BulkDeleteResult type with deleted count + IDs
- Added store methods: bulk_delete_by_tag, bulk_delete_cold,
  bulk_delete_all, count_by_tag
- Added Uteke methods: bulk_forget_by_tag, bulk_forget_cold,
  bulk_forget_all, store()

* feat: smooth namespace switching and defaults (#45)

- Add `uteke namespace list` β€” list all namespaces with memory counts
- Add `uteke namespace stats <name>` β€” show stats for a namespace
- Add `uteke namespace switch <name>` β€” set default namespace in config
- Implement layered namespace resolution: CLI flag > env > config > default
- Fix broken `resolve_namespace` that referenced undefined variable
- Support UTEKE_NAMESPACE env var for per-session defaults
- Config file default_namespace persists across sessions

* feat: daemon/server mode for warm recall <50ms (#54)

- Add uteke-server crate with HTTP API (tiny_http)
- Endpoints: /health, /remember, /recall, /search, /list, /forget, /stats, /namespaces
- Namespace support on all endpoints via JSON body
- CORS headers for cross-origin access
- Graceful shutdown on SIGINT (saves index, closes DB)
- Config: [server] section in uteke.toml (host, port, enabled)
- Benchmark: recall ~41ms (vs 2600ms CLI cold start)
- Binary: uteke-serve --host 127.0.0.1 --port 8767

* feat: auto-forget, temporal facts & contradiction detection (#51) (#84)

- Add temporal metadata: deprecated, valid_from, valid_until, memory_type
- Memory types: fact, procedure, preference, decision, context
- Contradiction detection on remember (--detect-contradiction flag)
  - Auto-deprecates old conflicting memories via vector similarity
  - Threshold calibrated for embeddinggemma-q4 model
- Prune command: uteke prune --ttl 30d --dry-run
  - Removes deprecated memories older than TTL
  - Dry-run mode for safe preview
- remember --type flag for memory classification
- DB migration: auto-adds new columns to existing stores
- All 22 tests pass

* feat: knowledge graph consolidation & deduplication (#52) (#85)

- Add consolidate command: uteke consolidate --threshold 0.90 --dry-run
- Detect near-duplicate memories via cosine similarity
- Merge duplicates: keeps newer, removes older, updates vector index
- Dry-run mode shows duplicate pairs without modifying store
- Add SimilarPair and ConsolidationResult types
- cosine_similarity helper for O(nΒ²) pairwise comparison
- Threshold configurable (default 0.90, recommend 0.60-0.70 for small models)
- All 22 tests pass

* feat: CLI auto-routes to server when enabled (#90)

- CLI detects running uteke-serve via HTTP health check
- When server.available, routes remember/recall/search/list/stats/forget via HTTP
- Recall latency: 21ms (vs 946ms CLI cold start) β€” 45x faster
- Fallback: if server not running, CLI works as before (cold start)
- Config: [server] enabled = true in uteke.toml
- All 22 tests pass

* chore: prepare v0.0.4 release (#91)

* chore: prepare v0.0.4 release

- Bump version 0.0.3 β†’ 0.0.4
- CHANGELOG: add v0.0.4 with all new features
- README: add server mode, consolidate, prune, namespace switch, fix 256d embedding
- CLI reference docs: add forget bulk, consolidate, prune, namespace, server mode
- Configuration docs: add server section, namespace resolution
- Roadmap: add v0.0.4 completed items, update next/future
- Multi-agent docs: add namespace switching section
- Release workflow: build both uteke + uteke-serve, updated release notes

* chore: fix clippy warnings, add cora review config

- Fix all clippy warnings across workspace (uteke-cli, uteke-core, uteke-server)
- Fix rustfmt issues across workspace
- Remove unused Arc import in uteke-server
- Fix cosine_similarity placement after test module in uteke-core
- Fix config loop indexing in uteke-cli
- Add .cora.yaml with custom provider (glm-5.1)
- Install cora pre-commit hook (warn mode)
- Fix strip fallback in release workflow
- Add config migration docs to website

* fix(ci): cora review exit code handling (#92)

- Update cora-cli to v0.1.2 (fixes spurious exit code 2)
- Add || true to cora review step so SARIF is always generated
- Blocking check still works via SARIF level analysis

* fix(ci): proper cora review error handling (#93)

- Replace || true with explicit exit code handling
- Exit code 0 (clean) and 2 (findings found) both proceed
- Other exit codes show ::warning with stderr log
- Empty SARIF produces warning instead of silent failure
- No more 2>/dev/null β€” errors are visible when unexpected

* fix(ci): dynamic release notes from CHANGELOG.md (#94)

- Extract changelog section via awk instead of hardcoded body
- Filter out bottom comparison links
- Printf-based footer to avoid YAML indentation leaking
- Warning annotation if CHANGELOG section not found
- No more manual workflow edits per release

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat(core): add UTEKE_HOME env var for custom data directory (#106)

- Add public uteke_home() in uteke-core β€” resolves data directory
- UTEKE_HOME set: uses that path directly (e.g. /data)
- UTEKE_HOME unset: falls back to ~/.uteke (zero breaking change)
- engine.rs: model path uses uteke_home() instead of dirs::home_dir()
- lib.rs: doctor model check uses uteke_home()
- uteke-server: DB path uses uteke_core::uteke_home()
- Remove unused dirs dependency from uteke-server

Closes #95

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* chore(docs): update roadmap with v0.0.5-v0.0.7 milestones (#103)

- v0.0.5: Docker & Deployment (5 issues)
- v0.0.6: Network & Auth (4 issues)
- v0.0.7: Cloud MVP (future)
- Backlog reorganized (6 items)
- Color-coded sections per version
- Descriptions for each milestone

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat(server): read uteke.toml config + smart server fallback (#107)

* feat(server): read uteke.toml config, default host 0.0.0.0

Server now reads [server] section from uteke.toml:
- Layered resolution: uteke_home/uteke.toml β†’ cwd/.uteke/uteke.toml
- Default host changed: 127.0.0.1 β†’ 0.0.0.0 (Docker-compatible)
- CLI --host/--port override config values
- Added toml dependency for config parsing

Also fixes smart server fallback (#104):
- CLI commands not supported via HTTP auto-fallback to local store
- No more error 'This command requires local store'
- Log message: 'Command not supported via server, using local store'

Closes #96
Closes #104

* fix(server): resolve type mismatch in load_uteke_toml path array

* style(server): apply cargo fmt

---------

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat(server): API parity β€” expanded remember, GET /memory endpoint (#108)

Expanded POST /remember to accept optional fields:
- type: fact, procedure, preference, decision, context
- valid_from, valid_until: temporal facts
- detect_contradiction: auto-deprecate conflicting memories

Added GET /memory?id=<uuid> endpoint:
- Returns full memory by ID
- 404 if not found

Updated --help to document new endpoint.

Closes #105

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat(docker): add multi-stage Dockerfile and .dockerignore (#109)

Dockerfile:
- Stage 1: download release binary + embedding model from HuggingFace
- Stage 2: runtime only (debian:bookworm-slim + binaries + model)
- ENV UTEKE_HOME=/data for volume mount
- EXPOSE 8767, ENTRYPOINT uteke-serve
- ARG VERSION and TARGET for build flexibility

.dockerignore:
- Excludes .git, target, node_modules, website, docs

Closes #97

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat(ci): Docker image build & push on release (#110)

* feat(docker): add multi-stage Dockerfile and .dockerignore

Dockerfile:
- Stage 1: download release binary + embedding model from HuggingFace
- Stage 2: runtime only (debian:bookworm-slim + binaries + model)
- ENV UTEKE_HOME=/data for volume mount
- EXPOSE 8767, ENTRYPOINT uteke-serve
- ARG VERSION and TARGET for build flexibility

.dockerignore:
- Excludes .git, target, node_modules, website, docs

Closes #97

* feat(ci): add Docker image build & push to release workflow

Multi-arch Docker build (linux/amd64 + linux/arm64):
- Triggered after release job completes
- Builds from Dockerfile with VERSION and TARGET build args
- Pushes to ghcr.io/ajianaz/uteke with semver tags + latest
- Uses GITHUB_TOKEN for GHCR auth (no new secrets needed)
- QEMU + buildx for cross-platform

Closes #99

---------

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* chore: prepare v0.0.5 release (#111)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(docker): remove pinned digest and update default version (#112)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(docker): remove pinned digest from runtime stage too (#113)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(docker): add curl retry and timeout for CI reliability (#114)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(ci): move downloads to host runner β€” buildx cannot access network (#115)

Buildx docker-container driver cannot reach github.com/huggingface.co,
causing consistent curl exit code 1. Move all downloads to CI host steps
and pass files via Docker context COPY instead.

- Dockerfile: COPY binaries/ and models/ from context, select by TARGETARCH
- release.yml: download step before build, single multi-platform push

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(ci): use build artifacts + lazy runtime model download (#116)

Primary: Docker job now depends on build-release (not release), gets
binaries via actions/download-artifact@v4 β€” no curl to github.com.

Fallback: Entrypoint checks if model exists at startup, downloads if
missing β€” works even if CI model bake step fails.

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(ci): find artifacts recursively β€” merge-multiple adds subdir (#117)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix(ci): remove --strip-components from tar extraction (#118)

The tar.gz archives contain uteke + uteke-serve at root level
(no directory prefix). --strip-components=1 was stripping the
filenames themselves, resulting in empty extraction.

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* refactor: adopt cora-review v2 β€” standalone workflow + hardened action (#119)

- Extract cora-review into its own workflow (.github/workflows/cora-review.yml)
  with dedicated concurrency group, 10-minute timeout, and scoped permissions
- Harden action.yml: pinned action SHAs, checksum verification on cora-cli
  download, retry logic for version resolution, empty-result handling
- Remove cora-review job and elevated permissions from ci.yml
  (CI pipeline now contains only Rust check/fmt/clippy/test/build)

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* fix: v0.0.6 patch & hardening (#146)

* fix: v0.0.6 patch & hardening β€” CI, Docker, API correctness

Closes #122, #123 (already done on develop), #124, #125, #126, #145

- ci.yml, release.yml: add FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 (#125)
- ci.yml, release.yml: remove unused musl-tools install (#145)
- release.yml: remove musl-tools apt step (#145)
- Dockerfile: add non-root USER directive with uteke user (#126)
- Dockerfile: create /data with correct ownership before USER switch
- types.rs: add #[serde(skip_serializing)] on Memory.embedding (#124)
- lib.rs: persist vector index after import() completes (#124)
- vector.rs: improve expect() panic message with dims and root cause hint (#124)
- .github/dependabot.yml: add Dependabot for cargo, github-actions, docker (#122)

* fix(test): update test_memory_types_serialization for skip_serializing embedding

The embedding field now uses #[serde(skip_serializing)], so the test
verifies that embedding is excluded from JSON output and that
deserialization produces an empty embedding (expected β€” embeddings are
populated programmatically via ONNX, not from JSON).

* fix: add serde(default) to skip_serializing embedding

skip_serializing without default causes deserialization error when
embedding field is missing from JSON. Adding default allows graceful
fallback to empty vec.

* release: v0.0.6 β€” patch & hardening

- CHANGELOG: add v0.0.6 entry, reorder all versions chronologically, consolidate link refs
- Cargo.toml: bump 0.0.5 β†’ 0.0.6

---------

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat: v0.0.7 β€” core stability (#157)

* feat: v0.0.7 β€” core stability (tag refactor, config wiring, tests)

#120 Tag storage: refactor all LIKE-based tag queries to json_each()
  - list(), unique_tags(), tags_with_counts(), count_tag(), rename_tag(),
    delete_tag(), bulk_delete_by_tag(), count_by_tag
  - tags_with_counts: N+1 β†’ single GROUP BY query
  - unique_tags: in-Rust JSON parse β†’ SQL json_each()
  - 11 new tag-related tests

#127 Config wiring: pass tier thresholds from config to core
  - Add TierConfig struct (hot_days, warm_days, hot_boost)
  - Uteke::open_with_tier() accepts custom tier config
  - MemoryTier::from_last_accessed() now takes configurable thresholds
  - main.rs passes config.tier.* to core
  - 7 new config tests (merge_from_file_all_sections, expand_tilde, etc.)

#129 Test coverage: +44 tests (22 β†’ 66 in store, 8 β†’ 25 in lib, 4 β†’ 15 in config)
  - Bulk operations: bulk_delete_by_tag, bulk_delete_cold, bulk_delete_all
  - Store operations: rename_tag, delete_tag, deprecate, tier_counts
  - Edge cases: search_content, find_aged, find_similar, pagination
  - Double insert, namespace isolation, empty results

#140 Namespace CLI: already implemented (NamespaceCommands::List)

Closes #120, #127, #129, #140

* fix: update old tests for new MemoryTier::from_last_accessed() signature

- Pass hot_days=7, warm_days=30 to old tier tests
- Remove dead count_tag() method (replaced by count_by_tag)

* fix: update all callers for tier_counts/bulk_delete_cold new signatures

Old tests called tier_counts(None) and bulk_delete_cold(None) with
1 arg, but sub-agent changed signatures to accept hot_days/warm_days.
Updated 5 test call sites.

* fix: correct test_path_in_memory and test_search_content_edge_cases

- test_path_in_memory: rusqlite may return Some for :memory: DB path
- test_search_content_edge_cases: SQLite LIKE is case-insensitive by default

* docs: fix configuration section in README (#128)

- Fix config search paths: .uteke/uteke.toml + ~/.uteke/uteke.toml
- Fix config format: proper TOML sections matching actual Config struct
- Remove non-existent --config flag from CLI reference
- Add all config sections: store, embedding, tier, logging, server

---------

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* release: v0.0.7 β€” core stability (#158)

CHANGELOG: add v0.0.7 entry with all changes
Cargo.toml: bump 0.0.6 β†’ 0.0.7

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* chore(deps): consolidate Dependabot bumps β€” 10 deps in 1 PR (#159)

Cargo deps:
- thiserror 1 β†’ 2 (API unchanged for our usage)
- dirs 5 β†’ 6 (home_dir() unchanged)
- toml 0.8 β†’ 1 (from_str() unchanged)
- uuid 1.23.1 β†’ 1.23.2 (patch)

GitHub Actions:
- docker/login-action v3 β†’ v4
- docker/metadata-action v5 β†’ v6
- actions/upload-artifact v4 β†’ v7
- Infisical/secrets-action v1.0.9 β†’ v1.0.16
- actions/setup-node v4 β†’ v6
- cloudflare/wrangler-action v3 β†’ v4

All changes reviewed β€” no breaking API impact for our usage.

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

* feat: release branch setup β€” main as release-only mirror (#168)

- Add install.sh at root with SHA256 checksum verification
- Add sync-main job to release.yml (develop β†’ main on every v* tag)
- Add SHA256 checksums generation to release job
- Enable Cora Review on PRs to main branch
- Update INSTALL.md to reference main/install.sh
- Update release notes template to use main/install.sh

Clones cora-cli #154/#155/#156 release branch pattern.

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>

---------

Co-authored-by: CTO Hermes <cto-hermes@users.noreply.github.com>
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