total-recall-brain 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/extension/background.js +13 -1
- package/extension/content-script.js +18 -1
- package/extension/lib/brain-client.js +18 -5
- package/extension/options/options.js +9 -4
- package/frontend/index.html +8 -0
- package/frontend/src/api.ts +1 -2
- package/frontend/src/pages/ChatPage.tsx +9 -6
- package/frontend/src/pages/IntegrationsPage.tsx +4 -2
- package/package.json +2 -2
- package/scaffold/.agent/skills/total-recall/SKILL.md +55 -6
- package/scaffold/.agent/skills/total-recall/memory-vault/invariants/operating-instructions.md +2 -2
- package/scaffold/.agent/skills/total-recall/skills/cli-agents/agents.yml +1 -6
- package/scaffold/.agent/skills/total-recall/skills/ssss/SKILL.md +19 -0
- package/scaffold/.agent/skills/total-recall/skills/ssss/references/ssss-spec.md +33 -5
- package/src/cli/forget.mjs +18 -12
- package/src/cli/ingest/index.mjs +3 -2
- package/src/cli/map.mjs +2 -2
- package/src/cli/rebuild.mjs +1 -1
- package/src/cli/remember.mjs +21 -11
- package/src/cli/share.mjs +7 -2
- package/src/core/append-log.mjs +131 -0
- package/src/core/clarity-rewriter.mjs +10 -6
- package/src/core/conclusion-writer.mjs +3 -2
- package/src/core/config.mjs +6 -0
- package/src/core/conflict-detector.mjs +4 -2
- package/src/core/context-compiler.mjs +412 -0
- package/src/core/daemon-loop.mjs +15 -0
- package/src/core/dream.mjs +4 -4
- package/src/core/drift-detector.mjs +3 -3
- package/src/core/embeddings.mjs +60 -10
- package/src/core/fact-seeker.mjs +70 -44
- package/src/core/import-rules.mjs +3 -2
- package/src/core/inference-engine.mjs +5 -4
- package/src/core/migrate.mjs +4 -3
- package/src/core/optimizer.mjs +6 -5
- package/src/core/parallel-context.mjs +288 -0
- package/src/core/post-mortem.mjs +4 -3
- package/src/core/research-queue.mjs +4 -3
- package/src/core/runtime.mjs +2 -2
- package/src/core/sandbox.mjs +56 -26
- package/src/core/scheduler.mjs +6 -5
- package/src/core/schema.mjs +2 -2
- package/src/core/search.mjs +167 -101
- package/src/core/surface.mjs +203 -53
- package/src/core/validated-write.mjs +100 -0
- package/src/core/vault-cache.mjs +46 -18
- package/src/core/vault.mjs +17 -29
- package/src/core/vector-field.mjs +659 -0
- package/src/core/vector-store.mjs +85 -0
- package/src/server/api.mjs +4 -3
- package/src/server/index.mjs +13 -61
- package/src/server/rest.mjs +233 -62
- package/src/server/route-manifest.json +344 -77
- package/src/server/routes/memory.mjs +85 -39
- package/src/server/routes/sessions.mjs +6 -2
- package/src/server/routes/share.mjs +9 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Total Recall — SSSS Sovereign AI OS
|
|
2
2
|
|
|
3
|
-
[](package.json)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](.github/workflows/test.yml)
|
|
6
6
|
|
package/extension/background.js
CHANGED
|
@@ -75,7 +75,7 @@ function showBadge(text, color) {
|
|
|
75
75
|
// ---------------------------------------------------------------------------
|
|
76
76
|
// Message listener (popup, content-script, sidepanel → background)
|
|
77
77
|
// ---------------------------------------------------------------------------
|
|
78
|
-
chrome.runtime.onMessage.addListener((msg,
|
|
78
|
+
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|
79
79
|
if (msg.type === 'QUERY_BRAIN') {
|
|
80
80
|
search(msg.query, msg.topK || 3)
|
|
81
81
|
.then(data => sendResponse({ memories: data.results || [] }))
|
|
@@ -96,4 +96,16 @@ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
|
|
|
96
96
|
.catch(() => sendResponse({ connected: false }));
|
|
97
97
|
return true;
|
|
98
98
|
}
|
|
99
|
+
|
|
100
|
+
if (msg.type === 'OPEN_SIDE_PANEL') {
|
|
101
|
+
const tabId = sender.tab?.id;
|
|
102
|
+
if (!chrome.sidePanel?.open || !tabId) {
|
|
103
|
+
sendResponse({ success: false, error: 'Side panel is unavailable for this tab.' });
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
chrome.sidePanel.open({ tabId })
|
|
107
|
+
.then(() => sendResponse({ success: true }))
|
|
108
|
+
.catch(err => sendResponse({ success: false, error: err.message }));
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
99
111
|
});
|
|
@@ -112,8 +112,25 @@
|
|
|
112
112
|
document.body.appendChild(pillHost);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
function isBlocked(blocklist) {
|
|
116
|
+
if (!Array.isArray(blocklist) || blocklist.length === 0) return false;
|
|
117
|
+
let host = '';
|
|
118
|
+
try {
|
|
119
|
+
host = new URL(pageContext.url).hostname.toLowerCase();
|
|
120
|
+
} catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return blocklist.some((entry) => {
|
|
124
|
+
const pattern = String(entry || '').trim().toLowerCase();
|
|
125
|
+
return pattern && (host === pattern || host.endsWith(`.${pattern}`) || pageContext.url.toLowerCase().includes(pattern));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
115
129
|
// ---- Query brain after delay ----
|
|
116
|
-
function queryBrain() {
|
|
130
|
+
async function queryBrain() {
|
|
131
|
+
const { passiveTracking = false, blocklist = [] } = await chrome.storage.sync.get(['passiveTracking', 'blocklist']);
|
|
132
|
+
if (!passiveTracking || isBlocked(blocklist)) return;
|
|
133
|
+
|
|
117
134
|
const query = pageContext.title || pageContext.url;
|
|
118
135
|
if (!query) return;
|
|
119
136
|
|
|
@@ -6,8 +6,21 @@
|
|
|
6
6
|
const DEFAULT_BRAIN_URL = 'http://127.0.0.1:3000';
|
|
7
7
|
|
|
8
8
|
async function getConfig() {
|
|
9
|
-
const
|
|
9
|
+
const [localConfig, syncConfig] = await Promise.all([
|
|
10
|
+
chrome.storage.local.get(['brainUrl', 'pat']),
|
|
11
|
+
chrome.storage.sync.get(['brainUrl', 'pat'])
|
|
12
|
+
]);
|
|
10
13
|
const pre = self.PreConfigured || {};
|
|
14
|
+
const config = {
|
|
15
|
+
brainUrl: localConfig.brainUrl || syncConfig.brainUrl,
|
|
16
|
+
pat: localConfig.pat || syncConfig.pat
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
if (syncConfig.pat && !localConfig.pat) {
|
|
20
|
+
await chrome.storage.local.set({ pat: syncConfig.pat });
|
|
21
|
+
await chrome.storage.sync.remove('pat');
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
return {
|
|
12
25
|
brainUrl: config.brainUrl || pre.brainUrl || DEFAULT_BRAIN_URL,
|
|
13
26
|
pat: config.pat || pre.pat || ''
|
|
@@ -67,13 +80,13 @@
|
|
|
67
80
|
return res.json();
|
|
68
81
|
}
|
|
69
82
|
|
|
70
|
-
// Self-heal stale storage: if preconfigured values exist,
|
|
83
|
+
// Self-heal stale storage: if preconfigured values exist, write them to extension-local storage.
|
|
71
84
|
try {
|
|
72
|
-
if (typeof chrome !== 'undefined' && chrome.storage && chrome.storage.
|
|
73
|
-
chrome.storage.
|
|
85
|
+
if (typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local) {
|
|
86
|
+
chrome.storage.local.get(['brainUrl', 'pat']).then((config) => {
|
|
74
87
|
const pre = self.PreConfigured || {};
|
|
75
88
|
if (pre.pat && (!config.pat || config.pat !== pre.pat)) {
|
|
76
|
-
chrome.storage.
|
|
89
|
+
chrome.storage.local.set({ brainUrl: pre.brainUrl, pat: pre.pat });
|
|
77
90
|
}
|
|
78
91
|
});
|
|
79
92
|
}
|
|
@@ -13,12 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
// ---- Load saved settings ----
|
|
15
15
|
async function loadSettings() {
|
|
16
|
-
const
|
|
17
|
-
'brainUrl',
|
|
18
|
-
|
|
16
|
+
const [localSettings, syncSettings] = await Promise.all([
|
|
17
|
+
chrome.storage.local.get(['brainUrl', 'pat']),
|
|
18
|
+
chrome.storage.sync.get([
|
|
19
19
|
'blocklist',
|
|
20
20
|
'captureGranularity'
|
|
21
|
+
])
|
|
21
22
|
]);
|
|
23
|
+
const settings = { ...syncSettings, ...localSettings };
|
|
22
24
|
|
|
23
25
|
const pre = self.PreConfigured || {};
|
|
24
26
|
brainUrlInput.value = settings.brainUrl || pre.brainUrl || 'http://127.0.0.1:3000';
|
|
@@ -48,9 +50,12 @@
|
|
|
48
50
|
const granularityRadio = document.querySelector('input[name="granularity"]:checked');
|
|
49
51
|
const captureGranularity = granularityRadio ? granularityRadio.value : 'minimal';
|
|
50
52
|
|
|
51
|
-
await chrome.storage.
|
|
53
|
+
await chrome.storage.local.set({
|
|
52
54
|
brainUrl: brainUrlInput.value.trim() || 'http://127.0.0.1:3000',
|
|
53
55
|
pat: patInput.value.trim(),
|
|
56
|
+
});
|
|
57
|
+
await chrome.storage.sync.remove('pat');
|
|
58
|
+
await chrome.storage.sync.set({
|
|
54
59
|
blocklist,
|
|
55
60
|
captureGranularity
|
|
56
61
|
});
|
package/frontend/index.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="description" content="Total Recall — Sovereign AI Brain Dashboard. Memory explorer, chat interface, code sandbox, and system health monitoring." />
|
|
7
7
|
<meta name="theme-color" content="#0a0a0f" />
|
|
8
|
+
<link rel="manifest" href="/manifest.json" />
|
|
8
9
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
9
10
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
10
11
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
@@ -13,5 +14,12 @@
|
|
|
13
14
|
<body>
|
|
14
15
|
<div id="root"></div>
|
|
15
16
|
<script type="module" src="/src/main.tsx"></script>
|
|
17
|
+
<script>
|
|
18
|
+
if ('serviceWorker' in navigator) {
|
|
19
|
+
window.addEventListener('load', () => {
|
|
20
|
+
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
16
24
|
</body>
|
|
17
25
|
</html>
|
package/frontend/src/api.ts
CHANGED
|
@@ -563,7 +563,7 @@ export async function resolveConflict(
|
|
|
563
563
|
|
|
564
564
|
export async function saveMemory(slug: string, node: Partial<MemoryNode>): Promise<MemoryNode> {
|
|
565
565
|
const res = await apiFetch(`${API_BASE}/api/memory/${slug}`, {
|
|
566
|
-
method: "
|
|
566
|
+
method: "PATCH",
|
|
567
567
|
headers: { "Content-Type": "application/json" },
|
|
568
568
|
body: JSON.stringify(node),
|
|
569
569
|
})
|
|
@@ -685,4 +685,3 @@ export async function fetchExtensionStatus(): Promise<{ available: boolean; conn
|
|
|
685
685
|
if (!res.ok) return { available: false, connected: false }
|
|
686
686
|
return res.json()
|
|
687
687
|
}
|
|
688
|
-
|
|
@@ -57,7 +57,10 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
|
|
|
57
57
|
|
|
58
58
|
// Model Selector state
|
|
59
59
|
const [availableModels, setAvailableModels] = useState<string[]>([])
|
|
60
|
-
const [selectedModel, setSelectedModel] = useState<string>(() =>
|
|
60
|
+
const [selectedModel, setSelectedModel] = useState<string>(() => {
|
|
61
|
+
const saved = localStorage.getItem('selectedModel');
|
|
62
|
+
return (saved && saved !== 'gemini') ? saved : 'antigravity';
|
|
63
|
+
})
|
|
61
64
|
const [selectedSubModel, setSelectedSubModel] = useState<string>(() => localStorage.getItem('selectedSubModel') || '')
|
|
62
65
|
const [geminiModels, setGeminiModels] = useState<{ id: string; displayName: string }[]>([])
|
|
63
66
|
const [showModelDropdown, setShowModelDropdown] = useState(false)
|
|
@@ -104,27 +107,27 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
|
|
|
104
107
|
.then(health => {
|
|
105
108
|
const agents = health.cli_agents && health.cli_agents.length > 0
|
|
106
109
|
? health.cli_agents
|
|
107
|
-
: ['antigravity', '
|
|
110
|
+
: ['antigravity', 'claude', 'codex'];
|
|
108
111
|
setAvailableModels(agents);
|
|
109
112
|
|
|
110
113
|
const saved = localStorage.getItem('selectedModel');
|
|
111
114
|
if (saved && agents.includes(saved)) {
|
|
112
115
|
setSelectedModel(saved);
|
|
113
116
|
} else {
|
|
114
|
-
const defaultAgent = agents.includes('
|
|
117
|
+
const defaultAgent = agents.includes('antigravity') ? 'antigravity' : agents[0];
|
|
115
118
|
setSelectedModel(defaultAgent);
|
|
116
119
|
localStorage.setItem('selectedModel', defaultAgent);
|
|
117
120
|
}
|
|
118
121
|
})
|
|
119
122
|
.catch(() => {
|
|
120
|
-
const agents = ['antigravity', '
|
|
123
|
+
const agents = ['antigravity', 'claude', 'codex'];
|
|
121
124
|
setAvailableModels(agents);
|
|
122
125
|
const saved = localStorage.getItem('selectedModel');
|
|
123
126
|
if (saved && agents.includes(saved)) {
|
|
124
127
|
setSelectedModel(saved);
|
|
125
128
|
} else {
|
|
126
|
-
setSelectedModel('
|
|
127
|
-
localStorage.setItem('selectedModel', '
|
|
129
|
+
setSelectedModel('antigravity');
|
|
130
|
+
localStorage.setItem('selectedModel', 'antigravity');
|
|
128
131
|
}
|
|
129
132
|
})
|
|
130
133
|
|
|
@@ -391,10 +391,12 @@ export default function IntegrationsPage() {
|
|
|
391
391
|
)
|
|
392
392
|
|
|
393
393
|
if (matchingKey) {
|
|
394
|
-
if (matchingKey.hit_count > 0) {
|
|
394
|
+
if (matchingKey.hit_count > 0 || preset.id === 'antigravity') {
|
|
395
395
|
const lastUsedStr = matchingKey.last_used_at
|
|
396
396
|
? ` (Active ${new Date(matchingKey.last_used_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })})`
|
|
397
|
-
: ''
|
|
397
|
+
: preset.id === 'antigravity'
|
|
398
|
+
? ' (Active Now)'
|
|
399
|
+
: ''
|
|
398
400
|
statusBadge = (
|
|
399
401
|
<span style={{
|
|
400
402
|
display: 'inline-flex',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "total-recall-brain",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Sovereign AI system — database-free, SSSS-powered personal intelligence engine deployable to any POSIX host.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"local-llm"
|
|
51
51
|
],
|
|
52
52
|
"author": "gregiteen",
|
|
53
|
-
"license": "
|
|
53
|
+
"license": "MIT",
|
|
54
54
|
"bugs": {
|
|
55
55
|
"url": "https://github.com/gregiteen/total-recall/issues"
|
|
56
56
|
},
|
|
@@ -26,9 +26,10 @@ You MUST actively reference and apply this skill under the following specific ru
|
|
|
26
26
|
|
|
27
27
|
### 3. When searching for complex domain knowledge or general facts
|
|
28
28
|
* **Trigger**: When you need to retrieve deep factual information (e.g. from the `facts/` category) or conceptual domain structures (e.g. from `concepts/`) that are not present in your active instruction files.
|
|
29
|
-
* **Action**: Use the
|
|
30
|
-
* **
|
|
31
|
-
* **
|
|
29
|
+
* **Action**: Use the semantic/lexical hybrid search engine (via the local `recall` command, or `/api/memory/search/semantic` endpoint) along with regular text search (e.g., grep):
|
|
30
|
+
* **Hybrid Search**: Blends cosine-similarity vector search and lexical density TF-IDF keyword matching using Reciprocal Rank Fusion (RRF). This blends intent-based semantic matching with exact keyword accuracy.
|
|
31
|
+
* **Hierarchical Parent-Child Search**: Memory node bodies are chunked and indexed as children. The vector store searches both the parent node and child chunks, returning matches based on maximum similarity.
|
|
32
|
+
* **Regular Text Search**: Use grep to locate exact configurations, literal keys, or symbols.
|
|
32
33
|
|
|
33
34
|
### 4. When a topic requires deep, structured domain learning and mastery
|
|
34
35
|
* **Trigger**: When you encounter a complex architectural topic, a deep conceptual system, or a technical domain where you need to acquire deep mastery to proceed effectively.
|
|
@@ -37,7 +38,7 @@ You MUST actively reference and apply this skill under the following specific ru
|
|
|
37
38
|
|
|
38
39
|
### 5. When you modify, add, or delete files in the memory vault
|
|
39
40
|
* **Trigger**: Immediately after performing any memory node writes.
|
|
40
|
-
* **Action**: Rebuild the instruction shims by sending a POST request to `/api/vault/compile`.
|
|
41
|
+
* **Action**: Rebuild the instruction shims. If using CLI commands (`npx total-recall remember` / `forget`), recompilation runs automatically in the background (asynchronously via detached subprocesses) to minimize latency. If editing vault files directly, trigger manual compilation by sending a POST request to `/api/vault/compile` or running `npx total-recall compile`.
|
|
41
42
|
|
|
42
43
|
### 6. When troubleshooting connections, port blocks, or sync errors
|
|
43
44
|
* **Trigger**: If the REST server is unreachable, ports are blocked, or the upstream sync tool encounters errors.
|
|
@@ -48,12 +49,12 @@ You MUST actively reference and apply this skill under the following specific ru
|
|
|
48
49
|
## ⚡ Core Directives for IDE Agents
|
|
49
50
|
|
|
50
51
|
### 1. Zero-Database Sovereign Integrity
|
|
51
|
-
Total Recall operates **entirely database-free**. The local filesystem is the source of truth. Every rule, pattern, decision, concept, preference, and fact exists as a plain Markdown file with semantic YAML frontmatter. Derived indexes are disposable caches. Do not look for PostgreSQL or
|
|
52
|
+
Total Recall operates **entirely database-free**. The local filesystem is the source of truth. Every rule, pattern, decision, concept, preference, and fact exists as a plain Markdown file with semantic YAML frontmatter. Derived indexes are disposable caches. While the internal Vector Store engine is pluggable and ready for native drop-in indexing engines (such as SQLite-VSS or HNSWLib), the canonical source of truth remains filesystem flat files. Do not look for PostgreSQL or traditional SQL databases.
|
|
52
53
|
|
|
53
54
|
### 2. Precise Tool & API Selection Heuristics
|
|
54
55
|
When interacting with the system, choose your interfaces based on the following:
|
|
55
56
|
* **Local Skills**: Use local skill packages (located in `.agent/skills/`) for complex workspace tasks, testing, and formatting. If a local skill has custom helper scripts, ALWAYS invoke them via your shell command tool instead of running raw standard commands.
|
|
56
|
-
* **Total Recall Brain (MANDATORY)**: For all semantic searches, memory retrieval, memory writes, and derived index recompilation, **
|
|
57
|
+
* **Total Recall Brain (MANDATORY)**: For all semantic searches, memory retrieval, memory writes, and derived index recompilation, **use either the local CLI suite (`npx total-recall`) or shell `curl` commands** targeting the REST API endpoints documented below.
|
|
57
58
|
|
|
58
59
|
### 3. Non-Destructive Code Modifications
|
|
59
60
|
When modifying existing rule surfaces or IDE shims (such as `.cursorrules`, `CLAUDE.md`, `GEMINI.md`, etc.), **NEVER** overwrite the developer's custom pre-existing rules. Instead, write compiled absolute invariants inside the managed comment block:
|
|
@@ -81,6 +82,54 @@ This spins up a secure local Express server (port 3000, increments dynamically i
|
|
|
81
82
|
|
|
82
83
|
---
|
|
83
84
|
|
|
85
|
+
## 🛠️ LOCAL CLI SUITE REFERENCE
|
|
86
|
+
|
|
87
|
+
For local workstation and terminal-based agent workflows, Total Recall provides a CLI command suite:
|
|
88
|
+
|
|
89
|
+
### 1. Save Memory Node
|
|
90
|
+
```bash
|
|
91
|
+
npx total-recall remember <category> "<content>" [options]
|
|
92
|
+
```
|
|
93
|
+
Save rules, preferences, corrections, and facts.
|
|
94
|
+
* **Categories**: `invariant`, `preference`, `correction`, `fact`, `concept`, `pattern`, `anti-pattern`, `decision`, `lore`.
|
|
95
|
+
* **Options**:
|
|
96
|
+
* `--global` / `--project`: Target scope. Global writes propagate to all registered projects.
|
|
97
|
+
* `--importance <1-5>`: Define relative importance.
|
|
98
|
+
* `--priority <level>`: Set priority level (`absolute`, `high`, `normal`, `low`).
|
|
99
|
+
* `--modality <type>`: Modality constraints (`must`, `must_not`, `should`, `should_not`, `descriptive`).
|
|
100
|
+
* `--slug <custom-slug>` / `--title "<custom-title>"`: Override automatic identifiers.
|
|
101
|
+
* `--expires <duration>`: Set expiration lifespan (e.g. `7d`, `2w`, `6h`, `3m`).
|
|
102
|
+
* *Note*: Spawns an asynchronous background surface compile process immediately on execution to avoid synchronous blockages.
|
|
103
|
+
|
|
104
|
+
### 2. Delete Memory Node
|
|
105
|
+
```bash
|
|
106
|
+
npx total-recall forget <slug> [options]
|
|
107
|
+
```
|
|
108
|
+
Delete a memory node by slug.
|
|
109
|
+
* **Options**:
|
|
110
|
+
* `--global` / `--project`: Scope layers. If omitted, checks project first, then global.
|
|
111
|
+
* `--no-compile`: Skip automatic background recompilation.
|
|
112
|
+
* *Note*: Spawns an asynchronous background surface compile process immediately on execution.
|
|
113
|
+
|
|
114
|
+
### 3. Recall / Hybrid Search
|
|
115
|
+
```bash
|
|
116
|
+
npx total-recall recall "<query>" [options]
|
|
117
|
+
```
|
|
118
|
+
Perform semantic/lexical hybrid search across rules, facts, and session history using Reciprocal Rank Fusion (RRF).
|
|
119
|
+
* **Options**:
|
|
120
|
+
* `--top-k, -k <number>`: Number of results (default: 5).
|
|
121
|
+
* `--category, -cat <name>`: Filter by SSSS category.
|
|
122
|
+
* `--tags, -t <list>`: Filter by tags.
|
|
123
|
+
* `--global` / `--project`: Search specific layer.
|
|
124
|
+
|
|
125
|
+
### 4. Build Memory Vault (Recompile)
|
|
126
|
+
```bash
|
|
127
|
+
npx total-recall compile
|
|
128
|
+
```
|
|
129
|
+
Synchronously rebuild the entire memory index (derived embeddings) and regenerate prompt instruction shims (such as `INSTRUCTIONS.md`, `GEMINI.md`, `AGENTS.md`, etc.).
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
84
133
|
## 🌐 DIRECT REST API REFERENCE
|
|
85
134
|
|
|
86
135
|
All requests to the Total Recall REST API must include the Bearer token in the `Authorization` header.
|
package/scaffold/.agent/skills/total-recall/memory-vault/invariants/operating-instructions.md
CHANGED
|
@@ -15,7 +15,7 @@ predicate: operate
|
|
|
15
15
|
object: memory_system
|
|
16
16
|
created: 2026-05-01T00:00:00.000Z
|
|
17
17
|
updated: 2026-05-15T00:00:00.000Z
|
|
18
|
-
last_accessed: 2026-
|
|
18
|
+
last_accessed: 2026-06-01T06:07:11.601Z
|
|
19
19
|
source:
|
|
20
20
|
type: scaffold
|
|
21
21
|
session_id: scaffold-seed
|
|
@@ -36,7 +36,7 @@ sentiment_polarity: directive_must
|
|
|
36
36
|
sentiment_target: memory_system
|
|
37
37
|
decay:
|
|
38
38
|
half_life_days: 365
|
|
39
|
-
access_count:
|
|
39
|
+
access_count: 3
|
|
40
40
|
x_temporal_context: 2026-05-26T23:05:06.525Z
|
|
41
41
|
---
|
|
42
42
|
# Total Recall Operating Protocol
|
|
@@ -5,12 +5,7 @@ agents:
|
|
|
5
5
|
priority: 1
|
|
6
6
|
enabled: true
|
|
7
7
|
exec: flag
|
|
8
|
-
|
|
9
|
-
binary: gemini
|
|
10
|
-
flags: --sandbox=false --yolo -o json
|
|
11
|
-
priority: 2
|
|
12
|
-
enabled: true
|
|
13
|
-
exec: flag
|
|
8
|
+
|
|
14
9
|
- name: claude
|
|
15
10
|
binary: claude
|
|
16
11
|
flags: --output-format json --permission-mode bypassPermissions
|
|
@@ -9,11 +9,23 @@ schema_version: 2
|
|
|
9
9
|
|
|
10
10
|
Structured Semantic Syntax System (ssss) is the core operational substrate of the Total Recall Virtual File System (VFS). This skill guides agents in inspecting, reading, and constructing SSSS-compliant memory nodes, conflict models, and derived indices.
|
|
11
11
|
|
|
12
|
+
## Spec Version
|
|
13
|
+
|
|
14
|
+
Current specification: **v0.2 — Draft** (see `references/ssss-spec.md`)
|
|
15
|
+
|
|
16
|
+
### v0.2 Changes (2026-05-30)
|
|
17
|
+
- Expanded `modality` enum: `must|must_not|should|should_not|descriptive|preference`
|
|
18
|
+
- Expanded `priority` enum: `absolute|high|normal|low` (OPTIONAL, defaults to `normal`)
|
|
19
|
+
- Added §10.1: Projection Manifest requirement with vault-hash staleness detection
|
|
20
|
+
- Added §11.3: Single canonical embedding implementation (no dual systems)
|
|
21
|
+
|
|
12
22
|
## Core Directives
|
|
13
23
|
|
|
14
24
|
1. **Schema Integrity:** Every SSSS node must strictly adhere to the frontmatter schema definitions (Modality, Category, Sentiment).
|
|
15
25
|
2. **Zero-Database Persistence:** Do not look for Postgres or SQLite. Everything lives as a git-versioned Markdown file.
|
|
16
26
|
3. **Decay and Drift Monitoring:** Use decay indicators to manage node half-lives dynamically in background ticks.
|
|
27
|
+
4. **Cached Reads:** All vault reads MUST go through `vault-cache.mjs` (`getNodes()`) — never call `loadNodes()` directly. The cache supports multi-directory (global + project) with per-directory `fs.watch` invalidation.
|
|
28
|
+
5. **Operation Contract:** All agent-generated mutations MUST flow through `processOperation()` (§6). Direct `writeNode()` calls bypass validation, idempotency, authorization, lease protection, and audit logging.
|
|
17
29
|
|
|
18
30
|
## Progressive Memory Disclosure
|
|
19
31
|
|
|
@@ -22,6 +34,13 @@ Memory flows through a 3-tier progressive hierarchy:
|
|
|
22
34
|
* **Tier 2 (Warm):** SKILL.md injects (Category-routed warm capsules).
|
|
23
35
|
* **Tier 3 (Cold):** Full memory vault (Search index files on demand).
|
|
24
36
|
|
|
37
|
+
## Performance Invariants
|
|
38
|
+
|
|
39
|
+
* `vault-cache.mjs` is the **single import point** for all node reads. The cache uses `fs.watch` auto-invalidation and supports multiple vault directories simultaneously.
|
|
40
|
+
* `walkMd()` uses `{ withFileTypes: true }` to eliminate per-file `stat()` syscalls.
|
|
41
|
+
* `deleteNode()` scans category directories directly — O(categories) not O(nodes).
|
|
42
|
+
* Surface recompilation (`triggerMutation()`) is debounced with a 2-second quiet period for batch writes.
|
|
43
|
+
|
|
25
44
|
## References
|
|
26
45
|
|
|
27
46
|
* Core SSSS specification: `references/ssss-spec.md`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SSSS — Structured Semantic Syntax System
|
|
2
2
|
|
|
3
|
-
**Specification v0.
|
|
3
|
+
**Specification v0.2 — Draft**
|
|
4
4
|
|
|
5
5
|
> This is the canonical, vendor-neutral specification for SSSS. It is the ground
|
|
6
6
|
> truth on which all SSSS implementations are built. It is intended to be vendored
|
|
@@ -198,8 +198,8 @@ The knowledge primitive. Categories: `invariants`, `patterns`, `anti-patterns`,
|
|
|
198
198
|
REQUIRED: `type`, `slug`, `category`, `title`, `status`, `schema_version`.
|
|
199
199
|
|
|
200
200
|
Knowledge-graph fields, REQUIRED when `schema_version: 2`: `confidence` (0..1),
|
|
201
|
-
`importance` (1..5), `modality` (`must|must_not|should|should_not`),
|
|
202
|
-
`predicate`, `object`, `sentiment_polarity`
|
|
201
|
+
`importance` (1..5), `modality` (`must|must_not|should|should_not|descriptive|preference`),
|
|
202
|
+
`subject`, `predicate`, `object`, `sentiment_polarity`
|
|
203
203
|
(`directive_must|directive_must_not|descriptive|preference`).
|
|
204
204
|
|
|
205
205
|
The `subject`/`predicate`/`object` triple SHOULD use stable, language-neutral
|
|
@@ -228,7 +228,8 @@ POSIX filesystems; direct writes risk partial-file corruption on crash.
|
|
|
228
228
|
```
|
|
229
229
|
|
|
230
230
|
Memory nodes in the `invariants` category additionally carry `priority: absolute`
|
|
231
|
-
and `immutable: true`.
|
|
231
|
+
and `immutable: true`. The full `priority` enum is `absolute|high|normal|low`;
|
|
232
|
+
`priority` is OPTIONAL on non-invariant categories (defaults to `normal`).
|
|
232
233
|
|
|
233
234
|
#### `skill`
|
|
234
235
|
|
|
@@ -673,6 +674,30 @@ A host that maintains projections MUST provide a means to (a) rebuild a projecti
|
|
|
673
674
|
from a vault scan, and (b) detect and repair drift between a projection and the
|
|
674
675
|
vault.
|
|
675
676
|
|
|
677
|
+
### 10.1 Projection Manifest
|
|
678
|
+
|
|
679
|
+
A host SHOULD maintain a `MANIFEST.json` (or equivalent) in the derived-artifacts
|
|
680
|
+
directory declaring each projection as disposable and recording provenance:
|
|
681
|
+
|
|
682
|
+
```jsonc
|
|
683
|
+
{
|
|
684
|
+
"type": "projection-manifest",
|
|
685
|
+
"generated_at": "2026-05-30T06:35:00Z",
|
|
686
|
+
"vault_hash": "sha256:abc123...", // content hash of the vault at build time
|
|
687
|
+
"projections": [
|
|
688
|
+
{ "file": "graph-index.jsonl", "disposable": true },
|
|
689
|
+
{ "file": "memory-layers.jsonl", "disposable": true },
|
|
690
|
+
{ "file": "embeddings.json", "disposable": true }
|
|
691
|
+
],
|
|
692
|
+
"rebuild_command": "npx total-recall compile"
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
The `vault_hash` field enables **staleness detection**: if the current vault hash
|
|
697
|
+
differs from the manifest's hash, the projections are stale and SHOULD be rebuilt.
|
|
698
|
+
This supports **incremental compilation** — a host MAY skip recompilation when the
|
|
699
|
+
hash matches, avoiding redundant I/O on unchanged vaults.
|
|
700
|
+
|
|
676
701
|
---
|
|
677
702
|
|
|
678
703
|
## 11. The Semantic Layer
|
|
@@ -713,6 +738,9 @@ disposable, never source-of-truth, fully rebuildable from the vault.
|
|
|
713
738
|
|
|
714
739
|
- It MUST record the `embedding_model` and vector `dim` that produced it. Embeddings
|
|
715
740
|
are not comparable across models; a model change REQUIRES a full reindex.
|
|
741
|
+
- A host MUST maintain exactly **one canonical embedding implementation**. Parallel
|
|
742
|
+
or duplicate embedding systems (e.g. one in JSON format and another in JSONL)
|
|
743
|
+
create consistency risks where a node is indexed in one but not the other.
|
|
716
744
|
- Retrieval SHOULD be **hybrid**: an exact/lexical pass (strong for slugs,
|
|
717
745
|
identifiers, and code) fused with a dense semantic pass (strong for meaning and
|
|
718
746
|
cross-lingual matches).
|
|
@@ -802,7 +830,7 @@ opaque ID as the slug and keep the human-readable label in `title` / `name`.
|
|
|
802
830
|
This document is versioned independently of any host and of the conformance
|
|
803
831
|
fixture set.
|
|
804
832
|
|
|
805
|
-
- The spec version is stated in the document header (currently **v0.
|
|
833
|
+
- The spec version is stated in the document header (currently **v0.2 — Draft**).
|
|
806
834
|
- Breaking changes to the file format, the type registry, or the Operation
|
|
807
835
|
Contract increment the spec version.
|
|
808
836
|
- Until **v1.0**, any version MAY introduce breaking changes.
|
package/src/cli/forget.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { resolveAgentDir, resolveBrainDir, parseLayerFlag, getBothBrains } from './agent-dir.mjs';
|
|
4
4
|
import { compileSurface } from '../core/surface.mjs';
|
|
5
|
-
import { deleteNode
|
|
5
|
+
import { deleteNode } from '../core/vault.mjs';
|
|
6
6
|
|
|
7
7
|
function printHelp() {
|
|
8
8
|
console.log(`
|
|
@@ -46,9 +46,15 @@ export default async function forget(args) {
|
|
|
46
46
|
// Check project first, then global
|
|
47
47
|
if (brains.project) {
|
|
48
48
|
const projVaultDir = path.join(brains.project.brainDir, 'memory-vault');
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
49
|
+
// Direct category scan instead of full vault load
|
|
50
|
+
if (fs.existsSync(projVaultDir)) {
|
|
51
|
+
const cats = fs.readdirSync(projVaultDir, { withFileTypes: true });
|
|
52
|
+
for (const cat of cats) {
|
|
53
|
+
if (cat.isDirectory() && fs.existsSync(path.join(projVaultDir, cat.name, `${slug}.md`))) {
|
|
54
|
+
layer = 'project';
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
if (layer === 'auto') {
|
|
@@ -76,17 +82,17 @@ export default async function forget(args) {
|
|
|
76
82
|
|
|
77
83
|
// Recompile unless --no-compile
|
|
78
84
|
if (!noCompile) {
|
|
79
|
-
console.log(' ⏳ Recompiling active memory surfaces and indexes...');
|
|
85
|
+
console.log(' ⏳ Recompiling active memory surfaces and indexes in the background...');
|
|
80
86
|
try {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
instructionsFile
|
|
87
|
+
const { spawn } = await import('node:child_process');
|
|
88
|
+
const child = spawn(process.argv[0], [process.argv[1], 'compile'], {
|
|
89
|
+
detached: true,
|
|
90
|
+
stdio: 'ignore'
|
|
86
91
|
});
|
|
87
|
-
|
|
92
|
+
child.unref();
|
|
93
|
+
console.log(' ✅ Background compilation started.');
|
|
88
94
|
} catch (err) {
|
|
89
|
-
console.warn(` ⚠️ Node deleted, but
|
|
95
|
+
console.warn(` ⚠️ Node deleted, but background recompilation spawn failed: ${err.message}`);
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
}
|
package/src/cli/ingest/index.mjs
CHANGED
|
@@ -24,7 +24,8 @@ import { parseSearchHistory } from './parsers/search-history.mjs';
|
|
|
24
24
|
import { parseChromeBookmarks } from './parsers/chrome-bookmarks.mjs';
|
|
25
25
|
import { parseGoogleKeep } from './parsers/google-keep.mjs';
|
|
26
26
|
import { parseYoutubeHistory } from './parsers/youtube-history.mjs';
|
|
27
|
-
import { writeNode
|
|
27
|
+
import { writeNode } from '../../core/vault.mjs';
|
|
28
|
+
import { getNodes } from '../../core/vault-cache.mjs';
|
|
28
29
|
import { resolveBrainDir, parseLayerFlag, getBothBrains, defaultLayerForCategory } from '../../cli/agent-dir.mjs';
|
|
29
30
|
|
|
30
31
|
/**
|
|
@@ -204,7 +205,7 @@ export async function ingestGoogleTakeout(takeoutPath, options = {}) {
|
|
|
204
205
|
// Load existing vault nodes for dedup
|
|
205
206
|
let existingNodes = [];
|
|
206
207
|
if (fs.existsSync(vaultDir)) {
|
|
207
|
-
existingNodes =
|
|
208
|
+
existingNodes = getNodes(vaultDir);
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
// Run parsers for each detected type
|
package/src/cli/map.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { resolveBrainDir, parseLayerFlag, getBothBrains } from './agent-dir.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { getNodes } from '../core/vault-cache.mjs';
|
|
5
5
|
|
|
6
6
|
function printHelp() {
|
|
7
7
|
console.log(`
|
|
@@ -68,7 +68,7 @@ export default async function map(args) {
|
|
|
68
68
|
const vaultDir = path.join(l.path, 'memory-vault');
|
|
69
69
|
if (!fs.existsSync(vaultDir)) continue;
|
|
70
70
|
|
|
71
|
-
const nodes =
|
|
71
|
+
const nodes = getNodes(vaultDir).map(n => ({ ...n, _layer: l.name }));
|
|
72
72
|
loadedLayers.push({ name: l.name, nodes });
|
|
73
73
|
totalNodesCount += nodes.length;
|
|
74
74
|
}
|
package/src/cli/rebuild.mjs
CHANGED
|
@@ -59,7 +59,7 @@ export async function runRebuild(options = {}) {
|
|
|
59
59
|
|
|
60
60
|
console.log('🏗️ Recompiling surface from canonical vault...');
|
|
61
61
|
try {
|
|
62
|
-
const stats = await compileSurface({ vaultDir, skillsDir, derivedDir, instructionsFile });
|
|
62
|
+
const stats = await compileSurface({ vaultDir, skillsDir, derivedDir, instructionsFile, force: true });
|
|
63
63
|
console.log(`✅ Processed ${stats.nodesProcessed} canonical memory nodes.`);
|
|
64
64
|
console.log(`✅ Injected memory into ${stats.skillsInjected} skill files.`);
|
|
65
65
|
console.log(`✅ Rebuilt graph-index.jsonl, memory-layers.jsonl, and skill-routes.jsonl.`);
|