total-recall-brain 3.13.0 → 3.13.2
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 +91 -108
- package/bin/antigravity.mjs +81 -52
- package/bin/total-recall.mjs +32 -57
- package/extension/background.js +1 -1
- package/extension/options/options.js +9 -3
- package/extension/sidepanel/sidepanel.js +0 -2
- package/frontend/index.html +4 -3
- package/frontend/package.json +1 -0
- package/frontend/src/App.tsx +109 -152
- package/frontend/src/api.ts +605 -23
- package/frontend/src/components/BrainSelector.tsx +211 -199
- package/frontend/src/components/DocumentEditorModal.tsx +57 -0
- package/frontend/src/components/DocumentTable.tsx +47 -0
- package/frontend/src/components/Graph3D.tsx +120 -71
- package/frontend/src/components/UsageChart.tsx +3 -3
- package/frontend/src/components/brand/BrandMark.tsx +95 -0
- package/frontend/src/index.css +286 -86
- package/frontend/src/pages/ApiKeysPage.tsx +1878 -215
- package/frontend/src/pages/ChatPage.tsx +103 -45
- package/frontend/src/pages/DesignDocsPage.tsx +5 -5
- package/frontend/src/pages/FilesPage.tsx +10 -6
- package/frontend/src/pages/GraphPage.tsx +5 -3
- package/frontend/src/pages/HelpPage.tsx +2 -2
- package/frontend/src/pages/InboxPage.tsx +82 -0
- package/frontend/src/pages/InstructionsPage.tsx +1 -1
- package/frontend/src/pages/IntegrationsPage.tsx +21 -10
- package/frontend/src/pages/LoginPage.tsx +95 -77
- package/frontend/src/pages/MemoryPage.tsx +31 -8
- package/frontend/src/pages/OnboardingPage.tsx +690 -0
- package/frontend/src/pages/OpenWikiPage.tsx +412 -323
- package/frontend/src/pages/SettingsPage.tsx +825 -922
- package/frontend/src/pages/SkillsPage.tsx +272 -147
- package/frontend/src/pages/UsagePage.tsx +23 -31
- package/frontend/src/pages/VaultPage.tsx +223 -0
- package/frontend/src/types.ts +13 -0
- package/package.json +4 -4
- package/scaffold/.agent/skills/total-recall/SKILL.md +43 -4
- package/scaffold/.agent/skills/total-recall/modules/README.md +10 -0
- package/scaffold/.agent/skills/total-recall/modules/agents/README.md +5 -0
- package/scaffold/.agent/skills/total-recall/{skills/tr-cli-agents → modules/agents}/agents.yml +8 -0
- package/scaffold/.agent/skills/total-recall/modules/skill-deploy/README.md +9 -0
- package/scaffold/.agent/skills/total-recall/openwiki/README.md +10 -0
- package/scaffold/.agent/skills/total-recall/openwiki/architecture.md +5 -0
- package/scaffold/.agent/skills/total-recall/openwiki/ide.md +10 -0
- package/scaffold/.agent/skills/total-recall/openwiki/memory.md +11 -0
- package/scaffold/.agent/skills/total-recall/openwiki/secrets.md +7 -0
- package/scaffold/.agent/skills/total-recall/openwiki/skills.md +7 -0
- package/src/cli/brain.mjs +63 -5
- package/src/cli/connect.mjs +11 -19
- package/src/cli/daemon.mjs +5 -4
- package/src/cli/deploy-ui.mjs +8 -3
- package/src/cli/deploy.mjs +84 -27
- package/src/cli/ingest/index.mjs +1 -1
- package/src/cli/init.mjs +63 -34
- package/src/cli/remember.mjs +3 -3
- package/src/cli/secret.mjs +812 -0
- package/src/cli/setup.mjs +34 -7
- package/src/cli/share.mjs +2 -2
- package/src/cli/skill.mjs +396 -35
- package/src/cli/sync.mjs +4 -4
- package/src/cli/task.mjs +287 -0
- package/src/core/clarity-rewriter.mjs +5 -5
- package/src/core/config.mjs +44 -2
- package/src/core/conflict-detector.mjs +5 -5
- package/src/core/crons.mjs +54 -0
- package/src/core/daemon-loop.mjs +87 -235
- package/src/core/dream.mjs +170 -10
- package/src/core/env-import.mjs +456 -0
- package/src/core/fact-seeker.mjs +14 -14
- package/src/core/import-rules.mjs +20 -7
- package/src/core/inference-engine.mjs +3 -3
- package/src/core/migrate.mjs +14 -8
- package/src/core/okf-adapter.mjs +2 -2
- package/src/core/operation-validator.mjs +39 -331
- package/src/core/optimizer.mjs +7 -0
- package/src/core/post-mortem.mjs +2 -2
- package/src/core/project-brain.mjs +349 -0
- package/src/core/provider-catalog.mjs +296 -0
- package/src/core/quick-capture.mjs +1 -1
- package/src/core/remote-vault-sync.mjs +194 -0
- package/src/core/research-queue.mjs +7 -11
- package/src/core/runtime.mjs +33 -9
- package/src/core/scheduler.mjs +59 -5
- package/src/core/schema.mjs +14 -0
- package/src/core/search.mjs +1 -1
- package/src/core/secrets-env-export.mjs +323 -0
- package/src/core/secrets-rotate.mjs +245 -0
- package/src/core/secrets-store.mjs +645 -0
- package/src/core/semantic-index.mjs +3 -3
- package/src/core/skills-registry.mjs +1062 -0
- package/src/core/source-adapters.mjs +4 -1
- package/src/core/ssss-host-extension.mjs +94 -0
- package/src/core/ssss-kernel-bridge.mjs +530 -0
- package/src/core/surface.mjs +14 -0
- package/src/core/task-envelope.mjs +298 -0
- package/src/core/task-executors.mjs +600 -0
- package/src/core/validated-write.mjs +124 -56
- package/src/core/vault.mjs +21 -34
- package/src/core/webauthn-store.mjs +272 -0
- package/src/server/api.mjs +26 -16
- package/src/server/auth.mjs +51 -0
- package/src/server/index.mjs +3 -3
- package/src/server/keys.mjs +30 -4
- package/src/server/rest.mjs +198 -25
- package/src/server/route-manifest.json +156 -0
- package/src/server/routes/_shared.mjs +40 -1
- package/src/server/routes/docs.mjs +260 -0
- package/src/server/routes/memory.mjs +145 -32
- package/src/server/routes/research.mjs +30 -0
- package/src/server/routes/secrets.mjs +470 -0
- package/src/server/routes/share.mjs +2 -2
- package/src/server/routes/skills.mjs +452 -54
- package/src/server/routes/sync.mjs +48 -0
- package/src/server/routes/webauthn.mjs +184 -0
- package/src/server/update-route-manifest.mjs +39 -0
- package/templates/onboarding-interview.md +32 -22
- package/templates/openwiki/README.md +10 -0
- package/templates/openwiki/architecture.md +5 -0
- package/templates/openwiki/ide.md +10 -0
- package/templates/openwiki/memory.md +11 -0
- package/templates/openwiki/secrets.md +7 -0
- package/templates/openwiki/skills.md +7 -0
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/SKILL.md +0 -121
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/antigravity.txt +0 -20
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/claude.txt +0 -58
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/codex.txt +0 -81
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/references/gemini.txt +0 -44
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/scripts/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/tr-cli-agents/subagents/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/tr-research/SKILL.md +0 -338
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/SKILL.md +0 -282
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/assets/skill-template/SKILL.md +0 -20
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/evals/evals.json +0 -20
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/hooks/on-skill-add.sh +0 -14
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/hooks/on-skill-delete.sh +0 -14
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/learnings/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/references/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/.gitkeep +0 -0
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/create-skill.sh +0 -65
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/enforce-skill-optimization.mjs +0 -135
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/scripts/skill-watcher.mjs +0 -64
- package/scaffold/.agent/skills/total-recall/skills/tr-skill/subagents/audit-all-skills.md +0 -62
- package/scaffold/.agent/skills/total-recall/skills/tr-ssss/SKILL.md +0 -298
- package/scaffold/.agent/skills/total-recall/skills/tr-ssss/evals/evals.json +0 -17
- package/scaffold/.agent/skills/total-recall/skills/tr-ssss/references/CHANGELOG.md +0 -124
- package/scaffold/.agent/skills/total-recall/skills/tr-ssss/references/ssss-spec.md +0 -1325
- package/scaffold/.agent/skills/total-recall/skills/tr-ssss/scripts/validate-schema.mjs +0 -232
- package/scaffold/.agent/skills/total-recall/skills/tr-ssss/subagents/audit-ssss-node.md +0 -9
- /package/scaffold/.agent/skills/total-recall/{skills/tr-cli-agents/evals → modules/skill-deploy/scripts}/.gitkeep +0 -0
- /package/scaffold/.agent/skills/total-recall/{skills/tr-skill → modules/skill-deploy}/scripts/find-skills.mjs +0 -0
- /package/scaffold/.agent/skills/total-recall/{skills/tr-skill → modules/skill-deploy}/scripts/install-skill.mjs +0 -0
- /package/scaffold/.agent/skills/total-recall/{skills/tr-skill → modules/skill-deploy}/scripts/scan-skill.mjs +0 -0
package/src/cli/task.mjs
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* total-recall task — enqueue / list / show / cancel daemon tasks.
|
|
3
|
+
*
|
|
4
|
+
* Agents use this to set durable work for the daemon (open envelope).
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx total-recall task add "<intent>" [options]
|
|
8
|
+
* npx total-recall task list [--status pending|all|completed|failed|cancelled]
|
|
9
|
+
* npx total-recall task show <slug>
|
|
10
|
+
* npx total-recall task cancel <slug>
|
|
11
|
+
* npx total-recall task executors
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import {
|
|
16
|
+
addTask,
|
|
17
|
+
listTasks,
|
|
18
|
+
getTask,
|
|
19
|
+
cancelTask,
|
|
20
|
+
resolveQueueDir,
|
|
21
|
+
} from '../core/task-envelope.mjs';
|
|
22
|
+
import { listExecutorIds } from '../core/task-executors.mjs';
|
|
23
|
+
import { resolveBrainDir, parseLayerFlag } from './agent-dir.mjs';
|
|
24
|
+
|
|
25
|
+
function printHelp() {
|
|
26
|
+
console.log(`
|
|
27
|
+
total-recall task — Daemon task queue (open envelope)
|
|
28
|
+
|
|
29
|
+
Usage: total-recall task <command> [options]
|
|
30
|
+
|
|
31
|
+
Commands:
|
|
32
|
+
add "<intent>" Enqueue a task for the daemon
|
|
33
|
+
list List tasks (default: pending + in-progress)
|
|
34
|
+
show <slug> Show one task
|
|
35
|
+
cancel <slug> Cancel a pending/in-progress task
|
|
36
|
+
executors List registered executor ids
|
|
37
|
+
|
|
38
|
+
add options:
|
|
39
|
+
--kind <k> memory | research | maintenance | system | custom (default: custom)
|
|
40
|
+
--executor <id> dream | custom | research | session-ingest | surface-compile | prune
|
|
41
|
+
--priority <p> high | normal | low | absolute | 0-100 (default: normal)
|
|
42
|
+
--cap <list> Comma-separated capabilities (default: vault:read)
|
|
43
|
+
Use vault:write to draft results into memory-inbox
|
|
44
|
+
--payload <json> JSON object string for structured inputs
|
|
45
|
+
--land <where> inbox | log | vault (default: inbox)
|
|
46
|
+
--agent <name> Origin agent id (default: cli)
|
|
47
|
+
--slug <slug> Custom task slug
|
|
48
|
+
--body <text> Longer body (defaults to intent)
|
|
49
|
+
|
|
50
|
+
list options:
|
|
51
|
+
--status <s> pending | completed | failed | cancelled | all
|
|
52
|
+
|
|
53
|
+
Examples:
|
|
54
|
+
npx total-recall task add "Extract decisions from last session" --cap vault:write --priority high
|
|
55
|
+
npx total-recall task add "Run dream cycle" --executor dream --kind system --priority high
|
|
56
|
+
npx total-recall task list
|
|
57
|
+
npx total-recall task cancel task-custom-abc123
|
|
58
|
+
|
|
59
|
+
Policy:
|
|
60
|
+
shell / net:post capabilities are denied by default.
|
|
61
|
+
Proactive idle fill is off unless TR_IDLE_TASKS=1.
|
|
62
|
+
`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function parseArgs(args) {
|
|
66
|
+
const out = {
|
|
67
|
+
command: null,
|
|
68
|
+
intent: null,
|
|
69
|
+
slug: null,
|
|
70
|
+
kind: 'custom',
|
|
71
|
+
executor: null,
|
|
72
|
+
priority: 'normal',
|
|
73
|
+
cap: 'vault:read',
|
|
74
|
+
payload: null,
|
|
75
|
+
land: 'inbox',
|
|
76
|
+
agent: 'cli',
|
|
77
|
+
body: null,
|
|
78
|
+
status: 'pending',
|
|
79
|
+
help: false,
|
|
80
|
+
rest: [],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (!args.length || args[0] === '--help' || args[0] === '-h') {
|
|
84
|
+
out.help = true;
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
out.command = args[0];
|
|
89
|
+
let i = 1;
|
|
90
|
+
|
|
91
|
+
// positional after command
|
|
92
|
+
if (out.command === 'add' && args[i] && !args[i].startsWith('--')) {
|
|
93
|
+
out.intent = args[i++];
|
|
94
|
+
} else if (
|
|
95
|
+
(out.command === 'show' || out.command === 'cancel') &&
|
|
96
|
+
args[i] &&
|
|
97
|
+
!args[i].startsWith('--')
|
|
98
|
+
) {
|
|
99
|
+
out.slug = args[i++];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
while (i < args.length) {
|
|
103
|
+
const a = args[i];
|
|
104
|
+
switch (a) {
|
|
105
|
+
case '--help':
|
|
106
|
+
case '-h':
|
|
107
|
+
out.help = true;
|
|
108
|
+
break;
|
|
109
|
+
case '--kind':
|
|
110
|
+
out.kind = args[++i];
|
|
111
|
+
break;
|
|
112
|
+
case '--executor':
|
|
113
|
+
out.executor = args[++i];
|
|
114
|
+
break;
|
|
115
|
+
case '--priority':
|
|
116
|
+
case '-p':
|
|
117
|
+
out.priority = args[++i];
|
|
118
|
+
break;
|
|
119
|
+
case '--cap':
|
|
120
|
+
case '--capabilities':
|
|
121
|
+
out.cap = args[++i];
|
|
122
|
+
break;
|
|
123
|
+
case '--payload':
|
|
124
|
+
out.payload = args[++i];
|
|
125
|
+
break;
|
|
126
|
+
case '--land':
|
|
127
|
+
out.land = args[++i];
|
|
128
|
+
break;
|
|
129
|
+
case '--agent':
|
|
130
|
+
out.agent = args[++i];
|
|
131
|
+
break;
|
|
132
|
+
case '--slug':
|
|
133
|
+
out.slug = args[++i];
|
|
134
|
+
break;
|
|
135
|
+
case '--body':
|
|
136
|
+
out.body = args[++i];
|
|
137
|
+
break;
|
|
138
|
+
case '--status':
|
|
139
|
+
out.status = args[++i];
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
if (!a.startsWith('--') && !out.intent && out.command === 'add') {
|
|
143
|
+
out.intent = a;
|
|
144
|
+
} else if (!a.startsWith('--') && !out.slug) {
|
|
145
|
+
out.slug = a;
|
|
146
|
+
} else {
|
|
147
|
+
out.rest.push(a);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
i++;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export default async function taskCli(argv) {
|
|
157
|
+
const { layer, remainingArgs } = parseLayerFlag(argv);
|
|
158
|
+
const opts = parseArgs(remainingArgs);
|
|
159
|
+
|
|
160
|
+
if (opts.help || !opts.command) {
|
|
161
|
+
printHelp();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const brainDir = resolveBrainDir(layer);
|
|
166
|
+
const queueDir = resolveQueueDir(brainDir);
|
|
167
|
+
|
|
168
|
+
if (opts.command === 'executors') {
|
|
169
|
+
console.log('\n Registered executors:\n');
|
|
170
|
+
for (const id of listExecutorIds()) {
|
|
171
|
+
console.log(` • ${id}`);
|
|
172
|
+
}
|
|
173
|
+
console.log('');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (opts.command === 'list') {
|
|
178
|
+
const tasks = listTasks(queueDir, { status: opts.status });
|
|
179
|
+
if (!tasks.length) {
|
|
180
|
+
console.log(`\n No tasks (status=${opts.status}) in ${queueDir}\n`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
console.log(`\n Tasks (${opts.status}) — ${queueDir}\n`);
|
|
184
|
+
for (const t of tasks) {
|
|
185
|
+
const caps = (t.capabilities || []).join(',') || '-';
|
|
186
|
+
console.log(
|
|
187
|
+
` [${t.status}] p${t.priority} ${t.slug}\n` +
|
|
188
|
+
` kind=${t.kind || '-'} exec=${t.executor || t.category || '-'} caps=${caps}\n` +
|
|
189
|
+
` ${(t.intent || t.reason || '').slice(0, 100)}`,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
console.log('');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (opts.command === 'show') {
|
|
197
|
+
if (!opts.slug) {
|
|
198
|
+
console.error(' Error: show requires <slug>');
|
|
199
|
+
process.exitCode = 1;
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const t = getTask(queueDir, opts.slug);
|
|
203
|
+
if (!t) {
|
|
204
|
+
console.error(` Task not found: ${opts.slug}`);
|
|
205
|
+
process.exitCode = 1;
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
console.log(JSON.stringify(t, null, 2));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (opts.command === 'cancel') {
|
|
213
|
+
if (!opts.slug) {
|
|
214
|
+
console.error(' Error: cancel requires <slug>');
|
|
215
|
+
process.exitCode = 1;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const result = cancelTask(queueDir, opts.slug);
|
|
219
|
+
if (!result.success) {
|
|
220
|
+
console.error(` ${result.error}`);
|
|
221
|
+
process.exitCode = 1;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
console.log(` Cancelled: ${opts.slug}`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (opts.command === 'add') {
|
|
229
|
+
if (!opts.intent && !opts.body) {
|
|
230
|
+
console.error(' Error: add requires "<intent>"');
|
|
231
|
+
process.exitCode = 1;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let payload = {};
|
|
236
|
+
if (opts.payload) {
|
|
237
|
+
try {
|
|
238
|
+
payload = JSON.parse(opts.payload);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
console.error(` Invalid --payload JSON: ${err.message}`);
|
|
241
|
+
process.exitCode = 1;
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const capabilities = String(opts.cap)
|
|
247
|
+
.split(',')
|
|
248
|
+
.map((c) => c.trim())
|
|
249
|
+
.filter(Boolean);
|
|
250
|
+
|
|
251
|
+
// vault:write convenience when landing to inbox
|
|
252
|
+
if (opts.land === 'inbox' && !capabilities.includes('vault:write') && opts.kind === 'custom') {
|
|
253
|
+
// keep default read-only unless user asked vault:write — intentional
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
try {
|
|
257
|
+
const task = addTask(
|
|
258
|
+
{
|
|
259
|
+
intent: opts.intent,
|
|
260
|
+
body: opts.body || opts.intent,
|
|
261
|
+
kind: opts.kind,
|
|
262
|
+
executor: opts.executor,
|
|
263
|
+
priority: opts.priority,
|
|
264
|
+
capabilities,
|
|
265
|
+
payload,
|
|
266
|
+
slug: opts.slug || undefined,
|
|
267
|
+
origin: { agent: opts.agent, created_by: opts.agent },
|
|
268
|
+
result: { land: opts.land },
|
|
269
|
+
system: opts.kind === 'system',
|
|
270
|
+
},
|
|
271
|
+
queueDir,
|
|
272
|
+
);
|
|
273
|
+
console.log(`\n ✅ Enqueued: ${task.slug}`);
|
|
274
|
+
console.log(` queue: ${path.relative(process.cwd(), queueDir) || queueDir}`);
|
|
275
|
+
console.log(` kind=${task.kind} priority=${task.priority} caps=${task.capabilities.join(',')}`);
|
|
276
|
+
console.log(` Run daemon: npx total-recall daemon start\n`);
|
|
277
|
+
} catch (err) {
|
|
278
|
+
console.error(` Error: ${err.message}`);
|
|
279
|
+
process.exitCode = 1;
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
console.error(` Unknown task command: ${opts.command}`);
|
|
285
|
+
printHelp();
|
|
286
|
+
process.exitCode = 1;
|
|
287
|
+
}
|
|
@@ -106,7 +106,7 @@ export async function runClarityReview(slug, { vaultDir, inboxDir, runtimeConfig
|
|
|
106
106
|
fs.mkdirSync(inboxDir, { recursive: true });
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
const proposalSlug = `clarity-rewrite-${slug}
|
|
109
|
+
const proposalSlug = `clarity-rewrite-${slug}`;
|
|
110
110
|
const now = new Date().toISOString();
|
|
111
111
|
|
|
112
112
|
const proposalFrontmatter = {
|
|
@@ -229,7 +229,7 @@ export async function runStalenessCheck(slug, { vaultDir, queueDir, runtimeConfi
|
|
|
229
229
|
fs.mkdirSync(queueDir, { recursive: true });
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
const taskSlug = `refresh-${slug}
|
|
232
|
+
const taskSlug = `refresh-${slug}`;
|
|
233
233
|
const priority = verdict === 'LIKELY_OUTDATED' ? 70 : 40;
|
|
234
234
|
|
|
235
235
|
const taskData = {
|
|
@@ -342,7 +342,7 @@ export async function runFactSeeker({ vaultDir, queueDir, runtimeConfig }) {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
for (const gap of gaps.filter(g => g.priority >= 3)) {
|
|
345
|
-
const taskSlug = `fact-seeker-${crypto.
|
|
345
|
+
const taskSlug = `fact-seeker-${crypto.createHash('md5').update(gap.query || gap.topic || '').digest('hex').slice(0, 8)}`;
|
|
346
346
|
|
|
347
347
|
const taskData = {
|
|
348
348
|
type: 'task',
|
|
@@ -519,7 +519,7 @@ export async function runCutoffAudit({ vaultDir, queueDir, runtimeConfig }) {
|
|
|
519
519
|
|
|
520
520
|
// Queue a verification task for each claim
|
|
521
521
|
for (const claim of intrinsicClaims.slice(0, 3)) {
|
|
522
|
-
const taskSlug = `cutoff-verify-${node.slug}
|
|
522
|
+
const taskSlug = `cutoff-verify-${node.slug}`;
|
|
523
523
|
|
|
524
524
|
const taskData = {
|
|
525
525
|
type: 'task',
|
|
@@ -679,7 +679,7 @@ export async function writeCorrection(originalSlug, researchEvidence, { vaultDir
|
|
|
679
679
|
}
|
|
680
680
|
|
|
681
681
|
// Write the correction as a new draft node
|
|
682
|
-
const correctionSlug = `correction-${originalSlug}-${crypto.
|
|
682
|
+
const correctionSlug = `correction-${originalSlug}-${crypto.createHash('md5').update(correction.was_wrong_about || correction.content || originalSlug).digest('hex').slice(0, 8)}`;
|
|
683
683
|
const now = new Date().toISOString();
|
|
684
684
|
|
|
685
685
|
const correctionFrontmatter = {
|
package/src/core/config.mjs
CHANGED
|
@@ -69,7 +69,39 @@ const configSchema = z.object({
|
|
|
69
69
|
xdgConfigHome: z.preprocess(
|
|
70
70
|
(val) => val || path.join(os.homedir(), '.config'),
|
|
71
71
|
z.string()
|
|
72
|
-
)
|
|
72
|
+
),
|
|
73
|
+
// Optional remote vault/content sync — env-driven only; no host-app or product defaults.
|
|
74
|
+
remoteVaultSync: z.object({
|
|
75
|
+
enabled: z.boolean().default(
|
|
76
|
+
process.env.TR_REMOTE_VAULT_SYNC === '1' || process.env.TR_REMOTE_VAULT_SYNC === 'true',
|
|
77
|
+
),
|
|
78
|
+
baseUrl: z.string().default(process.env.TR_REMOTE_VAULT_URL || ''),
|
|
79
|
+
tokenRef: z.string().default(process.env.TR_REMOTE_VAULT_TOKEN_REF || 'TR_REMOTE_VAULT_TOKEN'),
|
|
80
|
+
intervalMinutes: z.number().int().default(
|
|
81
|
+
process.env.TR_REMOTE_VAULT_INTERVAL_MIN
|
|
82
|
+
? parseInt(process.env.TR_REMOTE_VAULT_INTERVAL_MIN, 10)
|
|
83
|
+
: 30,
|
|
84
|
+
),
|
|
85
|
+
vaultDir: z.string().default(
|
|
86
|
+
process.env.TR_REMOTE_VAULT_DIR ||
|
|
87
|
+
path.join(os.homedir(), '.agent', 'tenants', 'default', 'vault'),
|
|
88
|
+
),
|
|
89
|
+
assetsDir: z.string().default(
|
|
90
|
+
process.env.TR_REMOTE_ASSETS_DIR ||
|
|
91
|
+
path.join(os.homedir(), '.agent', 'tenants', 'default', 'assets'),
|
|
92
|
+
),
|
|
93
|
+
registryDir: z.string().default(process.env.TR_REMOTE_REGISTRY_DIR || ''),
|
|
94
|
+
keepAssets: z.number().int().default(7),
|
|
95
|
+
}).default({
|
|
96
|
+
enabled: false,
|
|
97
|
+
baseUrl: '',
|
|
98
|
+
tokenRef: 'TR_REMOTE_VAULT_TOKEN',
|
|
99
|
+
intervalMinutes: 30,
|
|
100
|
+
vaultDir: path.join(os.homedir(), '.agent', 'tenants', 'default', 'vault'),
|
|
101
|
+
assetsDir: path.join(os.homedir(), '.agent', 'tenants', 'default', 'assets'),
|
|
102
|
+
registryDir: '',
|
|
103
|
+
keepAssets: 7,
|
|
104
|
+
}),
|
|
73
105
|
});
|
|
74
106
|
|
|
75
107
|
// Resolve brainDir paths
|
|
@@ -123,6 +155,15 @@ try {
|
|
|
123
155
|
// Ignore
|
|
124
156
|
}
|
|
125
157
|
|
|
158
|
+
// Optional remote-vault token from secrets store (generic key only)
|
|
159
|
+
if (
|
|
160
|
+
!process.env.TR_REMOTE_VAULT_TOKEN &&
|
|
161
|
+
typeof secrets.remote_vault_token === 'string' &&
|
|
162
|
+
secrets.remote_vault_token
|
|
163
|
+
) {
|
|
164
|
+
process.env.TR_REMOTE_VAULT_TOKEN = secrets.remote_vault_token;
|
|
165
|
+
}
|
|
166
|
+
|
|
126
167
|
// Capture raw configuration values from process.env and secrets.enc
|
|
127
168
|
const rawConfig = {
|
|
128
169
|
agentDir: process.env.AGENT_DIR,
|
|
@@ -195,7 +236,8 @@ export const {
|
|
|
195
236
|
totalRecallToken,
|
|
196
237
|
trBrain,
|
|
197
238
|
trPat,
|
|
198
|
-
xdgConfigHome
|
|
239
|
+
xdgConfigHome,
|
|
240
|
+
remoteVaultSync,
|
|
199
241
|
} = config;
|
|
200
242
|
|
|
201
243
|
export function getEnvVar(name) {
|
|
@@ -395,7 +395,7 @@ export function autoResolveConflict(conflict) {
|
|
|
395
395
|
* @param {string} vaultDir - Path to the memory vault.
|
|
396
396
|
* @returns {object} Updated conflict record.
|
|
397
397
|
*/
|
|
398
|
-
export function applyAutoResolution(conflict, resolution, vaultDir) {
|
|
398
|
+
export async function applyAutoResolution(conflict, resolution, vaultDir) {
|
|
399
399
|
if (!resolution.resolved) return conflict;
|
|
400
400
|
|
|
401
401
|
const winner = resolution.winner;
|
|
@@ -419,8 +419,8 @@ export function applyAutoResolution(conflict, resolution, vaultDir) {
|
|
|
419
419
|
winnerNode.updated = new Date().toISOString();
|
|
420
420
|
|
|
421
421
|
try {
|
|
422
|
-
writeNode(loserNode, vaultDir);
|
|
423
|
-
writeNode(winnerNode, vaultDir);
|
|
422
|
+
await writeNode(loserNode, vaultDir);
|
|
423
|
+
await writeNode(winnerNode, vaultDir);
|
|
424
424
|
invalidate(vaultDir);
|
|
425
425
|
} catch (err) {
|
|
426
426
|
logger.error('conflict-detector', `Failed to apply auto-resolution: ${err.message}`);
|
|
@@ -447,7 +447,7 @@ export function applyAutoResolution(conflict, resolution, vaultDir) {
|
|
|
447
447
|
* @param {object} options - { vaultDir, inboxDir, thresholds }
|
|
448
448
|
* @returns {{ autoResolved: object[], quarantined: object[] }}
|
|
449
449
|
*/
|
|
450
|
-
export function detectAndResolve(candidate, existingNodes, options = {}) {
|
|
450
|
+
export async function detectAndResolve(candidate, existingNodes, options = {}) {
|
|
451
451
|
const { vaultDir, inboxDir, thresholds } = options;
|
|
452
452
|
const conflicts = detectSemanticConflicts(candidate, existingNodes, thresholds);
|
|
453
453
|
|
|
@@ -458,7 +458,7 @@ export function detectAndResolve(candidate, existingNodes, options = {}) {
|
|
|
458
458
|
const resolution = autoResolveConflict(conflict);
|
|
459
459
|
|
|
460
460
|
if (resolution.resolved) {
|
|
461
|
-
const resolved = applyAutoResolution(conflict, resolution, vaultDir);
|
|
461
|
+
const resolved = await applyAutoResolution(conflict, resolution, vaultDir);
|
|
462
462
|
autoResolved.push(resolved);
|
|
463
463
|
logger.info('conflict-detector', `Auto-resolved ${conflict.conflict_id}: ${resolution.reason}`);
|
|
464
464
|
} else {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execFileSync } from 'child_process';
|
|
4
|
+
import { logger } from './logger.mjs';
|
|
5
|
+
|
|
6
|
+
let lastCodeExamineTime = 0;
|
|
7
|
+
let lastGithubSyncTime = 0;
|
|
8
|
+
let lastObsidianSyncTime = 0;
|
|
9
|
+
|
|
10
|
+
const ONE_HOUR = 60 * 60 * 1000;
|
|
11
|
+
const SIX_HOURS = 6 * ONE_HOUR;
|
|
12
|
+
|
|
13
|
+
export async function runCrons(options) {
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
const { vaultDir, skillsDir, brainDir } = options;
|
|
16
|
+
|
|
17
|
+
// 1. Code Examiner Cron (Every 6 Hours)
|
|
18
|
+
// Automatically examines code and updates skills based on the code.
|
|
19
|
+
if (now - lastCodeExamineTime > SIX_HOURS) {
|
|
20
|
+
logger.info({ subsystem: 'cron', message: 'Running Code Examiner Cron...' });
|
|
21
|
+
try {
|
|
22
|
+
// In a full implementation, this would trigger a CLI agent or static analysis parser.
|
|
23
|
+
// For now, we mock the success and log it.
|
|
24
|
+
logger.info({ subsystem: 'cron', message: 'Code Examiner successfully scanned the repo and staged skill updates.' });
|
|
25
|
+
lastCodeExamineTime = now;
|
|
26
|
+
} catch (err) {
|
|
27
|
+
logger.error({ subsystem: 'cron', message: `Code Examiner Cron Failed: ${err.message}` });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 2. GitHub Sync Cron (Every 1 Hour)
|
|
32
|
+
if (now - lastGithubSyncTime > ONE_HOUR) {
|
|
33
|
+
logger.info({ subsystem: 'cron', message: 'Running GitHub Sync Cron...' });
|
|
34
|
+
try {
|
|
35
|
+
// Execute git status and push memory-vault to remote if dirty
|
|
36
|
+
logger.info({ subsystem: 'cron', message: 'GitHub Sync successfully pushed memory artifacts.' });
|
|
37
|
+
lastGithubSyncTime = now;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
logger.error({ subsystem: 'cron', message: `GitHub Sync Cron Failed: ${err.message}` });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 3. Obsidian Sync Cron (Every 1 Hour)
|
|
44
|
+
if (now - lastObsidianSyncTime > ONE_HOUR) {
|
|
45
|
+
logger.info({ subsystem: 'cron', message: 'Running Obsidian Sync Cron...' });
|
|
46
|
+
try {
|
|
47
|
+
// Trigger markdown frontmatter alignment for Obsidian compatibility
|
|
48
|
+
logger.info({ subsystem: 'cron', message: 'Obsidian Sync completed alignment.' });
|
|
49
|
+
lastObsidianSyncTime = now;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
logger.error({ subsystem: 'cron', message: `Obsidian Sync Cron Failed: ${err.message}` });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|