Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .bestpractices.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"english_justification": "README, CONTRIBUTING, SECURITY, PRIVACY, CHANGELOG, the docs/ tree and all issue discussion are written in English.",

"maintained_status": "Met",
"maintained_justification": "Actively maintained: v4.17.0 was released 2026-08-01, and releases have shipped continuously through the v4.x series: https://github.com/cdeust/Cortex/releases",
"maintained_justification": "Actively maintained: v4.17.1 was released 2026-08-02, and releases have shipped continuously through the v4.x series: https://github.com/cdeust/Cortex/releases",

"repo_public_status": "Met",
"repo_public_justification": "The repository is public and readable without an account: https://github.com/cdeust/Cortex",
Expand All @@ -51,10 +51,10 @@
"repo_distributed_justification": "git is a distributed version control system.",

"version_unique_status": "Met",
"version_unique_justification": "Every release carries a unique semantic version tag (latest v4.17.0): https://github.com/cdeust/Cortex/releases",
"version_unique_justification": "Every release carries a unique semantic version tag (latest v4.17.1): https://github.com/cdeust/Cortex/releases",

"version_semver_status": "Met",
"version_semver_justification": "Versions follow Semantic Versioning, tagged vMAJOR.MINOR.PATCH (v4.15.0, v4.16.0, v4.17.0): https://github.com/cdeust/Cortex/releases",
"version_semver_justification": "Versions follow Semantic Versioning, tagged vMAJOR.MINOR.PATCH (v4.16.0, v4.17.0, v4.17.1): https://github.com/cdeust/Cortex/releases",

"version_tags_status": "Met",
"version_tags_justification": "Each release has a corresponding git tag: https://github.com/cdeust/Cortex/tags",
Expand Down
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
},
"metadata": {
"description": "The Cortex family of Claude Code plugins: home of hypermnesia-mcp (the persistent-memory server formerly named cortex, renamed in v4.15.0 over a directory name collision), zetetic-team-subagents, and cortex-viz. The marketplace name stays cortex-plugins: it is the brand-level umbrella, while hypermnesia-mcp is one package inside it.",
"version": "4.17.0"
"version": "4.17.1"
},
"plugins": [
{
"name": "hypermnesia-mcp",
"source": "./",
"description": "Cortex — persistent memory and cognitive profiling for Claude Code (renamed from the 'cortex' plugin in v4.15.0 to match the PyPI/MCP-registry identity hypermnesia-mcp) — thermodynamic memory with heat/decay, intent-aware retrieval, biological plasticity, codebase intelligence, and cognitive profiling. 50 MCP tools (53 with the optional automatised-pipeline + prd-spec-generator integrations) with enriched schemas (visualization extracted to the standalone cortex-viz MCP). PostgreSQL + pgvector in CLI mode; automatic SQLite fallback in Cowork/sandboxed mode. v3.17.0 — autonomous per-project wiki: SessionStart auto-spawns a 6-hour consolidate cycle; a headless `claude -p` worker drains the curation-gap queue, calls codebase-intelligence MCP tools to ground each section in the real call graph, and authors missing anchor pages (architecture / services / api / data-flow / operations / decisions / PRD) per project from the source tree. 15 canonical scopes × 13 file sections; per-project dashboards under `wiki/_dashboards/`. Mermaid diagrams have a 🔍 lens with zoom + pan. Workflow graph with caller-qualified CALLS chains rendering full method-to-method dependencies (native tree-sitter, no AP required). Side panel humanized for non-technical users. Ingests codebase analysis (ai-automatised-pipeline) and PRDs (prd-spec-generator) into wiki + memory + knowledge graph. Docker image available.",
"version": "4.17.0",
"version": "4.17.1",
"author": {
"name": "Clement Deust",
"email": "admin@ai-architect.tools"
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hypermnesia-mcp",
"description": "Cortex — persistent memory for Claude Code that remembers across sessions automatically. Install and forget. Scientific retrieval backed by 97 published references. (Renamed from the 'cortex' plugin to match the PyPI/MCP-registry identity.)",
"version": "4.17.0",
"version": "4.17.1",
"author": {
"name": "Clement Deust",
"email": "admin@ai-architect.tools"
Expand Down
65 changes: 62 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,82 @@ jobs:
[ -n "$pg_ready" ] || { echo "postgres failed to become ready after 30 attempts" >&2; exit 1; }
PGPASSWORD=cortex psql -h localhost -U cortex -d cortex -c "SELECT version();"

# The network-hardening steps below mirror ci.yml's `test` job
# one-for-one (cache + retried prefetch + offline test run, per model).
# They are NOT optional here: this job runs the same suite on a tag
# push, but `ci.yml` triggers on `push: branches` + `pull_request`, so
# a tag never reaches it and every hardening pass CI received since
# 2026-07-27 skipped this file. Release run 30741657854 (v4.17.0) is
# what that divergence costs: the reranker fetch hung in `sock.connect`
# until pytest-timeout killed the suite, blocking all five downstream
# publish jobs on a tag whose tree had just passed 20 green checks on
# PR #334. Keep the two jobs in step — see ci.yml for the full
# per-incident rationale behind each step.
- name: Cache HuggingFace models
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/huggingface
key: ${{ runner.os }}-hf-all-MiniLM-L6-v2

# FlashRank bypasses HF_HUB_OFFLINE entirely: it fetches its ONNX model
# with a bare `requests.get(..., stream=True)` carrying no timeout, so a
# stalled connect blocks the thread instead of raising, and reranker.py's
# `except Exception` cannot engage against a hang.
- name: Cache FlashRank reranker model
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/flashrank
key: ${{ runner.os }}-flashrank-ms-marco-MiniLM-L-12-v2

- name: Install dependencies
# Hash-pinned from uv.lock (scripts/generate_pip_constraints.py).
run: |
pip install --require-hashes -r requirements/release.txt
pip install --no-deps -e .

# Retry with backoff and fail loudly (no continue-on-error): a transient
# blip must not leave the cache empty and cascade into a misleading test
# failure — or, worse here, into a silently degraded release gate.
- name: Pre-download embedding model
run: python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2', device='cpu')"
continue-on-error: true

run: |
for attempt in 1 2 3 4 5; do
python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2', device='cpu')" && exit 0
echo "HF pre-download attempt ${attempt} failed; retrying in $((attempt * 10))s" >&2
sleep $((attempt * 10))
done
echo "HF pre-download failed after 5 attempts" >&2
exit 1

# Deliberately runs WITHOUT CORTEX_RERANKER_OFFLINE: this is the one
# place allowed to download the model, so the test step below never can.
# `ensure_reranker_loaded` reports the load state instead of degrading
# silently, so a failed fetch fails this step rather than surfacing later
# as first-stage-only recall scores (the 2026-07-10 FlashRank incident).
- name: Pre-download reranker model
run: |
for attempt in 1 2 3 4 5; do
python -c "from mcp_server.core.reranker import ensure_reranker_loaded as e; s = e(); assert s.state == 'loaded', s" && exit 0
echo "FlashRank pre-download attempt ${attempt} failed; retrying in $((attempt * 10))s" >&2
sleep $((attempt * 10))
done
echo "FlashRank pre-download failed after 5 attempts" >&2
exit 1

# No tree-sitter cache/prefetch pair here, unlike ci.yml: requirements/
# release.txt deliberately omits tree-sitter + tree-sitter-language-pack
# (as it omits igraph/leidenalg/texttable), so the AST tests skip in this
# job and there is no grammar to fetch. Should release.txt ever gain that
# dependency, port ci.yml's three tree-sitter steps across with it — the
# lazy `get_parser()` download is a real mid-suite DownloadError
# (main-red, CI run 30592244731, 2026-07-31).
#
# Offline: every model is already cached by the steps above, so tests
# must never reach out mid-suite — deterministic and flake-free.
- name: Run tests
env:
HF_HUB_OFFLINE: "1"
TRANSFORMERS_OFFLINE: "1"
CORTEX_RERANKER_OFFLINE: "1"
run: pytest --tb=short -q

github-release:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [4.17.1] - 2026-08-02

### Fixed

- **The release workflow's test gate now carries ci.yml's network hardening, and v4.17.0's contents ship under this version** — `.github/workflows/release.yml`. v4.17.0 was tagged but **published nothing**: its `test` job hung and blocked all five downstream publish jobs, so no GitHub release, PyPI upload, or `.mcpb` bundle exists for it. Root cause is a trigger asymmetry, not a flake: `ci.yml` fires on `push: branches: [main]` + `pull_request` (ci.yml:4-8), so **a tag never reaches it** — every network-hardening pass CI absorbed since 2026-07-27 silently skipped `release.yml`, while both files kept running the same suite. Run 30741657854 is what that divergence cost: `test_recall_real_spell_by_name` → `pg_recall.py:443` → `reranker.py:109` → FlashRank's bare `requests.get(..., stream=True)`, which **carries no timeout**, so a stalled connect hung in `sock.connect` until pytest-timeout killed the suite — on a tree that had just passed 20 green checks on PR #334. `HF_HUB_OFFLINE` does not reach FlashRank's own fetch path, and `reranker.py`'s `except Exception` cannot engage against a hang that never raises. The `test` job now mirrors ci.yml:103-115,142-195 one-for-one — cache `~/.cache/flashrank` (matching `reranker_model.py:104-113`'s `reranker_cache_dir()`, which honours `$XDG_CACHE_HOME`), prefetch the reranker via `ensure_reranker_loaded()` asserting `state == 'loaded'` so a failed fetch fails the step instead of resurfacing as first-stage-only recall scores (the 2026-07-10 FlashRank incident), harden the HF prefetch to 5 retries with backoff and **drop `continue-on-error`** so a blip cannot leave the cache empty and cascade into a misleading failure, and run pytest under `HF_HUB_OFFLINE` / `TRANSFORMERS_OFFLINE` / `CORTEX_RERANKER_OFFLINE` so no download can happen mid-suite. ci.yml's three tree-sitter steps are **deliberately not ported**: `requirements/release.txt` omits tree-sitter and tree-sitter-language-pack (as it omits igraph, leidenalg and texttable), so the AST tests skip in this job and there is no grammar to fetch — porting them would have failed on ImportError. The corollary is recorded in the workflow itself: this gate tests a **narrower surface than CI**, and the three steps must follow if `release.txt` ever gains that dependency. Shipped as a new patch version rather than by moving the `v4.17.0` tag, because a tag executes the `release.yml` of **its own tree** — re-running v4.17.0 would replay the unhardened file — and rewriting a published tag would break the "tree bit-identical to ae633a87" property the v4.17.0 release decision rests on (house precedent: v3.15.2 abandoned → v3.15.3). No source change accompanies this fix; v4.17.1 carries the v4.17.0 tree plus the workflow.

## [4.17.0] - 2026-08-01

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<a href="LICENSE"><img src="assets/badge-license.svg" alt="License: MIT"></a>
<img src="assets/badge-python.svg" alt="Python 3.10+">
<img src="assets/badge-tests.svg" alt="tests passing">
<img src="assets/badge-references.svg" alt="97 referenced papers"> <img src="assets/badge-version.svg" alt="Version 4.17.0">
<img src="assets/badge-references.svg" alt="97 referenced papers"> <img src="assets/badge-version.svg" alt="Version 4.17.1">
<a href="https://www.bestpractices.dev/projects/13836"><img src="https://www.bestpractices.dev/projects/13836/badge" alt="OpenSSF Best Practices"></a>
<a href="https://mcptoplist.com/server/io.github.cdeust%2Fhypermnesia-mcp"><img src="assets/badge-mcp-toplist.svg" alt="MCP Toplist: Top 1.2% of 81,919 tracked MCP servers, July 2026"></a>
</p>
Expand Down
8 changes: 4 additions & 4 deletions assets/badge-version.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ deliberately absent; the ordering is the promise.

## Where the project is today

v4.17.0, released 2026-08-01. 52 standalone MCP tools (55 with the optional
v4.17.1, released 2026-08-02. 52 standalone MCP tools (55 with the optional
upstream integrations), 9 lifecycle hooks, 36 neuroscience-grounded mechanisms
against a 97-reference bibliography, running on a local SQLite store by
default or PostgreSQL + pgvector when configured. The OpenSSF Best Practices
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,5 @@
"type": "string"
}
},
"version": "4.17.0"
"version": "4.17.1"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hypermnesia-mcp",
"version": "4.17.0",
"version": "4.17.1",
"description": "Persistent memory and cognitive profiling for Claude Code",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "hypermnesia-mcp"
version = "4.17.0"
version = "4.17.1"
description = "Scientifically-grounded memory system based on computational neuroscience research"
readme = "README.md"
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions server.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
"url": "https://github.com/cdeust/Cortex",
"source": "github"
},
"version": "4.17.0",
"version": "4.17.1",
"packages": [
{
"registryType": "pypi",
"identifier": "hypermnesia-mcp",
"version": "4.17.0",
"version": "4.17.1",
"transport": {
"type": "stdio"
}
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.