Skip to content

Rank L0 recall, add forget/export, and ship an offline uvx install - #2

Merged
SherryLi-vc merged 13 commits into
mainfrom
cursor/recall-forget-packaging-readme-ce43
Oct 29, 2026
Merged

SherryLi-vc merged 13 commits into
mainfrom
cursor/recall-forget-packaging-readme-ce43

Conversation

@SherryLi-vc

@SherryLi-vc SherryLi-vc commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Summary

UAT on 280115b was No-Go for packaging. This revision is 2.2.1.

  • B1. mcp is >=1.0.0,<2. A clean wheel install now resolves mcp 1.30.0, and --help, setup, and the MCP handshake succeed. CI job smoke builds the wheel, installs it into a fresh venv with no lockfile, and runs those checks.
  • B2. The distribution name is strata-memory-mcp again. Docs, the skill, and setup snippets say uvx strata-memory-mcp and uvx --from 'strata-memory-mcp[local]' strata-memory-mcp. Until publish, they also document uvx --from git+https://github.com/SherryLi-vc/strata-memory strata-memory-mcp. They tell readers not to run uvx strata-memory, which is a different PyPI project.
  • H1. Snippets do not set STRATA_EMBEDDING_PROVIDER. The Hermes wrapper no longer exports local over a saved config. The index writes embedder.json (provider, model, dimension, backend). A non-empty index with a missing or different stamp returns EMBEDDER_UNSTAMPED or EMBEDDER_MISMATCH and does not mix vectors. Rebuild is the way to accept a new embedder.
  • M1. forget_memory deletes the supersede chain by default. include_chain=false deletes only the matched row.
  • M2. Audit rows for forgotten ids stay. before_snap, after_snap, and summary are replaced with [redacted].
  • M3. Forget and export return total, remaining, and next_offset. Page size is capped at 2000. Export still defaults to 500 per page.
  • M4. scripts/recall_benchmark.py reports literal overlap and paraphrase separately, and marks the semantic backend not_run when fastembed is absent. Literal overlap is 4/4. Paraphrase is 0/4 on the lexical ranker. That 4/4 is shared surface tokens, not paraphrase quality.
  • M5. A saved config that only sets provider uses that provider's model, URL, and dimension. A palace file with no embedding block stays on SiliconFlow. A missing config file still defaults to local. The effective provider, model, and backend are logged.
  • M6. A semantic local model that cannot download fails with a short error naming STRATA_LOCAL_EMBED_BACKEND=hash. Hub connect timeouts are tightened. STRATA_EMBEDDING_HASH_FALLBACK=1 opts into hashing after a failed download. The no-extra install still uses hashing and does not download.
  • M7. strata_init and strata_doctor include provider, model, and backend.
  • M8. The Claude Desktop snippet is JSON only.
  • N1. strata_rebuild_index keeps the open Chroma client, clears embedder.json first, and replaces the collection in place. It writes a new stamp only when every row indexes and the vector count matches. A failed rebuild returns REBUILD_INCOMPLETE and does not stamp a partial index.
  • N2. After a forget page, remaining matches are recounted. While any remain, next_offset is 0, so a caller can drain a set larger than one page. Covered by a 4,100-row regression.

Tests

uv sync --extra dev, then .venv/bin/pytest -q: 76 passed. ruff check . passed. ruff format --check . passed after a formatting follow-up on strata_memory/pipeline/forget.py (08ee372).

Known issues

  • H2. With an empty tenant_id, vector recall can return another tenant's rows for the same user_id, because that query filters only on user_id.

Nothing was published. The TestPyPI workflow was not run.

Open in Web Open in Cursor 

cursoragent and others added 13 commits October 28, 2026 17:29
L0 cards were prepended with score 1.0 and ignored limit. They now share one relevance ranking with every other tier, include_l0 is on the MCP tool, and forget/export stay inside tenant/user scope. uvx strata-memory starts the server with a local embedder and no API key.

Co-authored-by: SherryLi-vc <SherryLi-vc@users.noreply.github.com>
A clean install was pulling mcp 2.x and crashing, and uvx strata-memory installs a third-party package. The distribution name is strata-memory-mcp again. Host snippets no longer override a saved embedder, and the index refuses mixed vectors.

Co-authored-by: SherryLi-vc <SherryLi-vc@users.noreply.github.com>
Co-authored-by: SherryLi-vc <SherryLi-vc@users.noreply.github.com>
Rebuild replaces the Chroma collection via the existing client, clears the stamp first, and refuses to stamp on index failure or vector-count mismatch. Forget recounts remaining matches and returns next_offset=0 while matches remain. Adds legacy/failed rebuild tests and a 4,100-row pagination regression test.
Co-authored-by: SherryLi-vc <SherryLi-vc@users.noreply.github.com>
…ly on unstamped indexes

N7: strata_rebuild_index(tenant_id=...) reset the whole collection and re-added
one tenant, dropping every other tenant's vectors while returning ok. It now
deletes and re-adds only that tenant's vectors and checks the others are
untouched. An unstamped or mismatched index escalates to a full rebuild
(scope=all) because the other vectors are unusable anyway.

N8: strata_doctor compares indexable SoT ids with vectors present
(vector_coverage / INDEX_INCOMPLETE). A fully failed rebuild now reports
degraded instead of healthy; a partial gap is a warning. Also covers a stamp
whose collection is missing (N9).

N1 residual: recall_context on an index without an embedder stamp (pre-2.2.1)
falls back to lexical recall with fusion.vector_skipped and a warning instead
of failing with EMBEDDER_UNSTAMPED. EMBEDDER_MISMATCH still fails. README and
README.zh-CN gain an upgrade section; CHANGELOG updated.
…ironments

Every user- or host-visible version now comes from strata_memory.__version__
(2.2.1): MCP handshake server_version, strata_init, the CLI, new configs,
migration configs, and the skill metadata. tests/test_version_consistency.py
keeps pyproject, __version__, CHANGELOG and SKILL.md in sync.

release.yml follows the PyPA Trusted Publishing guide: a build job (version
check against the release tag, uv build, twine check --strict, wheel smoke
test, artifact), then publish-testpypi (workflow_dispatch, environment
testpypi, .devN version) and publish-pypi (release published, environment
pypi). Only the publish jobs get id-token: write; no secrets are referenced.
testpypi.yml is folded in so one workflow file backs both pending publishers.
DEVELOPMENT.md lists the exact pending-publisher fields.
…it log

H2: recall filtered tenant only when it was non-empty, in list_active, FTS and
the Chroma where clause, so tenant_id='' returned other tenants' rows for the
same user_id. Candidates are now checked against the SoT row's tenant_id and
user_id, and the vector query always filters on tenant_id.

N5: the recall_context audit summary kept query[:80], which forget never
reaches. It now stores q_len, hits and tokens. Legacy q=<text> rows are
rewritten to q=[redacted] on open with secure_delete and a WAL checkpoint;
a test checks the bytes are gone from the database files.
README, README.zh-CN, SKILL.md, setup --host snippets and the shipped JSON
templates now use uvx --from git+https://github.com/SherryLi-vc/strata-memory.
uvx strata-memory-mcp is marked coming soon. The [local] extra uses the
PEP 508 form 'strata-memory-mcp[local] @ git+...'. A test fails on any bare
PyPI command outside the coming-soon note, and checks that README,
README.zh-CN, SKILL.md and DEVELOPMENT.md state 13 tools and list every tool
registered in server.py.
commit_memory called chroma.count() and rewrote embedder.json on every
write. It now reads the stamp first: a matching stamp needs neither a count
nor a rewrite; count() runs only when there is no stamp (an empty unstamped
index may be stamped, a non-empty one is refused as before). A stamp removed
by another process is still noticed because the file is read every time.

cProfile, 1k commits, hash embedder, in-process handler: count() was 1.38 s
of 31.5 s (4.4%) and write_stamp 0.32 s; chroma upsert was 19.3 s (61%).
After: 1 count call, no stamp rewrite. Throughput change is within noise
(median 37.3 -> 37.3/s over three interleaved runs); upsert dominates.
L1: strata_doctor kept status=ok when it listed only warnings, so healthy
was false while status said ok. status is now degraded whenever there is
an issue, and severity (none/warn/error) keeps warnings and errors apart.
commit_memory now masks detected secrets by default (on_secret=redact):
each secret becomes [redacted:<kind>] before the claim is validated,
hashed, stored, embedded or audited, and the response lists
secrets_redacted. on_secret=reject (config.json or STRATA_ON_SECRET)
keeps the old SECRET_DETECTED refusal. Invalid values are refused.

The rules live in governance/secrets.py and are written for this project
from the providers' documented token formats (AWS, GitHub, GitLab, Slack,
Stripe, Google, sk- keys, npm, PyPI, JWT, private key blocks, passwords,
bearer tokens, URL credentials). The rule families were scoped against
gitleaks (MIT) and detect-secrets (Apache-2.0); no code or regex is copied.
The quality kernel, CBT redaction, hygiene, doctor and migration share them.
Hygiene previews and migration skip reports no longer echo a raw secret.

recall_context marks a cut summary with ' …[truncated]' and
summary_truncated, and reports truncated plus truncation details: scan
limit reached, cards dropped by the token budget, summaries cut.
Every uses: in ci.yml and release.yml points at the commit of the newest
tag in the major already in use, with the version in a comment:
checkout v4.4.0, setup-uv v3.2.4, upload-artifact v4.6.2,
download-artifact v4.3.0, gh-action-pypi-publish v1.14.3 (release/v1).
uv is pinned to 0.13.6 instead of latest. A test enforces both.
@SherryLi-vc
SherryLi-vc merged commit 21bc7cf into main Oct 29, 2026
4 checks passed
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.

2 participants