From 7b464a8ba698861befb9ca2aca06a76d2e56204e Mon Sep 17 00:00:00 2001 From: Anshul Date: Sun, 10 May 2026 01:13:49 +0530 Subject: [PATCH 1/2] chore(cli): deprecate soul remember in favor of soul note (phase 2 #231) --- README.md | 1 + docs/cli-reference.md | 4 +++- src/soul_protocol/cli/main.py | 12 ++++++++++++ tests/test_cli/test_cli.py | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c0e544c..4bc315e 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ pip install -e ".[dev]" soul init "Aria" --archetype "The Compassionate Creator" soul inspect .soul/ soul status .soul/ +soul note .soul/ "User prefers concise PR summaries" --type semantic ``` ### Python diff --git a/docs/cli-reference.md b/docs/cli-reference.md index f0450be..12ef74e 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -533,7 +533,7 @@ soul export-a2a aria.soul -o card.json --url https://aria.example.com ### `soul remember` -Store a memory directly in a soul. Use this when you already know what tier the memory belongs in and don't need the cognitive pipeline to decide for you (see `soul observe` for the pipeline-driven alternative). +Deprecated alias for direct memory writes. Prefer `soul note ""`, which routes through dedup-aware reconciliation. ```bash # Semantic by default — facts the soul should know @@ -583,6 +583,8 @@ Core memory (persona and human knowledge) is not writable through `remember`. Us **Output:** A confirmation panel showing the stored text, tier, domain, importance, emotion, and memory ID. The soul is saved automatically. +**Deprecation:** `soul remember` emits a deprecation warning and points to `soul note`. Use `soul note --no-dedup` when you explicitly want legacy raw-append behavior. + --- ### `soul note` (v0.5.0, #231) diff --git a/src/soul_protocol/cli/main.py b/src/soul_protocol/cli/main.py index 41f7484..8c5bc31 100644 --- a/src/soul_protocol/cli/main.py +++ b/src/soul_protocol/cli/main.py @@ -115,6 +115,7 @@ import builtins import json import sys +import warnings import zipfile from datetime import datetime from pathlib import Path @@ -1149,6 +1150,17 @@ def remember_cmd(path, text, importance, emotion, memory_type, domain): soul remember aria.soul "Shipped v0.3" --type episodic --importance 8 soul remember aria.soul "Q3 revenue up 12%" --domain finance --importance 8 """ + warnings.warn( + "soul remember is deprecated; use 'soul note \"\"' instead. " + "Use '--no-dedup' on note for raw append behavior.", + DeprecationWarning, + stacklevel=2, + ) + console.print( + "[yellow]DeprecationWarning:[/yellow] `soul remember` is deprecated. " + "Use `soul note \"\"` (or add `--no-dedup` for raw writes)." + ) + from soul_protocol.runtime.types import MemoryType tier = MemoryType(memory_type.lower()) diff --git a/tests/test_cli/test_cli.py b/tests/test_cli/test_cli.py index 8996268..676a260 100644 --- a/tests/test_cli/test_cli.py +++ b/tests/test_cli/test_cli.py @@ -78,6 +78,7 @@ def test_remember_command(tmp_path): result = runner.invoke(cli, ["remember", soul_path, "User prefers dark mode", "-i", "7"]) assert result.exit_code == 0 + assert "deprecated" in result.output.lower() assert "Memory Stored" in result.output assert "User prefers dark mode" in result.output assert "7/10" in result.output From bca9de1eadf1d89213e70709b9e287353fafdb13 Mon Sep 17 00:00:00 2001 From: Anshul Date: Wed, 13 May 2026 22:09:30 +0530 Subject: [PATCH 2/2] chnglog changes --- CHANGELOG.md | 6 +++++- docs/cli-reference.md | 4 ++-- src/soul_protocol/cli/main.py | 6 ++++-- tests/test_cli/test_cli.py | 5 +++++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 340a552..ad74863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - **`Soul.note()` runtime + `soul note` CLI (#231 Phase 1)** — new fact-shaped writer that runs the new content through `reconcile_fact()` (Jaccard + containment) against existing entries in the matching tier before storing. Repeated calls with near-identical text collapse into SKIP / MERGE rather than appending duplicate entries the way `Soul.remember()` does. Returns `{"action": "CREATE" | "SKIP" | "MERGE", "id", "existing_id", "similarity"}` so callers can branch on the outcome. Episodic memories bypass dedup (events are unique by time). Pass `dedup=False` to fall through to the blunt `remember` path. Per-domain isolation: when `domain` is non-default, dedup is restricted to entries with the same domain (mirrors the scope used by `MemoryManager.observe()`). New CLI command `soul note ""` mirrors `soul remember` but routes through the new pipeline; flags include `--no-dedup` (force a blunt write — restores `remember` behaviour for callers that need it) and `--no-contradictions` (plumbed for the follow-up). The output panel reports the action taken (`CREATED` / `SKIPPED` / `MERGED`) with the relevant memory IDs and similarity score, colour-coded by action. Naming note: issue #231 originally proposed `soul observe`, but a pre-existing `soul observe` (cognitive interaction pipeline) owns that name; the new command ships as `soul note` to match the runtime method (`Soul.note()`). Closes the part of #231 that mattered for the captain — `soul-sync.sh` and other shell hooks were accumulating duplicates because `soul remember` had no dedup. `soul remember` is unchanged in this release; deprecation, the soul-sync.sh hook update, and the README rewrite are deferred to Phase 2 (tracked on the same issue). +### Deprecated + +- **`soul remember` CLI alias** - deprecated in favor of `soul note`. Still supported in v0.5.x, and now explicitly scheduled for removal in v0.7.0. + ### Memory update primitives - **Brain-aligned memory update primitives (#192)** — six runtime verbs gated by a prediction-error score and a one-hour reconsolidation window. `Soul.confirm(id)` refreshes activation on a verified memory (PE assumed ~0). `Soul.update(id, patch, prediction_error=0.5)` patches an entry in place when the entry was surfaced via recall within the last hour and PE sits in `[0.2, 0.85)`. `Soul.supersede(old_id, new_content, prediction_error=0.85)` writes a new entry, sets `old.superseded_by = new.id` and `new.supersedes = old.id` for two-way provenance walks; PE band locked at `>= 0.85`. `Soul.forget(id)` semantic shift — drops `MemoryEntry.retrieval_weight` to 0.05 (below the recall floor of 0.1) instead of hard-deleting; the entry stays on disk and `Soul.reinstate(id)` restores weight to 1.0. `Soul.purge(id)` is the explicit GDPR / safety hard-delete with `.soul.bak` and a `prior_payload_hash` audit entry. PE outside the verb's band raises `PredictionErrorOutOfBandError`; `update()` outside the window raises `ReconsolidationWindowClosedError`. Both errors land on `soul_protocol.runtime.exceptions`. `MemoryEntry` gains three additive fields with backward-compatible defaults: `retrieval_weight: float = 1.0`, `supersedes: str | None = None`, `prediction_error: float | None = None` — Pydantic v2 backfills them on awaken so pre-0.5 souls round-trip without migration code. `MemoryManager.recall()` accepts a `min_weight` kwarg (default 0.1) and `Soul.recall()` accepts `include_superseded=True` to surface older versions through the back-edge. `Soul.last_recall_provenance` is a sidecar dict mapping each returned id to its full supersedes chain (provenance walks back to the oldest known version). `Soul._reconsolidation_window` is an in-memory map keyed by entry id; LRU-capped at 1000; reset on awaken because the window models cellular destabilization, not persistent state. New CLI: `soul confirm`, `soul update`, `soul purge`, `soul reinstate`, `soul upgrade --to 0.5.0 [--dry-run]`. Existing `soul forget` semantics shift to weight-decay on both the `--id` and bulk-query paths; help text updated to call out the shift and point at `soul purge` for the hard-delete path. New MCP tools: `soul_confirm`, `soul_update`, `soul_supersede`, `soul_purge`, `soul_reinstate`; `soul_forget` semantics shifted with `total_deleted` → `total` in the response. Trust-chain entries: `memory.confirm`, `memory.update`, `memory.supersede` (extends 0.4.0 with `prediction_error`), `memory.forget` (extended payload), `memory.purge`, `memory.reinstate`. Spec stanzas updated: `MemoryEntry` (§4.2) and the recall contract (§4.4) gain the new fields and `min_weight` parameter, with §11 conformance row noting the additive nature. Reconsolidation-window state is implementation-specific runtime mechanism — not part of the on-disk format and not mandated at the spec layer. Full doc at `docs/memory-architecture.md` ("Memory update primitives" section); the cog-sci grounding (Nader / LeDoux on reconsolidation, Sevenster / Beckers / Kindt on PE gating, Bjork / Wimber on forgetting as inhibition, Anderson on ACT-R) lives in `docs/rfc-memory-update-primitives.md`. @@ -347,4 +351,4 @@ A third-party runtime implementing Soul Protocol in another language (or a custo - 1,189 tests, spec + runtime two-layer architecture. - MCP server (12 tools, 3 resources), 15-command CLI. - Empirical validation: 20/20 multi-judge benchmark, head-to-head vs. Mem0. -- Soul Health Score framework (7 dimensions, SHS 90.2/100). +- Soul Health Score framework (7 dimensions, SHS 90.2/100). diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 12ef74e..8061442 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -531,7 +531,7 @@ soul export-a2a aria.soul -o card.json --url https://aria.example.com --- -### `soul remember` +### `soul remember` (deprecated) Deprecated alias for direct memory writes. Prefer `soul note ""`, which routes through dedup-aware reconciliation. @@ -583,7 +583,7 @@ Core memory (persona and human knowledge) is not writable through `remember`. Us **Output:** A confirmation panel showing the stored text, tier, domain, importance, emotion, and memory ID. The soul is saved automatically. -**Deprecation:** `soul remember` emits a deprecation warning and points to `soul note`. Use `soul note --no-dedup` when you explicitly want legacy raw-append behavior. +**Deprecation:** `soul remember` emits a deprecation warning and points to `soul note`. Scheduled for removal in v0.7.0. Use `soul note --no-dedup` when you explicitly want legacy raw-append behavior. --- diff --git a/src/soul_protocol/cli/main.py b/src/soul_protocol/cli/main.py index 8c5bc31..d759414 100644 --- a/src/soul_protocol/cli/main.py +++ b/src/soul_protocol/cli/main.py @@ -1152,13 +1152,15 @@ def remember_cmd(path, text, importance, emotion, memory_type, domain): """ warnings.warn( "soul remember is deprecated; use 'soul note \"\"' instead. " - "Use '--no-dedup' on note for raw append behavior.", + "Use '--no-dedup' on note for raw append behavior. " + "Scheduled for removal in 0.7.0.", DeprecationWarning, stacklevel=2, ) console.print( "[yellow]DeprecationWarning:[/yellow] `soul remember` is deprecated. " - "Use `soul note \"\"` (or add `--no-dedup` for raw writes)." + "Use `soul note \"\"` (or add `--no-dedup` for raw writes). " + "Scheduled for removal in 0.7.0." ) from soul_protocol.runtime.types import MemoryType diff --git a/tests/test_cli/test_cli.py b/tests/test_cli/test_cli.py index 676a260..5a64cd3 100644 --- a/tests/test_cli/test_cli.py +++ b/tests/test_cli/test_cli.py @@ -83,6 +83,11 @@ def test_remember_command(tmp_path): assert "User prefers dark mode" in result.output assert "7/10" in result.output + with zipfile.ZipFile(soul_path) as zf: + semantic = json.loads(zf.read("memory/semantic.json")) + + assert any("User prefers dark mode" in entry["content"] for entry in semantic) + def test_remember_with_emotion(tmp_path): """remember command accepts an emotion tag."""