mirror of
https://github.com/samvallad33/vestige.git
synced 2026-04-25 00:36:22 +02:00
Some checks are pending
CI / Test (macos-latest) (push) Waiting to run
CI / Test (ubuntu-latest) (push) Waiting to run
CI / Release Build (aarch64-apple-darwin) (push) Blocked by required conditions
CI / Release Build (x86_64-unknown-linux-gnu) (push) Blocked by required conditions
CI / Release Build (x86_64-apple-darwin) (push) Blocked by required conditions
Test Suite / Unit Tests (push) Waiting to run
Test Suite / MCP E2E Tests (push) Waiting to run
Test Suite / User Journey Tests (push) Blocked by required conditions
Test Suite / Dashboard Build (push) Waiting to run
Test Suite / Code Coverage (push) Waiting to run
* feat(v2.0.9): Autopilot — backend event-subscriber routes 6 live events into cognitive hooks
The single architectural change that flips 14 dormant cognitive primitives
into active ones. Before this commit, Vestige's 20-event WebSocket bus had
zero backend subscribers — every emitted event flowed to the dashboard
animation layer and terminated. Cognitive modules with fully-built trigger
methods (synaptic_tagging.trigger_prp, predictive_memory.record_*,
activation_network.activate, prospective_memory.check_triggers, the 6h
auto-consolidation dreamer path) were never actually called from the bus.
New module `crates/vestige-mcp/src/autopilot.rs` spawns two tokio tasks at
startup:
1. Event subscriber — consumes the broadcast::Receiver, routes:
- MemoryCreated → synaptic_tagging.trigger_prp(CrossReference)
+ predictive_memory.record_memory_access(id, preview, tags)
- SearchPerformed → predictive_memory.record_query(q, [])
+ record_memory_access on top 10 result_ids
- MemoryPromoted → activation_network.activate(id, 0.3) spread
- MemorySuppressed → emit Rac1CascadeSwept (was declared-never-emitted)
- ImportanceScored (composite > 0.85 AND memory_id present)
→ storage.promote_memory + re-emit MemoryPromoted
- Heartbeat (memory_count > 700, 6h cooldown)
→ spawned find_duplicates sweep (rate-limited)
The loop holds the CognitiveEngine mutex only per-handler, never across
an await, so MCP tool dispatch is never starved.
2. Prospective poller — 60s tokio::interval calls
prospective_memory.check_triggers(Context { timestamp: now, .. }).
Matched intentions are logged at info! level today; v2.5 "Autonomic"
upgrades this to MCP sampling/createMessage for agent-side notifications.
ImportanceScored event gained optional `memory_id: Option<String>` field
(#[serde(default)], backward-compatible) so auto-promote has the id to
target. Both existing emit sites (server.rs tool dispatch, dashboard
handlers::score_importance) pass None because they score arbitrary content,
not stored memories — matches current semantics.
docs/VESTIGE_STATE_AND_PLAN.md §15 POST-v2.0.8 ADDENDUM records the full
three-agent audit that produced this architecture (2026-SOTA research,
active-vs-passive module audit, competitor landscape), the v2.0.9/v2.5/v2.6
ship order, and the one-line thesis: "the bottleneck was one missing
event-subscriber task; wiring it flips Vestige from memory library to
cognitive agent that acts on the host LLM."
Verified:
- cargo check --workspace clean
- cargo clippy --workspace -- -D warnings clean (let-chain on Rust 1.91+)
- cargo test -p vestige-mcp --lib 356/356 passing, 0 failed
* fix(autopilot): supervisor + dedup race + opt-out env var
Three blockers from the 5-agent v2.0.9 audit, all in autopilot.rs.
1. Supervisor loops around both tokio tasks (event subscriber + prospective
poller). Previously, if a cognitive hook panicked on a single bad memory,
the spawned task died permanently and silently — every future event lost.
Now the outer supervisor catches JoinError::is_panic(), logs the panic
with full error detail, sleeps 5s, and respawns the inner task. Turns
a permanent silent failure into a transient hiccup.
2. DedupSweepState struct replaces the bare Option<Instant> timestamp. It
tracks the in-flight JoinHandle so the next Heartbeat skips spawning a
second sweep while the first is still running. Previously, the cooldown
timestamp was set BEFORE spawning the async sweep, which allowed two
concurrent find_duplicates scans on 100k+ memory DBs where the sweep
could exceed the 6h cooldown window. is_running() drops finished handles
so a long-dead sweep doesn't block the next legitimate tick.
3. VESTIGE_AUTOPILOT_ENABLED=0 opt-out. v2.0.8 users updating in place
can preserve the passive-library contract by setting the env var to
any of {0, false, no, off}. Any other value (unset, 1, true, etc.)
enables the default v2.0.9 Autopilot behavior. spawn() early-returns
with an info! log before any task is spawned.
Audit breakdown:
- Agent 1 (internals): NO-GO → fixed (1, 2)
- Agent 2 (backward compat): NO-GO → fixed (3)
- Agent 3 (orphan cleanup): GO clean
- Agent 4 (runtime safety): GO clean
- Agent 5 (release prep): GO, procedural note logged
Verification:
- cargo check -p vestige-mcp: clean
- cargo test -p vestige-mcp --lib: 373 passed, 0 failed
- cargo clippy -p vestige-mcp --lib --bins -- -D warnings: clean
* chore(release): v2.0.9 "Autopilot"
Bump workspace + vestige-core + vestige-mcp + apps/dashboard to 2.0.9.
CHANGELOG [2.0.9] entry + README hero banner rewrite to "Autopilot".
Scope (two commits on top of v2.0.8):
- 0e9b260: 3,091 LOC orphan-code cleanup
- fe7a68c: Autopilot backend event-subscriber
- HEAD (this branch): supervisor + dedup race + opt-out env var hardening
Pure backend release — tool count unchanged (24), schema unchanged,
JSON-RPC shape unchanged, CLI flags unchanged. Only visible behavior
change is the Autopilot task running in the background, which is
VESTIGE_AUTOPILOT_ENABLED=0-gated.
Test gate: 1,223 passing / 0 failed (workspace, no-fail-fast).
Clippy: clean on vestige-mcp lib + bins with -D warnings.
Audit: 5 parallel agents (internals, backward compat, orphan cleanup,
runtime safety, release prep) — all GO after hardening commit.
98 lines
3.3 KiB
TOML
98 lines
3.3 KiB
TOML
[package]
|
|
name = "vestige-mcp"
|
|
version = "2.0.9"
|
|
edition = "2024"
|
|
description = "Cognitive memory MCP server for Claude - FSRS-6, spreading activation, synaptic tagging, 3D dashboard, and 130 years of memory research"
|
|
authors = ["samvallad33"]
|
|
license = "AGPL-3.0-only"
|
|
keywords = ["mcp", "ai", "memory", "fsrs", "neuroscience", "cognitive-science", "spaced-repetition"]
|
|
categories = ["command-line-utilities", "database"]
|
|
repository = "https://github.com/samvallad33/vestige"
|
|
|
|
[features]
|
|
default = ["embeddings", "ort-download", "vector-search"]
|
|
embeddings = ["vestige-core/embeddings"]
|
|
vector-search = ["vestige-core/vector-search"]
|
|
# Default ort backend: downloads prebuilt ONNX Runtime at build time.
|
|
# Fails on targets without prebuilts (notably x86_64-apple-darwin).
|
|
ort-download = ["embeddings", "vestige-core/ort-download"]
|
|
# Alternative ort backend: runtime-linked system libonnxruntime via dlopen.
|
|
# Required on Intel Mac and on systems with glibc < 2.38.
|
|
# Usage: cargo build --no-default-features --features ort-dynamic,vector-search
|
|
# Runtime: export ORT_DYLIB_PATH=$(brew --prefix onnxruntime)/lib/libonnxruntime.dylib
|
|
ort-dynamic = ["embeddings", "vestige-core/ort-dynamic"]
|
|
|
|
[[bin]]
|
|
name = "vestige-mcp"
|
|
path = "src/main.rs"
|
|
|
|
[[bin]]
|
|
name = "vestige-restore"
|
|
path = "src/bin/restore.rs"
|
|
|
|
[[bin]]
|
|
name = "vestige"
|
|
path = "src/bin/cli.rs"
|
|
|
|
[dependencies]
|
|
# ============================================================================
|
|
# VESTIGE CORE - The cognitive science engine
|
|
# ============================================================================
|
|
# Includes: FSRS-6, spreading activation, synaptic tagging, hippocampal indexing,
|
|
# memory states, context memory, importance signals, dreams, and more.
|
|
#
|
|
# Only `bundled-sqlite` is always on. `embeddings` and `vector-search` are
|
|
# toggled via vestige-mcp's own feature flags below so `--no-default-features`
|
|
# actually works (previously hardcoded here, which silently defeated the flag).
|
|
vestige-core = { version = "2.0.8", path = "../vestige-core", default-features = false, features = ["bundled-sqlite"] }
|
|
|
|
# ============================================================================
|
|
# MCP Server Dependencies
|
|
# ============================================================================
|
|
# Async runtime
|
|
tokio = { version = "1", features = ["full", "io-std"] }
|
|
|
|
# Serialization
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
|
|
# Date/Time
|
|
chrono = { version = "0.4", features = ["serde"] }
|
|
|
|
# UUID
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
|
|
# Constant-time comparison for auth tokens (prevents timing side-channels)
|
|
subtle = "2"
|
|
|
|
# Error handling
|
|
thiserror = "2"
|
|
anyhow = "1"
|
|
|
|
# Logging
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
|
|
|
# Platform directories
|
|
directories = "6"
|
|
|
|
# CLI
|
|
clap = { version = "4", features = ["derive"] }
|
|
colored = "3"
|
|
|
|
# SQLite (for backup WAL checkpoint)
|
|
rusqlite = { version = "0.38", features = ["bundled"] }
|
|
|
|
# Dashboard (v2.0) - HTTP server + WebSocket + embedded SvelteKit
|
|
axum = { version = "0.8", default-features = false, features = ["json", "query", "tokio", "http1", "ws"] }
|
|
tower = { version = "0.5", features = ["limit"] }
|
|
tower-http = { version = "0.6", features = ["cors", "set-header"] }
|
|
futures-util = "0.3"
|
|
open = "5"
|
|
|
|
# Embedded SvelteKit dashboard (v2.0)
|
|
include_dir = "0.7"
|
|
mime_guess = "2"
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|