Skip to content

Commit bac01b2

Browse files
cdeustclaude
andcommitted
release: v3.19.5 — open_visualization reuses the running server; snapshot clobber fixed
Bumps manifest + marketplace + pyproject to 3.19.5, marks the CHANGELOG section released, and adds release notes for the viz fixes (80631e5): an instance registry (~/.cache/cortex/viz-server.json) lets launch paths reuse a healthy source-current server instead of spawning a new ephemeral-port process with a cold rebuild on every call; the handler's unconditional launch_server after bootstrap (a double-spawn race) is gone; and the skeleton-snapshot write that clobbered the full snapshot (36,931 → 31 nodes) is removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 80631e5 commit bac01b2

5 files changed

Lines changed: 86 additions & 4 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
},
77
"metadata": {
88
"description": "Persistent memory and cognitive profiling plugins for Claude Code",
9-
"version": "3.19.4"
9+
"version": "3.19.5"
1010
},
1111
"plugins": [
1212
{
1313
"name": "cortex",
1414
"source": "./",
1515
"description": "Persistent memory and cognitive profiling for Claude Code — thermodynamic memory with heat/decay, intent-aware retrieval, biological plasticity, codebase intelligence, and cognitive profiling. 49 MCP tools with enriched schemas. 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.",
16-
"version": "3.19.4",
16+
"version": "3.19.5",
1717
"author": {
1818
"name": "Clement Deust",
1919
"email": "admin@ai-architect.tools"

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cortex",
33
"description": "Persistent memory for Claude Code — remembers across sessions automatically. Install and forget. Scientific retrieval backed by 41 published papers.",
4-
"version": "3.19.4",
4+
"version": "3.19.5",
55
"author": {
66
"name": "Clement Deust",
77
"email": "admin@ai-architect.tools"

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ adheres to [Semantic Versioning](https://semver.org/).
66

77
## [Unreleased]
88

9+
## [3.19.5] - 2026-06-12
10+
11+
### Fixed
12+
13+
- **`open_visualization` spawned a new server on a new port (with a cold
14+
graph rebuild) on every call, leaking ephemeral-port processes.** Two
15+
root causes: nothing recorded the running instance, and the handler
16+
ran `launch_server` unconditionally even after the bootstrap had
17+
already started a server (a double-spawn race). New
18+
`mcp_server/server/viz_instance.py` keeps an instance registry at
19+
`~/.cache/cortex/viz-server.json` (`{pid, port, started_at}`); launch
20+
paths probe it and reuse a healthy, source-current instance
21+
(source-currency compares the newest source mtime, excluding
22+
`__pycache__`). Stale instances are stopped with kill-and-wait
23+
(SIGTERM → wait → SIGKILL, reaping the instance's own zombie children)
24+
before rebinding. The handler now parses the bootstrap's `url=` line
25+
and skips `launch_server` when the bootstrap already produced a live
26+
server. Verified by smoke test: run 1 spawns and registers, run 2
27+
reuses the same pid.
28+
- **The skeleton-snapshot write clobbered the shared full graph
29+
snapshot.** The skeleton write in `http_standalone_graph.py` fed a
30+
nonexistent `/api/graph.bin` route; its only observable effects were
31+
overwriting the full snapshot (36,931 → 31 nodes) and flipping the
32+
complete-snapshot counts to `None`, forcing cold rebuilds. Removed.
33+
934
## [3.19.4] - 2026-06-12
1035

1136
### Fixed

docs/release-notes/v3.19.5.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# v3.19.5 — `open_visualization` reuses the running server; snapshot clobber fixed
2+
3+
Fifth entry in the 3.19.x reliability series. This one fixes two
4+
`cortex-visualize` defects: every `open_visualization` call spawned a brand-new
5+
server on a fresh ephemeral port with a cold graph rebuild, and a vestigial
6+
skeleton-snapshot write silently destroyed the shared full graph snapshot.
7+
8+
## What it fixes
9+
10+
### 1. New server + new port + cold rebuild on every call
11+
12+
Calling `open_visualization` twice left two (or more) servers running on
13+
different ephemeral ports (observed: `:56746`, `:57167`), each paying the full
14+
cold-start graph build. Two root causes:
15+
16+
1. **No instance record.** Nothing persisted which pid/port was already
17+
serving, so every launch path started from scratch.
18+
2. **Double-spawn race.** The handler ran `launch_server` unconditionally
19+
*after* the bootstrap had already started a server, so a single tool call
20+
could itself spawn two processes.
21+
22+
### 2. Skeleton snapshot clobbered the full snapshot
23+
24+
`http_standalone_graph.py` wrote a "skeleton" snapshot intended for an
25+
`/api/graph.bin` route that does not exist. Its only observable effects were
26+
overwriting the shared full snapshot (36,931 → 31 nodes) and flipping the
27+
complete-snapshot counts to `None` — which then forced cold rebuilds on the
28+
next launch.
29+
30+
## The fix
31+
32+
- **New `mcp_server/server/viz_instance.py`** — an instance registry at
33+
`~/.cache/cortex/viz-server.json` (`{pid, port, started_at}`):
34+
- `reusable_instance()` probes the registered server and reuses it when it
35+
is alive, responding, and *source-current* (`is_current` compares the
36+
newest source mtime, excluding `__pycache__`, against the instance start).
37+
- `kill_and_wait()` stops stale instances deterministically
38+
(SIGTERM → wait → SIGKILL), reaping the instance's own zombie children
39+
via `waitpid(WNOHANG)` so the wait cannot stall.
40+
- `http_standalone.py` registers the actually-bound port right after bind.
41+
- `http_launcher.py` consults the registry before killing/spawning, and
42+
`_kill_port` now waits for process exit instead of fire-and-forget.
43+
- `visualize_bootstrap.py` prints `ok reused pid=N url=...` on the reuse path
44+
and reports the ACTUAL bound port.
45+
- `open_visualization` handler parses the bootstrap's `url=` line, probes it,
46+
and **skips `launch_server`** when the bootstrap already produced a live
47+
server — eliminating the double-spawn race. Dead `_prepare_layout` removed.
48+
- The skeleton-snapshot write was **removed** outright (it fed a nonexistent
49+
route).
50+
51+
## Verification
52+
53+
- 30 viz tests pass (13 new in `tests_py/server/test_viz_instance.py`;
54+
handler tests made hermetic by stubbing `_find_dev_source`).
55+
- `tests_py/server/` — 63 passed; ruff clean.
56+
- Smoke test: run 1 spawned and registered pid 71693 on port 3458; run 2
57+
reused the same pid. Full snapshot intact at 45,332 nodes afterwards.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "neuro-cortex-memory"
7-
version = "3.19.4"
7+
version = "3.19.5"
88
description = "Scientifically-grounded memory system based on computational neuroscience research"
99
readme = "README.md"
1010
license = "MIT"

0 commit comments

Comments
 (0)