diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 122d5152..b915511f 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,14 +5,14 @@ "email": "admin@ai-architect.tools" }, "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.", + "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 hypermnesia-mcp-viz. The marketplace name stays cortex-plugins: it is the brand-level umbrella, while hypermnesia-mcp is one package inside it.", "version": "4.17.2" }, "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.", + "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 + ai-architect-mcp-spec integrations) with enriched schemas (visualization extracted to the standalone Hypermnesia MCP Viz server). 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 (ai-architect-mcp-spec) into wiki + memory + knowledge graph. Docker image available.", "version": "4.17.2", "author": { "name": "Clement Deust", @@ -58,13 +58,14 @@ "category": "productivity" }, { - "name": "cortex-viz", + "name": "hypermnesia-mcp-viz", "source": { "source": "github", - "repo": "cdeust/cortex-viz" + "repo": "cdeust/cortex-viz", + "sha": "1c1940e278979f35cdecea6146d7fb5f749907e9" }, - "description": "Standalone visualization MCP for Cortex β a live neural-graph galaxy of every project, file, symbol, memory, discussion and wiki page, plus a per-session execution trace, a consolidation kanban, and a curated knowledge/wiki browser. Read-only bridge over Cortex's shared PostgreSQL store and the ~/.claude artifacts; it renders, it never remembers. Restores the open_visualization / get_methodology_graph / query_workflow_graph tools removed from Cortex 3.21.0; launch with /cortex-visualize.", - "version": "2.8.0", + "description": "Canonical Claude Code publication for the standalone Hypermnesia MCP Viz server β a live neural-graph galaxy of every project, file, symbol, memory, discussion and wiki page, plus a per-session execution trace, a consolidation kanban, and a curated knowledge/wiki browser. Read-only bridge over Cortex's shared PostgreSQL store and the ~/.claude artifacts; it renders, it never remembers. Restores the open_visualization and get_methodology_graph tools removed from Cortex; launch with /cortex-visualize.", + "version": "3.0.0", "author": { "name": "Clement Deust", "email": "admin@ai-architect.tools" @@ -82,6 +83,24 @@ ], "category": "productivity" }, + { + "name": "cortex-viz", + "source": "./plugins/cortex-viz-deprecated", + "description": "DEPRECATED β renamed to hypermnesia-mcp-viz in v3.0.0. This frozen, nonfunctional migration shim has no MCP server or tools; it only announces the replacement at session start. Uninstall cortex-viz@cortex-plugins, refresh this marketplace, then install hypermnesia-mcp-viz@cortex-plugins. The repository remains cdeust/cortex-viz; only the marketplace plugin identity changed.", + "version": "2.8.0", + "author": { + "name": "Clement Deust", + "email": "admin@ai-architect.tools" + }, + "homepage": "https://github.com/cdeust/cortex-viz", + "repository": "https://github.com/cdeust/cortex-viz", + "license": "MIT", + "keywords": [ + "deprecated", + "visualization" + ], + "category": "productivity" + }, { "name": "zetetic-team-subagents", "source": { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aee76b67..4efd766e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -207,6 +207,23 @@ jobs: # silently fall back. Raise the floor when coverage rises. run: pytest --cov=mcp_server --cov-report=xml --cov-report=term-missing --cov-fail-under=82 + # Match the primary Claude and additive Codex client identities against + # a real, explicitly configured PostgreSQL instance. Explicit targets + # cannot fall back, so successful memory_stats calls prove PostgreSQL + # was selected for both host contracts. + - name: Verify Claude and Codex PostgreSQL-first MCP contracts + if: matrix.python-version == '3.12' + env: + CORTEX_RUNTIME: cowork + HF_HUB_OFFLINE: "1" + TRANSFORMERS_OFFLINE: "1" + CORTEX_RERANKER_OFFLINE: "1" + run: >- + python scripts/verify_mcp_hosts.py + --clients claude-code codex-cli --profiles lean + --storage-selection auto + -- hypermnesia-mcp + # The advertised test count is the one claim the static gate cannot check # without collecting the suite, so it is checked in the job that already # has the suite installed. `--collect-only` re-collects (~seconds) rather @@ -432,13 +449,17 @@ jobs: "$cli_bin/codex" plugin list --json \ | python -c 'import json,sys; d=json.load(sys.stdin); p=[x for x in d.get("installed",[]) if x.get("pluginId")=="hypermnesia-mcp-codex@cortex-codex-plugins"]; assert len(p)==1, p; assert p[0]["installed"] and p[0]["enabled"]' "$cli_bin/codex" mcp list --json \ - | python -c 'import json,sys; ss=[s for s in json.load(sys.stdin) if s.get("name")=="cortex"]; assert len(ss)==1, ss; s=ss[0]; assert s["startup_timeout_sec"]==180.0, s; assert s["transport"]["command"]=="uvx", s' + | python -c 'import json,sys; ss=[s for s in json.load(sys.stdin) if s.get("name")=="cortex"]; assert len(ss)==1, ss; s=ss[0]; assert s["startup_timeout_sec"]==180.0, s; assert s["transport"]["command"]=="uvx", s; assert s["transport"]["env"]["CORTEX_RUNTIME"]=="cowork", s' mapfile -t plugin_command < <( python -c 'import json; s=json.load(open("plugins/hypermnesia-mcp-codex/.mcp.json"))["mcpServers"]["cortex"]; print(s["command"]); print(*s["args"], sep="\n")' ) plugin_timeout="$( python -c 'import json; print(json.load(open("plugins/hypermnesia-mcp-codex/.mcp.json"))["mcpServers"]["cortex"]["startup_timeout_sec"])' )" + plugin_runtime="$( + python -c 'import json; print(json.load(open("plugins/hypermnesia-mcp-codex/.mcp.json"))["mcpServers"]["cortex"]["env"]["CORTEX_RUNTIME"])' + )" + CORTEX_RUNTIME="$plugin_runtime" \ UV_CACHE_DIR="$RUNNER_TEMP/cortex-codex-cold-uv-cache" \ UV_TOOL_DIR="$RUNNER_TEMP/cortex-codex-cold-uv-tools" \ PYTHONPATH="$GITHUB_WORKSPACE" \ @@ -446,6 +467,7 @@ jobs: --timeout "$plugin_timeout" --clients codex-cli --profiles lean \ --command-includes-profile \ --allow-bootstrap-network \ + --storage-selection auto \ -- "${plugin_command[@]}" test-windows: diff --git a/.mcpbignore b/.mcpbignore index 09a59304..d8d7e888 100644 --- a/.mcpbignore +++ b/.mcpbignore @@ -55,6 +55,7 @@ commands/ skills/ plugins/hypermnesia-mcp-codex/ plugins/cortex-deprecated/ +plugins/cortex-viz-deprecated/ scripts/ docker/ Dockerfile diff --git a/CHANGELOG.md b/CHANGELOG.md index d6b0b02d..f6beeb2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,26 @@ adheres to [Semantic Versioning](https://semver.org/). exact 10-tool `lean` profile. Its 180-second startup ceiling is backed by a clean-cache `uvx` lifecycle measured at 110.46 seconds locally (macOS 26.5.1 arm64, uv 0.8.19) and 23.87 seconds on `ubuntu-latest` CI. This is additive: - Claude Code remains the primary integration and keeps its complete profile, - lifecycle hooks, custom agent, marketplace, and installation path unchanged. + Claude Code remains the primary integration and keeps its primary plugin + manifest, complete profile, lifecycle hooks, custom agent, and installation + path unchanged. Its shared marketplace catalog changes only for the + visualization-plugin migration described below. +- **Breaking visualization-plugin publication rename, with migration shim.** + The canonical Claude Code publication is + `hypermnesia-mcp-viz@cortex-plugins` 3.0.0, sourced from the unchanged + `cdeust/cortex-viz` repository at exact commit + `1c1940e278979f35cdecea6146d7fb5f749907e9`. Existing installs must uninstall + `cortex-viz@cortex-plugins`, refresh `cortex-plugins`, and install + `hypermnesia-mcp-viz@cortex-plugins`. The former identity remains as a + frozen 2.8.0 migration shim that only prints those instructions; it + registers no MCP server or tools. Claude's composed tool names also change: + `mcp__plugin_cortex-viz_cortex-viz__open_visualization` becomes + `mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__open_visualization`, + and `mcp__plugin_cortex-viz_cortex-viz__get_methodology_graph` becomes + `mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__get_methodology_graph`. + Current companion tables, MCP examples, and API/module documentation now use + `hypermnesia-mcp-viz` and `ai-architect-mcp-spec`; retired names remain only + in explicit migration or historical material. - **Hook-free MCP protocol and host-configuration gates.** CI now starts the installed production stdio entry point under representative Claude, Gemini, and Codex client identities, completes the MCP lifecycle for both the full diff --git a/README.md b/README.md index 6fe8703b..861285dd 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@
Part of a four-piece stack β each runs standalone; together they cover what an agent forgets, can't see, and can't verify. Full comparison β
automatised-pipeline β the repo as a queryable code graph (callers, blast radius, execution paths), so agents stop re-reading files; Cortex ingests it via ingest_codebase / change_impact
- prd-spec-generator β verifies a spec rather than only generating one; standalone, or a CI gate over spec-kit / Kiro / BMAD output
+ ai-architect-mcp-spec β verifies a spec rather than only generating one; standalone, or a CI gate over spec-kit / Kiro / BMAD output
zetetic-team-subagents β 97 sourced reasoning patterns as specialist agents, each with its own scoped Cortex memory
- cortex-viz β read-only visualization MCP (galaxy graph, execution trace, wiki browser) over this same store Β· cortex-beam-abstain β retrieval abstention model for RAG
+ hypermnesia-mcp-viz β read-only visualization MCP (galaxy graph, execution trace, wiki browser) over this same store Β· cortex-beam-abstain β retrieval abstention model for RAG
@@ -62,6 +62,10 @@ claude plugin marketplace add cdeust/Cortex claude plugin install hypermnesia-mcp ``` > **Upgrading from the `cortex` plugin?** The plugin was renamed `hypermnesia-mcp` in v4.15.0 (a community-directory name collision with an unrelated `cortex` plugin): `claude plugin uninstall cortex && claude plugin install hypermnesia-mcp` β your memories and configuration are untouched, storage paths do not change. +> +> **Upgrading from `cortex-viz@cortex-plugins`?** Its Claude Code marketplace identity was renamed in v3.0.0. Run `claude plugin uninstall cortex-viz@cortex-plugins`, then `claude plugin marketplace update cortex-plugins`, then `claude plugin install hypermnesia-mcp-viz@cortex-plugins`. The retained `cortex-viz@cortex-plugins` item is a frozen, nonfunctional migration shim: it only prints this notice and exposes no MCP server or tools. The repository remains `cdeust/cortex-viz`; only its marketplace plugin identity changed. +> +> Claude tool allowlists, hooks, skills, and agents must migrate both composed names: `mcp__plugin_cortex-viz_cortex-viz__open_visualization` becomes `mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__open_visualization`, and `mcp__plugin_cortex-viz_cortex-viz__get_methodology_graph` becomes `mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__get_methodology_graph`. That is the whole install β zero configuration, no PostgreSQL, no system packages. The postInstall provisions Python dependencies and selects the local **SQLite** store (`~/.claude/methodology/memory.db`); the store schema auto-creates on first use. The embedding model is *not* downloaded at install time β it fetches lazily on first use (~100 MB, one-time; see [PRIVACY.md](PRIVACY.md)) and runs fully offline afterwards. The plugin path registers all lifecycle hooks (session-start context injection, per-prompt auto-recall, auto-capture, compaction checkpointing, the autonomous wiki cycle) and the `/cortex-setup-project` command. @@ -162,7 +166,9 @@ Or add it to `~/.gemini/settings.json` directly: **OpenAI Codex and ChatGPT desktop β native local plugin (recommended).** The repository now carries an isolated Codex marketplace and an exact 10-tool lean MCP surface. Claude Code remains the primary integration and retains its -automatic hooks, custom agent, full tool profile, and unchanged marketplace. +automatic hooks, custom agent, and full tool profile. Its shared marketplace +catalog changes only for the pinned `hypermnesia-mcp-viz` 3.0.0 publication +and the frozen `cortex-viz` migration shim. Pre-install the same published package once so the plugin's first `uvx` handshake can reuse the local uv cache instead of spending its startup budget downloading the Python environment. The bundled server also declares a @@ -270,7 +276,7 @@ Cortex needs **no configuration** to run β the SQLite backend is the default a \* The single-click bundle pins the backend to `sqlite` through the manifest. If you run the server directly (clone / Docker) without setting the variable, the underlying code default is `auto` β it tries PostgreSQL and falls back to SQLite. -That's the entire surface most users touch. Both backends expose the **same 52 memory tools** (55 with the optional automatised-pipeline + prd-spec-generator integrations) and the same retrieval contract; PostgreSQL adds server-side PL/pgSQL fusion and HNSW indexing that pays off at very large scale. Every other knob uses the `CORTEX_MEMORY_` prefix β see `mcp_server/infrastructure/memory_config.py`. +That's the entire surface most users touch. Both backends expose the **same 52 memory tools** (55 with the optional automatised-pipeline + ai-architect-mcp-spec integrations) and the same retrieval contract; PostgreSQL adds server-side PL/pgSQL fusion and HNSW indexing that pays off at very large scale. Every other knob uses the `CORTEX_MEMORY_` prefix β see `mcp_server/infrastructure/memory_config.py`. --- @@ -329,7 +335,7 @@ You rarely call these by hand: the lifecycle hooks (plugin install) inject the r **v3.23.0 β single-click bundle + registry-indexer build fix.** Cortex now ships as an MCP bundle (`.mcpb`) with a `uv` runtime and a selectable storage backend β **SQLite by default, PostgreSQL optional** β so it installs in one click with zero setup. Also: a `neuro-cortex-memory` console script so `uv run neuro-cortex-memory` resolves from a checkout; registry indexers that build with `uv sync` and launch via that script now start the server and register all standalone tools **without** a PostgreSQL connection (so `tools/list` answers inside a DB-less container). -**v3.21.0 β visualization extracted to cortex-viz.** The entire visualization stack β the galaxy graph, execution trace, the Knowledge / Board / Wiki / Pipeline views, and their HTTP server β moves to a standalone companion MCP, **[cortex-viz](https://github.com/cdeust/cortex-viz)**, which reads this same store read-only. Cortex is a focused memory engine again (β50k lines). **Breaking:** the `open_visualization`, `get_methodology_graph`, and `query_workflow_graph` MCP tools are removed from Cortex β install cortex-viz to get them back (its `/cortex-visualize` skill replaces the old one). 46 MCP tools remain; no memory, retrieval, or wiki behaviour changed; full suite green (3214 tests). +**v3.21.0 β visualization extracted to cortex-viz.** The entire visualization stack β the galaxy graph, execution trace, the Knowledge / Board / Wiki / Pipeline views, and their HTTP server β moves to a standalone companion MCP, **[cortex-viz](https://github.com/cdeust/cortex-viz)**, which reads this same store read-only. Cortex is a focused memory engine again (β50k lines). **Breaking:** the `open_visualization`, `get_methodology_graph`, and `query_workflow_graph` MCP tools are removed from Cortex β install the canonical `hypermnesia-mcp-viz` Claude Code plugin to get them back (its `/cortex-visualize` skill replaces the old one). 46 MCP tools remain; no memory, retrieval, or wiki behaviour changed; full suite green (3214 tests). β **[Full changelog and release notes](https://github.com/cdeust/Cortex/releases)** @@ -475,7 +481,7 @@ cortex:anchor({ content: "We're using event-sourcing. All state changes go throu Anchored memories get maximum protection β they always survive compaction, no matter what. -> The compaction checkpoint, session-start injection, and the autonomous wiki cycle are **lifecycle hooks** registered by the Claude Code plugin install. The single-click `.mcpb` bundle is a Directory connector β it delivers the 52 memory tools but **no hooks** (the MCPB format carries none). For the automatic session-lifecycle memory (session-start injection, auto-capture, compaction checkpointing, the autonomous wiki cycle), install the Claude Code plugin (see [More options](#getting-started)); the plugin also auto-registers the 3 upstream-integration tools when automatised-pipeline / prd-spec-generator are present (55 total). +> The compaction checkpoint, session-start injection, and the autonomous wiki cycle are **lifecycle hooks** registered by the Claude Code plugin install. The single-click `.mcpb` bundle is a Directory connector β it delivers the 52 memory tools but **no hooks** (the MCPB format carries none). For the automatic session-lifecycle memory (session-start injection, auto-capture, compaction checkpointing, the autonomous wiki cycle), install the Claude Code plugin (see [More options](#getting-started)); the plugin also auto-registers the 3 upstream-integration tools when automatised-pipeline / ai-architect-mcp-spec are present (55 total). --- @@ -506,7 +512,7 @@ Every page is editable in place in a full scientific writing environment β the - **LaTeX math** via KaTeX, **BibTeX citations** (`[@friston2010]` β `(Friston 2010)` with an auto APA bibliography), and **figure / equation / table auto-numbering** with cross-refs. - **Pandoc export** β one click to PDF (via LaTeX), TEX, DOCX, or HTML. Journal-submittable from the same source. -> The wiki's editor, galaxy graph, and views render through the standalone **[cortex-viz](https://github.com/cdeust/cortex-viz)** MCP, which reads this same store read-only. +> The wiki's editor, galaxy graph, and views render through the standalone **[hypermnesia-mcp-viz](https://github.com/cdeust/cortex-viz)** MCP, which reads this same store read-only. --- @@ -533,9 +539,9 @@ Cortex fixes what an agent **forgets**. Three sibling MCP servers fix what it ** | | The problem it solves | Install it when | Related work | |---|---|---|---| | **[automatised-pipeline](https://github.com/cdeust/automatised-pipeline)** | Your agent answers structural questions ("who calls this?", "what breaks if I change it?") by re-reading files, burning context and missing cross-file callers. Indexes the repo into a property graph: call/import resolution, Leiden communities, hybrid BM25+TF-IDF search, impact analysis. | Refactoring, root-cause work, or any repo big enough that `grep` stops being an answer. | [codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp) covers far more languages (158). automatised-pipeline is narrower but **qualifies every impact answer as `exact` or `lower-bound`** instead of presenting a possibly-incomplete list as complete. | -| **[prd-spec-generator](https://github.com/cdeust/prd-spec-generator)** | Specs pass review, then the implementation quietly contradicts them. Turns a feature description into a 9-file PRD and *verifies* it β deterministic Hard Output Rules plus multi-judge consensus calibrated against external oracles (schema / math / code). | You already write specs and want a gate that fails, not a template that hopes. | [spec-kit](https://github.com/github/spec-kit), [BMAD](https://github.com/bmad-code-org/BMAD-METHOD) and Kiro **generate** specs. This **verifies** them β it runs as a CI gate over their output rather than replacing them. | +| **[ai-architect-mcp-spec](https://github.com/cdeust/ai-architect-mcp-spec)** | Specs pass review, then the implementation quietly contradicts them. Turns a feature description into a 9-file PRD and *verifies* it β deterministic Hard Output Rules plus multi-judge consensus calibrated against external oracles (schema / math / code). | You already write specs and want a gate that fails, not a template that hopes. | [spec-kit](https://github.com/github/spec-kit), [BMAD](https://github.com/bmad-code-org/BMAD-METHOD) and Kiro **generate** specs. This **verifies** them β it runs as a CI gate over their output rather than replacing them. | | **[zetetic-team-subagents](https://github.com/cdeust/zetetic-team-subagents)** | Subagents that assert confidently instead of citing. 11 problem-shaped skills over 97 sourced reasoning patterns (Curie to Toulmin), plus a pre-commit gate that blocks unsourced constants. | You want "I don't know" to be an available answer, and every constant in your code to trace to a paper or a benchmark. | Collections like [wshobson/agents](https://github.com/wshobson/agents) organise agents **by role**. These are organised **by problem shape**, and each carries its epistemic method and sources. | -| **[cortex-viz](https://github.com/cdeust/cortex-viz)** | Memory you can't inspect is memory you can't trust. Read-only galaxy graph, execution trace, and wiki browser over this same store. | You want to see what Cortex actually kept, and why. | β | +| **[hypermnesia-mcp-viz](https://github.com/cdeust/cortex-viz)** | Memory you can't inspect is memory you can't trust. Read-only galaxy graph, execution trace, and wiki browser over this same store. | You want to see what Cortex actually kept, and why. | β | --- @@ -579,7 +585,7 @@ The full per-mechanism evidence lives in the thermodynamic paper (Β§6.3); the BE ## Security -Runs **100% locally** β MCP over stdio, the storage backend (SQLite file or PostgreSQL on localhost) never leaves your machine (the optional [cortex-viz](https://github.com/cdeust/cortex-viz) companion binds its server to 127.0.0.1). No data leaves your machine. SafeSkill scan: **94/100** (code 97, content 88 β [docs/safeskill-report.json](docs/safeskill-report.json)). +Runs **100% locally** β MCP over stdio, the storage backend (SQLite file or PostgreSQL on localhost) never leaves your machine (the optional [hypermnesia-mcp-viz](https://github.com/cdeust/cortex-viz) companion binds its server to 127.0.0.1). No data leaves your machine. SafeSkill scan: **94/100** (code 97, content 88 β [docs/safeskill-report.json](docs/safeskill-report.json)). ## Privacy Policy @@ -613,7 +619,7 @@ outside any employment relationship and is not affiliated with, endorsed by, or owned by any past or present employer. It is part of the ai-architect ecosystem ([zetetic-team-subagents](https://github.com/cdeust/zetetic-team-subagents), [automatised-pipeline](https://github.com/cdeust/automatised-pipeline), -[prd-spec-generator](https://github.com/cdeust/prd-spec-generator)). +[ai-architect-mcp-spec](https://github.com/cdeust/ai-architect-mcp-spec)). The neuroscience and information-retrieval algorithms encoded in this software are derived from published academic work cited in diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index dda4b680..b19dddd5 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -85,7 +85,7 @@ in; the door is the issue tracker. a hard constraint; a gigabyte-scale model breaks the runs-on-your-machine promise regardless of what it would buy in accuracy. - **No re-absorption of the visualization stack.** It lives in - [cortex-viz](https://github.com/cdeust/cortex-viz) and reads this store + [hypermnesia-mcp-viz](https://github.com/cdeust/cortex-viz) and reads this store read-only; Cortex stays a memory engine. - **No backward-compatibility shims.** Format changes ship as one-shot migrations, per the standing rule in [CLAUDE.md](../CLAUDE.md). diff --git a/docs/api-reference.md b/docs/api-reference.md index 445b66a6..330ef92b 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -92,8 +92,8 @@ Incremental profile update after a session ends. Appends to the rolling session --- > **Moved out of Cortex.** `get_methodology_graph` and `open_visualization` -> were extracted to the companion [cortex-viz](https://github.com/cdeust/cortex-viz) -> MCP in v3.21.0 and are no longer registered here. Install cortex-viz to get +> were extracted to the companion [hypermnesia-mcp-viz](https://github.com/cdeust/cortex-viz) +> MCP in v3.21.0 and are no longer registered here. Install hypermnesia-mcp-viz to get > them back; their schemas are documented in that repository. ### `explore_features` diff --git a/docs/codex-plugin.md b/docs/codex-plugin.md index 2f465866..b77f2896 100644 --- a/docs/codex-plugin.md +++ b/docs/codex-plugin.md @@ -22,33 +22,49 @@ the active working directory. Add the Cortex repository marketplace and install the plugin: ```bash -uv tool install "hypermnesia-mcp[sqlite]" codex plugin marketplace add cdeust/Cortex codex plugin add hypermnesia-mcp-codex@cortex-codex-plugins ``` Restart the ChatGPT desktop app and start a new task so Codex loads the new plugin components. The plugin uses `uvx`, so `uv` must be available on `PATH`. -The preliminary `uv tool install` is deliberate: it downloads the published -package before Codex's startup window, allowing the first plugin handshake to -reuse uv's local artifact cache. +The first launch installs both storage drivers. Cortex tries PostgreSQL first +at the configured `DATABASE_URL` (or its local `cortex` default), then falls +back to SQLite only when no explicit PostgreSQL target was supplied and the +default server is unavailable. An explicitly configured but unreachable +`DATABASE_URL` remains an error rather than silently redirecting writes. + +An optional prewarm can download the package before restarting Codex; it is a +startup optimization, not an installation prerequisite: + +```bash +uv tool install "hypermnesia-mcp[postgresql,sqlite]" +``` The bundled server declares `startup_timeout_sec: 180`. This is a bounded -startup ceiling, not a delay. On 2026-08-02, a local macOS 26.5.1 arm64 run -with uv 0.8.19 and clean `UV_CACHE_DIR` and `UV_TOOL_DIR` completed -`initialize`, `tools/list`, and `memory_stats` in 110.46 seconds with exactly -ten lean tools. A follow-up on the same machine after the tool installation -completed the same contract in 28.19 seconds. The clean `ubuntu-latest` CI -runner completed it in 23.87 seconds; CI reads the command and timeout from the -manifest itself. +startup ceiling, not a delay. On 2026-08-03, the exact two-driver command below +completed `initialize`, `tools/list`, and a real PostgreSQL-backed +`memory_stats` call in 103.84 seconds from clean `UV_CACHE_DIR` and +`UV_TOOL_DIR` directories on macOS 26.5.1 arm64 with uv 0.8.19. It exposed +exactly ten lean tools. The next offline run from that cache completed the same +contract in 2.75 seconds. CI reads the command, runtime policy, and timeout from +the manifest itself and repeats the clean-cache contract. The bundled MCP command is equivalent to: ```bash -uvx --from "hypermnesia-mcp[sqlite]" \ +env CORTEX_RUNTIME=cowork \ + uvx --from "hypermnesia-mcp[postgresql,sqlite]" \ hypermnesia-mcp --profile lean ``` +`CORTEX_RUNTIME=cowork` selects Cortex's existing DB-optional local-runtime +policy; it does not install or invoke the Cowork plugin. Claude Code remains +the primary integration, and its primary plugin manifest, hooks, agents, and +full tool profile are unchanged. The shared Claude marketplace catalog changes +only to publish `hypermnesia-mcp-viz` 3.0.0 and retain `cortex-viz` as a frozen, +nonfunctional migration shim. + This is a local plugin. It does not make Cortex available to ChatGPT web and does not expose the local memory database over the internet. diff --git a/docs/mcp-connections.example.json b/docs/mcp-connections.example.json index 279f917b..c9d41cd3 100644 --- a/docs/mcp-connections.example.json +++ b/docs/mcp-connections.example.json @@ -8,10 +8,10 @@ "env": {} }, "prd-gen": { - "_comment": "prd-spec-generator β PRD authoring + validation. Consumed by ingest_prd.", + "_comment": "ai-architect-mcp-spec β PRD authoring + validation. Consumed by ingest_prd.", "command": "node", "args": [ - "/absolute/path/to/prd-spec-generator/mcp-server/index.mjs" + "/absolute/path/to/ai-architect-mcp-spec/mcp-server/index.js" ], "env": {} } diff --git a/docs/mcp-tools.md b/docs/mcp-tools.md index 308f0347..ad6a7a02 100644 --- a/docs/mcp-tools.md +++ b/docs/mcp-tools.md @@ -88,7 +88,7 @@ upstream MCP server is configured (55 total with both present). These register only when their upstream MCP server is configured, bringing the total to 55: `ingest_codebase` + `change_impact` (automatised-pipeline) -and `ingest_prd` (prd-spec-generator). With no upstream present, exactly the +and `ingest_prd` (ai-architect-mcp-spec). With no upstream present, exactly the **52 standalone tools** above register. Driving the ai-architect pipeline end-to-end (formerly `run_pipeline`) is **not** part of this server β it lives in the automatised-pipeline MCP. @@ -103,7 +103,7 @@ read-only. | Command | What it does | Roles | |---|---|---| -| `/methodology` | Retrieves the cognitive methodology profile (via `query_methodology`) for the current working directory and offers `rebuild_profiles` / `list_domains` follow-ups, plus cortex-viz's `get_methodology_graph` when that companion MCP is installed | Any user, any session β the general entry point into a domain's profile | +| `/methodology` | Retrieves the cognitive methodology profile (via `query_methodology`) for the current working directory and offers `rebuild_profiles` / `list_domains` follow-ups, plus hypermnesia-mcp-viz's `get_methodology_graph` when that companion MCP is installed | Any user, any session β the general entry point into a domain's profile | | `/why` | Deterministic blame-path: resolves `β¦rcpt:idβ§` presence-in-context markers via the `why` tool, reports which memories were in context (never that they *caused* an answer β Pearl-rung-1 evidence only) | Anyone auditing why an answer looked the way it did | | `/preflight [symptΓ΄me]` | Runs `python -m mcp_server.doctor` (backend-aware check list) and turns the output into a dependency-ordered, copy-paste repair plan; takes an optional symptom argument to prioritize the relevant check first. Read-only β modifies no files | New users whose install doesn't work yet; support; first-deploy DevOps (issue #119) | diff --git a/docs/module-inventory.md b/docs/module-inventory.md index d783b423..db8da2e8 100644 --- a/docs/module-inventory.md +++ b/docs/module-inventory.md @@ -78,7 +78,7 @@ Treat gaps as "undocumented," not "does not exist." - `profile_assembler.py` β Profile assembly from extracted components - `blindspot_patterns.py` β Blind spot pattern definitions - `session_shape.py` β Session shape analysis -- *(graph construction β `graph_builder*.py`, `graph_quality_scorer.py` β was extracted to the standalone **cortex-viz** MCP along with the HTTP/3D visualization stack)* +- *(graph construction β `graph_builder*.py`, `graph_quality_scorer.py` β was extracted to the standalone **hypermnesia-mcp-viz** MCP along with the HTTP/3D visualization stack)* *Behavioral Interpretability:* - `sparse_dictionary.py` β Behavioral feature dictionary learning (OMP sparse coding, K-SVD) @@ -269,7 +269,7 @@ latency. MCP tool registration + composition roots. The HTTP visualization stack (galaxy/trace/wiki/knowledge/board UI) was extracted to the standalone -**cortex-viz** MCP, which reads this same store read-only. +**hypermnesia-mcp-viz** MCP, which reads this same store read-only. ## hooks/ β Session lifecycle automation diff --git a/plugins/cortex-viz-deprecated/.claude-plugin/plugin.json b/plugins/cortex-viz-deprecated/.claude-plugin/plugin.json new file mode 100644 index 00000000..76805244 --- /dev/null +++ b/plugins/cortex-viz-deprecated/.claude-plugin/plugin.json @@ -0,0 +1,16 @@ +{ + "name": "cortex-viz", + "description": "DEPRECATED β renamed to hypermnesia-mcp-viz. This frozen migration shim has no MCP server or tools; it only announces the replacement at session start.", + "version": "2.8.0", + "author": { + "name": "Clement Deust", + "email": "admin@ai-architect.tools" + }, + "homepage": "https://github.com/cdeust/cortex-viz", + "repository": "https://github.com/cdeust/cortex-viz", + "license": "MIT", + "keywords": [ + "deprecated", + "visualization" + ] +} diff --git a/plugins/cortex-viz-deprecated/hooks/hooks.json b/plugins/cortex-viz-deprecated/hooks/hooks.json new file mode 100644 index 00000000..4e22906a --- /dev/null +++ b/plugins/cortex-viz-deprecated/hooks/hooks.json @@ -0,0 +1,18 @@ +{ + "//": "Frozen deprecation shim only. It announces the marketplace rename and must never register the legacy MCP server or tools.", + "description": "Migration notice for the retired cortex-viz Claude Code plugin identity", + "hooks": { + "SessionStart": [ + { + "matcher": "startup", + "hooks": [ + { + "type": "command", + "command": "echo '[cortex-viz@cortex-plugins] DEPRECATED: the Claude Code plugin was renamed in v3.0.0. Run: claude plugin uninstall cortex-viz@cortex-plugins; claude plugin marketplace update cortex-plugins; claude plugin install hypermnesia-mcp-viz@cortex-plugins. The repository remains cdeust/cortex-viz; only the marketplace plugin identity changed.'", + "timeout": 5 + } + ] + } + ] + } +} diff --git a/plugins/hypermnesia-mcp-codex/.mcp.json b/plugins/hypermnesia-mcp-codex/.mcp.json index dd9f8bd0..258285ff 100644 --- a/plugins/hypermnesia-mcp-codex/.mcp.json +++ b/plugins/hypermnesia-mcp-codex/.mcp.json @@ -4,11 +4,14 @@ "command": "uvx", "args": [ "--from", - "hypermnesia-mcp[sqlite]", + "hypermnesia-mcp[postgresql,sqlite]", "hypermnesia-mcp", "--profile", "lean" ], + "env": { + "CORTEX_RUNTIME": "cowork" + }, "startup_timeout_sec": 180 } } diff --git a/scripts/check_marketplace_pins.py b/scripts/check_marketplace_pins.py index d0939a1b..e774f1b4 100644 --- a/scripts/check_marketplace_pins.py +++ b/scripts/check_marketplace_pins.py @@ -49,10 +49,13 @@ Path(__file__).resolve().parent.parent / ".claude-plugin" / "marketplace.json" ) API_TIMEOUT_S = 15 # source: GitHub API p99 well below; matches prior gate rev -# source: audited 2026-07-25 (Cortex PR #182 review clause 5) β the `cortex` -# deprecation shim announces the hypermnesia-mcp rename and is frozen at the -# rename release by design; advancing it would defeat its purpose. -FROZEN_PINS = {"cortex": "deprecation shim, frozen at the 4.15.0 rename release"} +# source: audited 2026-07-25 (Cortex PR #182 review clause 5) and 2026-08-04 +# (Cortex PR #351 Opus review) β each legacy identity is a notice-only shim +# frozen at its rename release; advancing one would hide the migration boundary. +FROZEN_PINS = { + "cortex": "deprecation shim, frozen at the 4.15.0 rename release", + "cortex-viz": "deprecation shim, frozen at the 2.8.0 pre-rename release", +} def parse_semver(tag: str) -> tuple[int, ...] | None: diff --git a/scripts/verify_mcp_hosts.py b/scripts/verify_mcp_hosts.py index 4c5d5d5f..5550a007 100644 --- a/scripts/verify_mcp_hosts.py +++ b/scripts/verify_mcp_hosts.py @@ -26,6 +26,7 @@ CLIENTS = ("claude-code", "gemini-cli", "codex-cli") PROFILES: tuple[Literal["full", "lean"], ...] = ("full", "lean") +STORAGE_SELECTIONS: tuple[Literal["sqlite", "auto"], ...] = ("sqlite", "auto") # source: MCP protocol revision implemented by fastmcp==3.4.5. PROTOCOL_VERSION = "2025-06-18" # source: tests_py/test_main.py standalone baseline plus its three documented @@ -48,6 +49,7 @@ class ContractCase: data_root: Path timeout: int socks_proxy_regression: bool + storage_selection: Literal["sqlite", "auto"] @property def label(self) -> str: @@ -82,15 +84,27 @@ def _frames(client_name: str) -> str: ) -def _environment(data_root: Path, *, socks_proxy_regression: bool) -> dict[str, str]: +def _environment( + data_root: Path, + *, + socks_proxy_regression: bool, + storage_selection: Literal["sqlite", "auto"] = "sqlite", +) -> dict[str, str]: env = os.environ.copy() env.update( { "CORTEX_CLAUDE_DIR": str(data_root), - "CORTEX_MEMORY_STORE_BACKEND": "sqlite", "CORTEX_MEMORY_AP_ENABLED": "0", } ) + if storage_selection == "sqlite": + env["CORTEX_MEMORY_STORE_BACKEND"] = "sqlite" + else: + # Exercise production auto-selection. In particular, do not inherit a + # repository- or runner-level SQLite override that would make a + # PostgreSQL-first smoke pass without ever attempting PostgreSQL. + env.pop("CORTEX_MEMORY_STORE_BACKEND", None) + env.pop("CORTEX_ALLOW_SQLITE_FALLBACK", None) if socks_proxy_regression: # Regression environment: FastMCP's banner-time update check used to # import SOCKS support and abort before initialize. The MCP runtime @@ -144,6 +158,7 @@ def _run_client(case: ContractCase) -> dict[int, dict[str, object]]: env=_environment( case.data_root / case.client_name / case.profile, socks_proxy_regression=case.socks_proxy_regression, + storage_selection=case.storage_selection, ), timeout=case.timeout, check=False, @@ -269,6 +284,15 @@ def main() -> int: action="store_true", help="do not inject the SOCKS regression fixture; intended for cold uvx", ) + parser.add_argument( + "--storage-selection", + choices=STORAGE_SELECTIONS, + default="sqlite", + help=( + "storage policy to exercise: explicit sqlite (default), or auto " + "for PostgreSQL-first selection with SQLite fallback" + ), + ) parser.add_argument( "command", nargs=argparse.REMAINDER, @@ -298,6 +322,7 @@ def main() -> int: data_root=Path(temp_dir), timeout=args.timeout, socks_proxy_regression=not args.allow_bootstrap_network, + storage_selection=args.storage_selection, ) count, elapsed_seconds = _verify(case) print( diff --git a/tests_py/infrastructure/test_sqlite_backend.py b/tests_py/infrastructure/test_sqlite_backend.py index 9ed4bff9..e26a7a6c 100644 --- a/tests_py/infrastructure/test_sqlite_backend.py +++ b/tests_py/infrastructure/test_sqlite_backend.py @@ -540,6 +540,38 @@ def test_no_explicit_url_cowork_falls_back_silently(self, monkeypatch, tmp_path) store.close() get_memory_settings.cache_clear() + def test_reachable_postgresql_is_preferred_over_sqlite(self, monkeypatch, tmp_path): + """A reachable default PostgreSQL target wins before SQLite fallback.""" + import mcp_server.infrastructure.memory_store as memory_store_module + from mcp_server.infrastructure.memory_config import get_memory_settings + + pg_store = object() + monkeypatch.setenv("CORTEX_RUNTIME", "cowork") + monkeypatch.setenv("CORTEX_MEMORY_STORE_BACKEND", "auto") + monkeypatch.delenv("DATABASE_URL", raising=False) + monkeypatch.delenv("CORTEX_ALLOW_SQLITE_FALLBACK", raising=False) + monkeypatch.setattr( + memory_store_module, + "_try_pg_verbose", + lambda url: (pg_store, None), + ) + monkeypatch.setattr( + memory_store_module, + "_make_sqlite", + lambda *args, **kwargs: pytest.fail("SQLite fallback was selected"), + ) + get_memory_settings.cache_clear() + + try: + assert ( + memory_store_module._construct_store( + db_path=str(tmp_path / "unused.db") + ) + is pg_store + ) + finally: + get_memory_settings.cache_clear() + def test_postgresql_mode_unreachable_still_raises_unchanged(self, monkeypatch): """(d) STORE_BACKEND=postgresql (the CLI/explicit-postgresql path) with PG unreachable must keep raising exactly as before this fix β this diff --git a/tests_py/scripts/test_check_marketplace_pins.py b/tests_py/scripts/test_check_marketplace_pins.py index 96f36043..8ab2dc05 100644 --- a/tests_py/scripts/test_check_marketplace_pins.py +++ b/tests_py/scripts/test_check_marketplace_pins.py @@ -61,6 +61,17 @@ def test_numeric_not_lexicographic(self): class TestPinBehindTag(unittest.TestCase): """The review's replay: both manifests agree AND both are stale (#67).""" + def test_legacy_publication_identities_are_explicitly_frozen(self): + self.assertEqual( + gate.FROZEN_PINS, + { + "cortex": "deprecation shim, frozen at the 4.15.0 rename release", + "cortex-viz": ( + "deprecation shim, frozen at the 2.8.0 pre-rename release" + ), + }, + ) + def test_incident_replay_both_manifests_stale_tag_ahead(self): with TemporaryDirectory() as d: root = _git_repo_with_tags(d, ["v0.7.0", "v0.8.0", "v0.8.1", "v0.8.2"]) diff --git a/tests_py/scripts/test_codex_plugin_contract.py b/tests_py/scripts/test_codex_plugin_contract.py index 950925e2..55c65acf 100644 --- a/tests_py/scripts/test_codex_plugin_contract.py +++ b/tests_py/scripts/test_codex_plugin_contract.py @@ -11,6 +11,10 @@ PLUGIN_ROOT = REPO_ROOT / "plugins/hypermnesia-mcp-codex" PLUGIN_PATH = PLUGIN_ROOT / ".codex-plugin/plugin.json" MCP_PATH = PLUGIN_ROOT / ".mcp.json" +CLAUDE_MARKETPLACE_PATH = REPO_ROOT / ".claude-plugin/marketplace.json" +VIZ_SHIM_ROOT = REPO_ROOT / "plugins/cortex-viz-deprecated" +VIZ_SHIM_PLUGIN_PATH = VIZ_SHIM_ROOT / ".claude-plugin/plugin.json" +VIZ_SHIM_HOOKS_PATH = VIZ_SHIM_ROOT / "hooks/hooks.json" def _json(path: Path) -> dict: @@ -28,6 +32,7 @@ def test_codex_plugin_is_confined_to_a_dedicated_subdirectory() -> None: assert ".agents/" in ignored assert "plugins/hypermnesia-mcp-codex/" in ignored assert "plugins/cortex-deprecated/" in ignored + assert "plugins/cortex-viz-deprecated/" in ignored def test_codex_marketplace_resolves_only_the_dedicated_plugin() -> None: @@ -66,14 +71,18 @@ def test_codex_plugin_is_mcp_only_and_uses_the_exact_lean_profile() -> None: "command": "uvx", "args": [ "--from", - "hypermnesia-mcp[sqlite]", + "hypermnesia-mcp[postgresql,sqlite]", "hypermnesia-mcp", "--profile", "lean", ], - # Measured clean-cache startup on 2026-08-02: 110.46s on macOS 26.5.1 - # arm64 with uv 0.8.19. This bounded ceiling leaves startup headroom - # without inventing a sleep or retry. + # Codex is additive, but its local storage selection has the same + # auto contract as the DB-optional sandbox surface: try PostgreSQL + # first and fall back only when no explicit DATABASE_URL was supplied. + "env": {"CORTEX_RUNTIME": "cowork"}, + # Measured clean-cache startup with both extras on 2026-08-03: 103.84s + # on macOS 26.5.1 arm64 with uv 0.8.19. This bounded ceiling leaves + # startup headroom without inventing a sleep or retry. "startup_timeout_sec": 180, } @@ -91,3 +100,75 @@ def test_codex_package_does_not_weaken_the_primary_claude_plugin() -> None: "mcp_server", ] assert "--profile" not in claude_server["args"] + + +def test_claude_marketplace_publishes_pinned_canonical_viz_identity() -> None: + marketplace = _json(CLAUDE_MARKETPLACE_PATH) + entries = {entry["name"]: entry for entry in marketplace["plugins"]} + canonical = entries["hypermnesia-mcp-viz"] + + assert canonical["version"] == "3.0.0" + assert canonical["source"] == { + "source": "github", + "repo": "cdeust/cortex-viz", + "sha": "1c1940e278979f35cdecea6146d7fb5f749907e9", + } + assert "standalone Hypermnesia MCP Viz server" in canonical["description"] + + +def test_legacy_viz_identity_is_a_frozen_nonfunctional_migration_shim() -> None: + marketplace = _json(CLAUDE_MARKETPLACE_PATH) + entries = {entry["name"]: entry for entry in marketplace["plugins"]} + legacy = entries["cortex-viz"] + plugin = _json(VIZ_SHIM_PLUGIN_PATH) + hooks = _json(VIZ_SHIM_HOOKS_PATH) + + assert legacy["version"] == "2.8.0" + assert legacy["source"] == "./plugins/cortex-viz-deprecated" + assert "nonfunctional migration shim" in legacy["description"] + assert plugin["name"] == "cortex-viz" + assert plugin["version"] == legacy["version"] + for functional_surface in ("mcpServers", "skills", "commands", "agents"): + assert functional_surface not in plugin + + assert not (VIZ_SHIM_ROOT / ".mcp.json").exists() + assert set(hooks["hooks"]) == {"SessionStart"} + notice = hooks["hooks"]["SessionStart"][0]["hooks"][0] + assert notice["type"] == "command" + assert "cortex-viz@cortex-plugins" in notice["command"] + assert "hypermnesia-mcp-viz@cortex-plugins" in notice["command"] + + +def test_readme_carries_the_complete_viz_and_spec_identity_migrations() -> None: + readme = (REPO_ROOT / "README.md").read_text() + + assert "claude plugin uninstall cortex-viz@cortex-plugins" in readme + assert "claude plugin install hypermnesia-mcp-viz@cortex-plugins" in readme + for tool in ("open_visualization", "get_methodology_graph"): + old_name = f"mcp__plugin_cortex-viz_cortex-viz__{tool}" + new_name = f"mcp__plugin_hypermnesia-mcp-viz_hypermnesia-mcp-viz__{tool}" + assert old_name in readme + assert new_name in readme + + assert "ai-architect-mcp-spec" in readme + assert "prd-spec-generator" not in readme + + +def test_current_companion_docs_use_canonical_publication_identities() -> None: + readme = (REPO_ROOT / "README.md").read_text() + assert ( + 'hypermnesia-mcp-viz' + in readme + ) + + current_docs = [ + REPO_ROOT / "docs/api-reference.md", + REPO_ROOT / "docs/mcp-connections.example.json", + REPO_ROOT / "docs/mcp-tools.md", + REPO_ROOT / "docs/module-inventory.md", + ] + for path in current_docs: + content = path.read_text() + assert "prd-spec-generator" not in content + assert "**cortex-viz** MCP" not in content + assert "Install cortex-viz" not in content diff --git a/tests_py/scripts/test_verify_mcp_hosts.py b/tests_py/scripts/test_verify_mcp_hosts.py index 57372d48..842378c1 100644 --- a/tests_py/scripts/test_verify_mcp_hosts.py +++ b/tests_py/scripts/test_verify_mcp_hosts.py @@ -4,7 +4,7 @@ import pytest -from scripts.verify_mcp_hosts import ContractError, _responses +from scripts.verify_mcp_hosts import ContractError, _environment, _responses def test_malformed_stdout_frame_is_reported_at_the_parse_boundary() -> None: @@ -28,3 +28,25 @@ def test_valid_notification_is_ignored_but_response_is_retained() -> None: assert _responses(stdout) == { 2: {"jsonrpc": "2.0", "id": 2, "result": {"tools": []}} } + + +def test_default_environment_forces_the_isolated_sqlite_fixture(tmp_path) -> None: + env = _environment(tmp_path, socks_proxy_regression=False) + + assert env["CORTEX_MEMORY_STORE_BACKEND"] == "sqlite" + + +def test_auto_environment_cannot_inherit_a_forced_sqlite_backend( + monkeypatch, tmp_path +) -> None: + monkeypatch.setenv("CORTEX_MEMORY_STORE_BACKEND", "sqlite") + monkeypatch.setenv("CORTEX_ALLOW_SQLITE_FALLBACK", "1") + + env = _environment( + tmp_path, + socks_proxy_regression=False, + storage_selection="auto", + ) + + assert "CORTEX_MEMORY_STORE_BACKEND" not in env + assert "CORTEX_ALLOW_SQLITE_FALLBACK" not in env