From 431d4ef311872365d329387254e46c9ee8e00832 Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" Date: Sat, 5 Sep 2026 22:56:41 -0700 Subject: [PATCH] Protect Persistent Mind identity through cleanup and clarify workspace controls --- .../cos/PersistentMindContextPanel.jsx | 34 ++++- .../cos/PersistentMindMaintenancePanel.jsx | 15 ++- .../cos/PersistentMindVisibilityPanel.jsx | 62 +++++---- .../PersistentMindVisibilityPanel.test.jsx | 9 +- client/src/components/cos/tabs/MindTab.jsx | 31 ++--- .../src/components/cos/tabs/MindTab.test.jsx | 75 +++++++++++ docs/features/memory-system.md | 30 +++++ server/lib/README.md | 1 + server/lib/index.js | 1 + server/lib/persistentMindCapabilities.js | 8 +- server/lib/persistentMindMemory.js | 40 ++++++ server/lib/persistentMindTrajectory.js | 5 +- server/routes/cosMindRoutes.js | 2 + server/routes/cosMindRoutes.test.js | 9 ++ server/services/cosToolRegistry.js | 25 +++- server/services/cosToolRegistry.test.js | 12 ++ server/services/memory.js | 11 +- server/services/memory.test.js | 12 ++ server/services/memoryDB.db.test.js | 16 +++ server/services/memoryDB.js | 25 ++-- server/services/persistentMindAdapter.js | 46 +++++-- server/services/persistentMindAdapter.test.js | 42 +++++- server/services/persistentMindContext.js | 127 +++++++++++------- server/services/persistentMindContext.test.js | 59 +++++++- server/services/persistentMindMaintenance.js | 2 + .../persistentMindMaintenance.test.js | 3 +- .../services/persistentMindTaskCapability.js | 2 +- .../persistentMindTaskCapability.test.js | 13 ++ server/services/persistentMindVisibility.js | 2 +- .../persistentMindWorkspacePreflight.js | 15 ++- .../persistentMindWorkspacePreflight.test.js | 25 ++++ 31 files changed, 611 insertions(+), 148 deletions(-) create mode 100644 server/lib/persistentMindMemory.js diff --git a/client/src/components/cos/PersistentMindContextPanel.jsx b/client/src/components/cos/PersistentMindContextPanel.jsx index 59a412c909..b3390f975d 100644 --- a/client/src/components/cos/PersistentMindContextPanel.jsx +++ b/client/src/components/cos/PersistentMindContextPanel.jsx @@ -5,7 +5,7 @@ import BrailleSpinner from '../BrailleSpinner'; import Banner from '../ui/Banner'; const EMPTY_MEMORY = { - content: '', summary: '', type: 'observation', category: 'other', tags: [], importance: 0.5, + content: '', summary: '', type: 'observation', category: 'other', tags: [], importance: 0.5, protection: 'standard', }; const promptDraft = (data) => ({ @@ -118,7 +118,7 @@ export default function PersistentMindContextPanel({ view = 'all', refreshKey = {view !== 'context' &&

-

Memories created by the persistent mind and memories added here enter its bounded context automatically. You can edit them here at any time.

+

Memories created by the persistent mind and memories added here enter its bounded context automatically. Core identity and important memories survive cleanup and receive priority in bounded context. Existing memories are standard until explicitly protected; an importance score alone does not protect them.

@@ -151,6 +151,19 @@ export default function PersistentMindContextPanel({ view = 'all', refreshKey = ); } +function MemoryProtectionSelect({ id, value, onChange, disabled }) { + return ( + + ); +} + function MemoryCreator({ onCreated }) { const id = useId(); const [draft, setDraft] = useState(EMPTY_MEMORY); @@ -180,6 +193,7 @@ function MemoryCreator({ onCreated }) { setDraft((current) => ({ ...current, content: event.target.value }))} placeholder="A stable fact, preference, decision, or context…" className="min-w-0 flex-1 rounded border border-port-border bg-port-bg px-3 py-2 text-sm text-port-text" />
+
setDraft((current) => ({ ...current, protection }))} />
{error &&

{error}

} ); @@ -192,9 +206,13 @@ function MemoryEditor({ memory, onSaved }) { summary: memory.summary || '', type: memory.type || 'observation', category: memory.category || 'other', - tags: (memory.tags || []).join(', '), + tags: (memory.tags || []).filter((tag) => !tag.startsWith('mind:')).join(', '), importance: memory.importance ?? 0.5, }); + // Omit protection from ordinary edits so a newer protection applied by the + // mind survives even when this editor still has an older context snapshot. + const [protectionOverride, setProtectionOverride] = useState(null); + const protection = protectionOverride ?? memory.protection ?? 'standard'; const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const save = async (event) => { @@ -203,17 +221,21 @@ function MemoryEditor({ memory, onSaved }) { setError(null); await api.updatePersistentMindMemory(memory.id, { ...draft, + ...(protectionOverride !== null ? { protection: protectionOverride } : {}), summary: draft.summary.trim(), tags: draft.tags.split(',').map((tag) => tag.trim()).filter(Boolean), importance: Number(draft.importance), }, { silent: true }) - .then(() => onSaved()) + .then(async () => { + setProtectionOverride(null); + await onSaved(); + }) .catch((nextError) => setError(nextError?.message || 'Could not save the memory')) .finally(() => setSaving(false)); }; return (
- {memory.summary || memory.content} · {memory.type}/{memory.category} + {memory.summary || memory.content} · {memory.type}/{memory.category}{memory.protection && memory.protection !== 'standard' && {memory.protection === 'core-identity' ? 'Core identity' : 'Important'} · Protected}